Skip to content

Convert macdoc into a Claude Code plugin marketplace (monorepo + marketplace dual identity)#115

Merged
kiki830621 merged 6 commits into
mainfrom
feat/112-marketplace
Jul 2, 2026
Merged

Convert macdoc into a Claude Code plugin marketplace (monorepo + marketplace dual identity)#115
kiki830621 merged 6 commits into
mainfrom
feat/112-marketplace

Conversation

@kiki830621

Copy link
Copy Markdown
Collaborator

Refs #112

Summary

把 macdoc 變成 Claude Code plugin marketplace(與 Swift monorepo 雙身分並存):

  • .claude-plugin/marketplace.jsonname: "macdoc",4 個 plugin entries
  • plugins/che-word-mcpplugins/macdoc — 自 psychquant-claude-plugins 逐字複製diff -r byte-identical、git check-ignore audit 僅 .DS_Store
  • plugins/che-pdf-mcpplugins/che-pptx-mcp新建 binary-backed shells(v0.1.0),wrapper 自動從各 repo 首次 signed + notarized release 下載 universal binary
  • README / CLAUDE.md — marketplace 安裝指引 + 遷移註記
  • mcp/che-pdf-mcp submodule bump — MCP SDK Metadata 型別編譯修復(Release build broken: .image(metadata:) now requires MCP.Metadata, not [String: String] che-pdf-mcp#1

上游前置(已完成,非本 PR diff):

Verification

  • jq marketplace.json schema + 4 entries ✓
  • 複製 shells diff -r byte-identical ✓
  • 本地 claude plugin marketplace add + install che-pptx-mcp@macdoc ✓(驗畢已清理)
  • 兩個新 shell wrapper 實際下載 release binary + MCP initialize handshake ✓
  • 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.

- .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
@kiki830621

Copy link
Copy Markdown
Collaborator Author

Security review disposition(push review 4 findings,supply-chain / unverified RCE class):

  • 8ded517 — 兩個新 wrapper(che-pdf-mcp / che-pptx-mcp)加 .sha256 比對(fail-closed)+ codesign TeamIdentifier 6W377FS7BS 硬閘後才 exec。E2E 重測通過(強迫重下載 → 驗證 → MCP handshake)。
  • che-word-mcp wrapper(byte-identical 遷移複製件、既有生產 pattern)→ Harden che-word-mcp wrapper with sha256 + code-signature verification (security follow-up from #112 push review) #116 追蹤(需 shell/binary 版本解耦才能乾淨修)。
  • 註:plugins/che-word-mcp 維持 byte-identical 的遷移驗證主張不變;hardening 只落在本 PR 新建的兩個 wrapper。

@kiki830621

Copy link
Copy Markdown
Collaborator Author

Verify Report — PR #115(Round 1)

Engine

5 general-purpose Agents(Opus 4.8 reviewers, file-based output)+ Codex(gpt-5.5 xhigh, codex-call)

Aggregate

FAIL — 2 blocking(+2 個 bundled in-scope fixes),5 follow-up

Scope coverage

PR refs: #112(body 內 #1 / #101 為 cross-repo 引用,不在 verify scope)

Requirements coverage

6 項要求:4 FULLY、2 PARTIALLY(R3 wrapper 驗證未達宣稱強度、R2 verbatim 主張成立但含 pre-existing 文件漂移)

Findings(合併後)

# Severity Finding Source Action
1 HIGH codesign gate 可繞過--verify --strict 接受 ad-hoc 簽章;grep TeamIdentifier= 被攻擊者自訂 Identifier= 欄位偽造匹配。三方獨立重現(security、DA、coordinator)。Fix:requirement-based 驗證 -R '=anchor apple generic and certificate leaf[subject.OU] = "6W377FS7BS"'(已驗證:拒 evil、收真 binary) agents:security+devils-advocate Blocking
2 HIGH che-word-mcp wrapper 完全未加固 而 README/CLAUDE/CHANGELOG 宣稱 wrappers 下載 signed binary — 文件與實際安全態勢不符(DA:false security documentation,merge precondition)。原 #116 延後理由(版本耦合)不成立:macdoc marketplace 尚未首發,複製 shell 可在首發前修正而無版本影響 agents:security+logic+regression+codex Blocking(in-PR 加固全部 3 個 wrappers)
3 MEDIUM sha256 檢查 fail-open(asset 缺失時 warn-and-continue)+ 無 curl -f(404 頁面可誤讀)+ 無 hex 格式驗證 codex+agents:security In-scope fix(併入 #1 commit)
4 MEDIUM pinned version 失敗 fallback releases/latest 破壞釘選 + sidecar 記錄錯誤版本;亦開 downgrade 面 codex+agents:security In-scope fix
5 MEDIUM 既有 binary 於 exec 前不重驗(download-time only)— 被植入的 ~/bin binary 永久信任 agents:security+codex Follow-up
6 LOW 固定 .tmp 檔名(symlink / race)+ curl 未鎖 --proto =https agents:security+codex In-scope fix
7 LOW ~/bin 全域安裝碰撞面(跨 marketplace 同名 binary) codex Follow-up
8 LOW 複製內容的文件漂移(tool counts 218+/235/145、版本 3.12/3.13.2/3.20.0)+ marketplace description 過長 codex+agents:regression Follow-up
9 LOW macdoc SKILL.md 本機路徑 codex+agents:security 已追蹤 #113
10 INFO submodule bump 被 codex 判 scope creep — rejected with rationale:為 release blocker 的文件化前置(IC comment + PR body 已載明),非 creep codex 不處理
11 INFO DA 4a/4b(swift test 未跑、install 未驗)— coordinator session 證據補正:swift test 26/26 全過、本地 marketplace add + install che-pptx-mcp@macdoc 實測成功(見 issue #112 Implementation Complete comment);遠端 add 留待 merge 後 agents:devils-advocate 證據已存在

Devil's Advocate 判定

成立 — 推翻 logic「fail-closed 正確」的認證與 requirements 將 push-review 疑慮視為已滿足的判斷;aggregate 由「可 merge + follow-ups」降級為「修正後才可 merge」。

Process Gaps

(無 — 5/5 findings 檔完整,Codex 正常完成)

Next

Blocking #1#2(含 bundled #3/#4/#6)修復後重跑 verify(Round 2)。

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
@kiki830621

kiki830621 commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator Author

Verify Report — PR #115(Round 2)

Engine

5 general-purpose Agents(Opus 4.8,全新一輪獨立 reviewers)+ Codex(gpt-5.5 xhigh;第一次呼叫 timeout,重試成功 — 標記為 process note 非 gap)

Aggregate

PASS — 0 blocking。R1 的 2 個 HIGH blockers 經多方實測確認關閉;R2 新 findings 全數以 in-scope fixes 處理(8330daa07432d1)或 triage 為 follow-up。

R1 blockers 關閉證據(多方獨立實測)

  • HIGH-1 codesign bypass:R1 的 PoC(ad-hoc + Identifier 偽造)被新 requirement 拒絕(security、DA、regression 各自重現測試);連自簽偽造 CN+OU 也被 anchor apple generic 擋下。真 release binaries 三個全過 gate。
  • HIGH-2 word wrapper:三 wrapper 為同一硬化模板(diff 實證僅名稱異)。上游 CheWordMCP v3.20.0 原為 ad-hoc 簽章(TCC-fatal 既存缺陷)— 已補簽 + notarize + 換 assets(che-word-mcp#165 closed),regression 對 live asset 實測過 gate。
  • DA 文件精準性 precondition:R2 requirements/regression 確認 CHANGELOG/README/CLAUDE.md 宣稱與實作一致。

R2 Findings(合併後)

# Severity Finding Source Action
1 MEDIUM requirement 缺 Developer ID marker OIDs — 同 team 的 Apple Development cert 可過 gate(security 與 DA 獨立收斂,各自以真 Development cert 實證) agents:security+devils-advocate Fixed 8330daa(加 OID 6.2.6 + 6.1.13;驗證:拒 Development cert / 拒 ad-hoc PoC / 收全部真 binaries)
2 P1→Fixed exec-time 不重驗:sidecar 相符的既有 binary 永不再檢 — 具體現實案例:經舊 wrapper 安裝的 ad-hoc CheWordMCP 永不被清洗(security 植入示範 + DA 佐證 + Codex P1) agents:security+devils-advocate+codex Fixed 07432d1(每次 spawn 重驗 requirement;失敗刪除重下載一次。對抗性 E2E:植入 ad-hoc + 相符 sidecar → 偵測 → 自我修復)
3 MEDIUM plugin.json 存在但 version 解析不到 → 靜默降級 latest(grep 對 JSON 空白 fragile) codex Fixed 07432d1(空白容忍 + fail-closed)
4 MEDIUM chmod/mv/sidecar 寫入無檢查 → 假安裝可能 codex Fixed 07432d1
5 LOW TMP_FILE 在 exec 路徑殘留(trap 不跨 exec) agents:logic+regression Fixed 8330daa
6 LOW RESOLVED_VERSION 解析為 dead code(CDN redirect 遮蔽 tag)+ 註解誤導 agents:logic+devils-advocate Fixed 8330daa(移除)
7 LOW word CHANGELOG 雙 [Unreleased] 標題 agents:regression Fixed 8330daa
8 MEDIUM shell↔binary 版本耦合(plugin.json version = release tag;docs-only bump 會 404) agents:logic+codex 既有 #116(版本解耦)
9 LOW wrapper 不驗 notarization/hardened/universal 而部分文件暗示 codex Fixed 07432d1(文件精準化:wrapper 強制 sha256+DevID;notarization 為 release 流程性質)
10 LOW ~/bin 跨 marketplace 同名 binary 碰撞面 codex(R1)+agents:regression Follow-up(見 triage)
11 LOW 複製 shell 內文件漂移(tool counts / 版本)+ marketplace description 過長 codex(R1+R2) Follow-up(見 triage)
12 INFO 裸 tag(無 v 前綴)會 fail-closed — 現況三 repo 全為 vX.Y.Z,屬 maintainer 控制的 convention codex 不處理(記錄於此)

Post-R2 fixes 的驗證方式(透明聲明)

8330daa / 07432d1 在 R2 ensemble 之後落地,實作均為 reviewers 開處方並各自預先驗證過的 fix(security 驗過 OID 行、三方收斂 exec-time 設計),coordinator 以對抗性 E2E 複驗(evil PoC、Development-cert 場景由 security 驗、植入模擬、三 binary 快路徑)。未再開第三輪 ensemble — 若要最嚴格紀律可對 07432d1 單獨補一輪 targeted review。

Process Gaps

(無 — R2 5/5 findings 檔完整;Codex timeout 一次後重試成功)

Scope Check

8+5 檔改動全數可追溯至 R1/R2 findings;untracked cli/openspec/changes/pptx-geometry-tools/ 未觸碰。

結論

PASS — ready to merge(merge 後:遠端 claude plugin marketplace add PsychQuant/macdoc 補驗 + #101 來源端移除 + /idd-close #112

Follow-up Findings Filed (v2.72.0+ #148)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant