Skip to content

fix(connect): close JSONC comment-guard TOCTOU in connect/disconnect - #1353

Open
Dumbris wants to merge 1 commit into
mainfrom
claude/busy-northcutt-92e1b1
Open

Dumbris wants to merge 1 commit into
mainfrom
claude/busy-northcutt-92e1b1

Conversation

@Dumbris

@Dumbris Dumbris commented Sep 23, 2026

Copy link
Copy Markdown
Member

Summary

  • guardJsoncComments and readOrCreateJSON each performed their own independent s.read(cfgPath). A file that was comment-free when the guard read it but gained comments before the parse's later read would pass the guard on stale bytes and get silently rewritten as plain JSON — stripping the comments the guard exists to protect (connect opencode fails: OpenCode bootstraps opencode.jsonc, mcpproxy only recognizes opencode.json #922). disconnectJSON had the identical shape (not previously reported).
  • Fixed by folding the check into a pure guardJsoncCommentsBytes(cfgPath, raw []byte) run against bytes the caller already read, so the guard and the parse/write always see the same snapshot. The old, self-reading guardJsoncComments is kept only for the read-only preview path, which never writes and so has nothing to race.
  • Flagged as a pre-existing, out-of-scope finding during cross-model review of fix(connect): refuse writes when a client's servers section is not an object #1340 (a different, narrowly-scoped fix); closed independently here.

Test plan

  • New regression tests in internal/connect/opencode_jsonc_test.go prove the fix via read-call counting (TestConnectJSON_CommentGuardSharesOneReadWithParse, TestDisconnectJSON_CommentGuardSharesOneRead) — each verified locally to fail against the pre-fix code and pass against the fix.
  • TestGuardJsoncComments_SkipsReadForNonJsoncPath guards a suffix-check-ordering regression caught in second-round review.
  • Existing TestConnect_OpenCode_AllowsTrailingCommaJSON, TestPreview_ConnectRefusal_CommentedJsonc, TestPreview_ConnectRefusal_CommentFreeJsoncIsConnectable still pass.
  • go build (personal + server edition), go vet, gofmt, go test -race ./internal/connect/....
  • golangci-lint (bare and --build-tags server) clean.
  • Two rounds of independent cross-model review: codex gpt-5.6-sol (round 1, clean), then zcode/GLM (round 2, caught a suffix-check-ordering regression and a test coverage gap in round 1's fix — both corrected here and re-verified).

🤖 Generated with Claude Code

guardJsoncComments and readOrCreateJSON each did their own independent
s.read(cfgPath), so a file that was comment-free when the guard read it
but gained comments before the parse's later read would pass the guard
on stale bytes and get silently rewritten as plain JSON, stripping the
comments the guard exists to protect (#922). disconnectJSON had the
identical shape.

Fold the check into a pure guardJsoncCommentsBytes(cfgPath, raw) run
against bytes the caller already read, so the guard and the parse/write
now always see the same snapshot. The old read-it-yourself
guardJsoncComments is kept only for the read-only preview path, which
never writes.

Flagged as a pre-existing, out-of-scope finding in cross-model review of
PR #1340. Verified with call-counting regression tests (fail against the
pre-fix code, pass against the fix) and two rounds of independent
cross-model review (codex gpt-5.6-sol, then zcode/GLM), the second of
which caught a suffix-check-ordering regression and a test coverage gap
in the first fix, both corrected here.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying mcpproxy-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: f21ae3d
Status: ✅  Deploy successful!
Preview URL: https://3c731a78.mcpproxy-docs.pages.dev
Branch Preview URL: https://claude-busy-northcutt-92e1b1.mcpproxy-docs.pages.dev

View logs

@github-actions

Copy link
Copy Markdown
Contributor

📦 Build Artifacts

Workflow Run: View Run
Branch: claude/busy-northcutt-92e1b1

Available Artifacts

  • archive-darwin-amd64 (30 MB)
  • archive-darwin-arm64 (27 MB)
  • archive-linux-amd64 (18 MB)
  • archive-linux-arm64 (16 MB)
  • archive-windows-amd64 (30 MB)
  • archive-windows-arm64 (26 MB)
  • frontend-dist-pr (0 MB)
  • installer-dmg-darwin-amd64 (24 MB)
  • installer-dmg-darwin-arm64 (22 MB)
  • smart-mcp-proxymcpproxy-go14QDW7.dockerbuild (0 MB)

How to Download

Option 1: GitHub Web UI (easiest)

  1. Go to the workflow run page linked above
  2. Scroll to the bottom "Artifacts" section
  3. Click on the artifact you want to download

Option 2: GitHub CLI

gh run download 35814215901 --repo smart-mcp-proxy/mcpproxy-go

Note: Artifacts expire in 14 days.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

This branch has not been deployed

No deployments
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.

2 participants