Skip to content

fix(core): never echo JSON parser text from the account store reader - #184

Merged
ualtinok merged 1 commit into
cortexkit:mainfrom
iceteaSA:fix/json-parse-secret-echo
Sep 2, 2026
Merged

fix(core): never echo JSON parser text from the account store reader#184
ualtinok merged 1 commit into
cortexkit:mainfrom
iceteaSA:fix/json-parse-secret-echo

Conversation

@iceteaSA

@iceteaSA iceteaSA commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Bun 1.3.14's JSON.parse quotes an unquoted token adjacent to a syntax error verbatim:

JSON.parse('{"key":ckh_SECRET}')  →  SyntaxError: JSON Parse error: Unexpected identifier "ckh_SECRET"

(Unterminated-string and expected-brace cases stay clean; the trigger is a hand-edit that leaves a bare token.)

readJsonIfPresent in packages/core/src/accounts.ts interpolated that message into the thrown account store at <path> is corrupt or unreadable (<parser text>) error. It reads both anthropic-auth.json (may hold a Claustrum handle) and anthropic-auth-state.json (OAuth access and refresh tokens), and the plugin logs that error. So a bad hand-edit next to a token wrote the token into opencode-anthropic-auth.log. dump.ts parseBody had the same shape for request/response bodies.

Fix

parseJsonRedacted (packages/core/src/json.ts): catches SyntaxError and rethrows a fixed-message SyntaxError('invalid JSON') with no cause. Used by the account-store reader and the dump body parser. The account-store error keeps the path and the "fix or remove it" hint.

Audited the other JSON.parse sites in core (lock/owner files, sticky routing state, quota feed leases, cachekeep registry, dump metadata): none parse secret-bearing content with an interpolated message; left as is.

Proof

Regression writes a state file containing a bare sk-ant-oat…CANARY… token beside a syntax error and a config file with a bare handle-shaped value: the loader throws, the message and cause contain neither canary, and the message still names the path. Mutation (restore direct JSON.parse in readJsonIfPresent): the regression fails. Root 1368/0, typecheck, format, biome clean.

Found via the same class of bug in cortexkit/claustrum#28.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Prevents malformed account-store and dump JSON from echoing secret-like tokens from Bun’s JSON.parse errors. Previously, the account-store reader could include bare token identifiers in corruption logs; it now reports fixed invalid JSON text while retaining the file path and recovery hint.

  • Adds shared parseJsonRedacted handling for account config, account state, and dump bodies.
  • Adds regression coverage for OAuth token and Claustrum handle values in corrupt account stores.

Written for commit dfb6bc0. Summary will update on new commits.

Review in cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 5 files

Architecture diagram
sequenceDiagram
    participant User as User or Host Process
    participant OpenCode as OpenCode Runtime
    participant Accounts as Account Store Reader
    participant JSON as Redacted JSON Parser
    participant FS as Local Account Files
    participant Logger as Plugin Logger
    participant Dump as Dump Body Parser
    participant HTTP as Request or Response Body

    Note over User,Logger: Account loading flow
    User->>OpenCode: Load account configuration
    OpenCode->>Accounts: loadAccounts()
    Accounts->>FS: Read anthropic-auth.json
    FS-->>Accounts: Config JSON or file error
    Accounts->>JSON: Parse config text
    JSON-->>Accounts: Parsed config
    Accounts->>FS: Read anthropic-auth-state.json
    FS-->>Accounts: OAuth state JSON or file error
    Accounts->>JSON: Parse state text
    JSON-->>Accounts: Parsed OAuth tokens

    alt Valid JSON in both stores
        Accounts-->>OpenCode: Account configuration and auth state
        OpenCode-->>User: Accounts available
    else Missing account file
        FS-->>Accounts: ENOENT
        Accounts-->>OpenCode: File absent
        OpenCode-->>User: Continue with no stored account
    else Malformed JSON near a secret-bearing token
        JSON->>JSON: Catch SyntaxError
        JSON-->>Accounts: CHANGED: SyntaxError("invalid JSON") without cause
        Accounts-->>OpenCode: Corruption error with file path and fix-or-remove hint
        OpenCode->>Logger: Log corruption error without parser text or token
        Logger-->>User: Safe diagnostic
    end

    Note over User,HTTP: Request or response dump flow
    OpenCode->>Dump: Capture body for dump or diff summary
    Dump->>HTTP: Read body text
    HTTP-->>Dump: JSON or non-JSON body
    Dump->>JSON: Parse body text
    alt Valid JSON object
        JSON-->>Dump: Parsed object
        Dump-->>OpenCode: Redacted or summarized body data
    else Invalid JSON
        JSON->>JSON: Catch SyntaxError
        JSON-->>Dump: CHANGED: Fixed "invalid JSON" error without original text
        Dump-->>OpenCode: Treat body as unparsable
        OpenCode->>Logger: Log dump failure without parser text or secret
    end
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/core/src/json.ts
Bun 1.3.14 can include an unquoted token identifier in JSON.parse SyntaxError text. The account config and state files can hold Claustrum handles and OAuth access or refresh tokens; redact parser text before the reader surfaces corruption.
@iceteaSA
iceteaSA force-pushed the fix/json-parse-secret-echo branch from 9d3739e to dfb6bc0 Compare September 2, 2026 18:35
@ualtinok
ualtinok merged commit 59e06e2 into cortexkit:main Sep 2, 2026
5 checks passed
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