fix(security): close P-8 — scrub Bearer/token from _logError before storage#53
Merged
Conversation
…torage
api-client.mjs::_logError stored Chronicle error response bodies
(truncated to 200 chars) into the in-memory error log surfaced via
the dashboard. If Chronicle's error body echoed the request — e.g.,
"Invalid token: Bearer abc123..." — the apiKey would leak into the
diagnostics panel.
Fix: new _scrubAuthHeaders(text) helper (exported) that regex-replaces
"Bearer <token>" → "Bearer [redacted]" and "?token=<value>" / "&token=
<value>" → "?token=[redacted]" / "&token=[redacted]" before truncation
and storage. Applied at _logError's first line.
9 new tests in tools/test-api-client-secrets.mjs cover behavioral
patterns (Bearer redaction, ?token= query-param redaction, mid-query
&token=, case-insensitivity, multiple-secret messages, non-string
input, integration with _logError).
Test suite: 250 baseline + 9 new = 259/259 pass.
Cites: 2026-05-21-core-tenets §T-B1
reports/foundry/2026-05-22-fm-security-audit.md §2 P-8, §4 Chunk 4, §0.5 D3=(b)
9 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cites: 2026-05-21-core-tenets §T-B1; reports/foundry/2026-05-22-fm-security-audit.md §2 P-8, §4 Chunk 4, §0.5 D3=(b); dispatches/foundry/FM-SEC-CHUNK-4.md
Security implication: closes P-8 (theoretical Bearer-token / signed-URL-token exfiltration via error log). Without this fix, if Chronicle's error body echoed the request (
"Invalid token: Bearer abc..."), the apiKey would land in the in-memory error log surfaced via the dashboard's Status tab.Consumer-verified: n/a — log-handling change only, no wire surface.
Foundry compatibility: pure JS, ES regex; works across v12/v13/v14.
Mockup: n/a — internal diagnostic; no UI change other than redacted text where a secret would otherwise appear.
What this changes
Adds
_scrubAuthHeaders(text)toscripts/api-client.mjs(exported). The helper regex-replacesBearer <token>→Bearer [redacted]and?token=<value>/&token=<value>→?token=[redacted]/&token=[redacted]._logErrorcalls it on the message before truncation/storage.9 new behavioral tests in
tools/test-api-client-secrets.mjscover: Bearer redaction,?token=query-param redaction, mid-query&token=, case-insensitivity, multi-secret messages, non-string input passthrough, and the static-source integration check that pins_logErrorto call the helper.Why
The Foundry-side security audit (
§2 P-8,§0.5 D3=(b)) flagged the theoretical exfiltration vector. Even with the 200-char truncation in_logError, a 64-char Bearer apiKey fits entirely within the truncation buffer. The scrub closes the leak path without changing the diagnostic value of the log (path + status + non-secret message content still preserved).Test plan
node --test tools/test-*.mjspasses locally (250 baseline + 9 new = 259/259)node tools/check-package-descriptor.mjspasses (descriptor unchanged but ran for hygiene)?token=redaction,&token=redaction, case-insensitivity, multi-secret, non-string, integrationBearer [redacted]instead of the literal tokenTenet self-check
chronicle-foundry-moduleStop-and-flag
None encountered. The
dropLastErrorLogEntrypath (api-client.mjs:609) does NOT return the message externally — only invokes_errorLog.shift()— so no additional scrub needed there.getErrorLog()returns the already-scrubbed entries.🤖 Cites
dispatches/foundry/FM-SEC-CHUNK-4.md. Generated by Claude Code.Generated by Claude Code