Convert macdoc into a Claude Code plugin marketplace (monorepo + marketplace dual identity)#115
Conversation
- .claude-plugin/marketplace.json: 4 plugin entries (name: macdoc) - plugins/che-word-mcp, plugins/macdoc: verbatim copies from psychquant-claude-plugins (cp -R + diff -r byte-identical audit) - plugins/che-pdf-mcp, plugins/che-pptx-mcp: new binary-backed shells (wrapper auto-download from each repo's v0.1.0 signed release) - README.md / CLAUDE.md: marketplace install guide + dual-identity note Refs #112
Push security review flagged supply-chain / unverified remote code execution in the two new auto-download wrappers. Downloads are now verified against the release .sha256 asset (fail-closed on mismatch) and must carry a valid code signature from Team 6W377FS7BS before exec. che-word-mcp wrapper (verbatim migration copy) tracked separately. Refs #112
|
Security review disposition(push review 4 findings,supply-chain / unverified RCE class):
|
Verify Report — PR #115(Round 1)Engine5 general-purpose Agents(Opus 4.8 reviewers, file-based output)+ Codex(gpt-5.5 xhigh, codex-call) AggregateFAIL — 2 blocking(+2 個 bundled in-scope fixes),5 follow-up Scope coveragePR refs: #112(body 內 #1 / #101 為 cross-repo 引用,不在 verify scope) Requirements coverage6 項要求:4 FULLY、2 PARTIALLY(R3 wrapper 驗證未達宣稱強度、R2 verbatim 主張成立但含 pre-existing 文件漂移) Findings(合併後)
Devil's Advocate 判定成立 — 推翻 logic「fail-closed 正確」的認證與 requirements 將 push-review 疑慮視為已滿足的判斷;aggregate 由「可 merge + follow-ups」降級為「修正後才可 merge」。 Process Gaps(無 — 5/5 findings 檔完整,Codex 正常完成) Next |
Verify round 1 (5 Opus reviewers + Codex) found the codesign gate bypassable: --verify --strict accepts ad-hoc signatures and the TeamIdentifier grep matches the attacker-controlled Identifier field (empirically reproduced by 3 independent parties). Replaced with a requirement-based check pinning the Apple chain + Team OU 6W377FS7BS. Also per R1 findings: - sha256 verification now MANDATORY fail-closed (was warn-and-continue) - pinned versions no longer fall back to releases/latest; sidecar records the resolved version from the effective download URL - API-free direct-download endpoints (unauthenticated api.github.com rate limit made the wrapper fragile — surfaced by E2E) - mktemp unique temp file + curl -f --proto '=https' --tlsv1.2 - che-word-mcp wrapper now uses the same hardened template (R1 HIGH-2; version intentionally NOT bumped — plugin.json version pins the binary release tag; decoupling tracked in #116) - CHANGELOG/README/CLAUDE.md wording corrected to match actual posture (DA merge precondition: no false security documentation) Upstream: CheWordMCP v3.20.0 release asset was ad-hoc signed — re-signed with Developer ID + notarized, assets replaced (che-word-mcp#165). Refs #112
R2 in-scope fixes (security M-1 / DA-1 converged + logic L1/L2 + regression LOWs): - codesign requirement now includes Developer ID marker OIDs (intermediate 6.2.6 + leaf 6.1.13) — without them any Apple cert type in the team OU (e.g. Apple Development) passed, contradicting the documented 'Developer ID' guarantee. Verified: rejects ad-hoc PoC, accepts all 3 shipping release binaries. - run_existing_or_die now removes TMP_FILE before exec (EXIT trap does not fire across exec — rejected downloads no longer leak) - dead RESOLVED_VERSION extraction removed (CDN redirect masks the tag; sidecar records the pinned version) - che-word-mcp CHANGELOG dual-Unreleased headings merged Refs #112
…112) Verify R2 convergent finding (security M-2 demo + DA corroboration + Codex P1): binaries installed by the pre-hardening wrapper — including the formerly ad-hoc CheWordMCP — carry a matching version sidecar and were never re-checked, so the hardening never cleansed existing installs. Wrappers now re-verify the Developer ID requirement on EVERY spawn; a failing existing binary is deleted and re-downloaded once (adversarial E2E: planted ad-hoc binary + matching sidecar → detected, re-downloaded, verified). Also per Codex R2 P2s: version parse tolerates JSON spacing and fails closed when plugin.json exists but version is unparseable (no silent degrade to unpinned latest); chmod/mv failures no longer fake an install; plugin README wording now states exactly what the wrapper enforces vs what the release process provides (notarization). Refs #112
Verify Report — PR #115(Round 2)Engine5 general-purpose Agents(Opus 4.8,全新一輪獨立 reviewers)+ Codex(gpt-5.5 xhigh;第一次呼叫 timeout,重試成功 — 標記為 process note 非 gap) AggregatePASS — 0 blocking。R1 的 2 個 HIGH blockers 經多方實測確認關閉;R2 新 findings 全數以 in-scope fixes 處理( R1 blockers 關閉證據(多方獨立實測)
R2 Findings(合併後)
Post-R2 fixes 的驗證方式(透明聲明)
Process Gaps(無 — R2 5/5 findings 檔完整;Codex timeout 一次後重試成功) Scope Check8+5 檔改動全數可追溯至 R1/R2 findings;untracked 結論PASS — ready to merge(merge 後:遠端 Follow-up Findings Filed (v2.72.0+ #148)
|
Refs #112
Summary
把 macdoc 變成 Claude Code plugin marketplace(與 Swift monorepo 雙身分並存):
.claude-plugin/marketplace.json—name: "macdoc",4 個 plugin entriesplugins/che-word-mcp、plugins/macdoc— 自 psychquant-claude-plugins 逐字複製(diff -rbyte-identical、git check-ignoreaudit 僅.DS_Store)plugins/che-pdf-mcp、plugins/che-pptx-mcp— 新建 binary-backed shells(v0.1.0),wrapper 自動從各 repo 首次 signed + notarized release 下載 universal binarymcp/che-pdf-mcpsubmodule bump — MCP SDKMetadata型別編譯修復(Release build broken: .image(metadata:) now requires MCP.Metadata, not [String: String] che-pdf-mcp#1)上游前置(已完成,非本 PR diff):
Verification
jqmarketplace.json schema + 4 entries ✓diff -rbyte-identical ✓claude plugin marketplace add+install che-pptx-mcp@macdoc✓(驗畢已清理)swift build && swift test:26 tests / 4 suites 全過(monorepo 不受影響)✓claude plugin marketplace add PsychQuant/macdoc— merge 後驗證Checklist
Post-merge(不在本 PR)
Generated by /idd-implement on PR path. Do NOT add a GitHub close trailer (Closes/Fixes/Resolves) — IDD discipline requires manual /idd-close after merge to enforce checklist gate + closing summary.