Tracked from the v1.6.4 cross-audit (dimension b, adversarially verified). The MEMORY write path correctly runs redactSecrets() (mcp-server/src/redactor.js) on every ingest, but the OBSERVABILITY plane does not — several surfaces persist raw command lines / prompts / child output that can contain tokens, several with default 0644 perms.
Confirmed instances:
- Observation ledger —
scripts/observation/titleize.js (Bash titles = first ~80 chars of the raw command line; UserPromptSubmit titles = first 80 chars of the raw prompt) → scripts/observation/ledger.js appendFileSync(JSONL_PATH, ...) with no mode (0644) under a default-mode ~/.ijfw. A command like OPENAI_API_KEY=sk-... npm test or curl -H "Authorization: Bearer <tok>" persists the token in the title, indefinitely (10 rotated archives).
- ijfw_run sandbox —
mcp-server/src/sandbox.js spawns with full process.env; when output >40 lines, writeToSandbox writes the raw ANSI-stripped output + full command string to ~/.ijfw/session-sandbox/<label>.{txt,json} with no redaction (dir 0700/files 0600, 24h TTL — same-user exposure).
- profile edit-delta —
mcp-server/src/profile/capture.js EDIT_PII_PATTERNS scrubs assigned secrets but misses BARE key literals (const k = "sk-ant-...", a ghp_ in a URL) in cited_span (cap 160 chars); appended to <project>/.ijfw/.session-edits.jsonl (0644).
- cross-audit receipts —
mcp-server/src/cross-orchestrator.js stderrSnip (child-CLI stderr, 500 chars) lands in <project>/.ijfw/receipts/cross-runs.jsonl (0644) unredacted (mitigated: per-auditor env allowlist, so a child echoes only its own key).
Root cause: one plane enforces redactSecrets(), the other doesn't. Fix direction: route these four sinks through redactSecrets() before write, and set mode 0o600 on the ledger/JSONL appends. Watch item (no current leak): observability/trace-id.js traceEnv() returns full process.env — no spawn consumers today, but a loaded gun; allowlist it.
Severity MEDIUM (local same-user / backup exposure, not remote). Not fixed in the v1.6.4 audit loop (CRITICAL/HIGH were prioritized); filing so it's tracked.
Tracked from the v1.6.4 cross-audit (dimension b, adversarially verified). The MEMORY write path correctly runs
redactSecrets()(mcp-server/src/redactor.js) on every ingest, but the OBSERVABILITY plane does not — several surfaces persist raw command lines / prompts / child output that can contain tokens, several with default 0644 perms.Confirmed instances:
scripts/observation/titleize.js(Bash titles = first ~80 chars of the raw command line; UserPromptSubmit titles = first 80 chars of the raw prompt) →scripts/observation/ledger.jsappendFileSync(JSONL_PATH, ...)with no mode (0644) under a default-mode~/.ijfw. A command likeOPENAI_API_KEY=sk-... npm testorcurl -H "Authorization: Bearer <tok>"persists the token in the title, indefinitely (10 rotated archives).mcp-server/src/sandbox.jsspawns with fullprocess.env; when output >40 lines,writeToSandboxwrites the raw ANSI-stripped output + full command string to~/.ijfw/session-sandbox/<label>.{txt,json}with no redaction (dir 0700/files 0600, 24h TTL — same-user exposure).mcp-server/src/profile/capture.jsEDIT_PII_PATTERNSscrubs assigned secrets but misses BARE key literals (const k = "sk-ant-...", aghp_in a URL) incited_span(cap 160 chars); appended to<project>/.ijfw/.session-edits.jsonl(0644).mcp-server/src/cross-orchestrator.jsstderrSnip(child-CLI stderr, 500 chars) lands in<project>/.ijfw/receipts/cross-runs.jsonl(0644) unredacted (mitigated: per-auditor env allowlist, so a child echoes only its own key).Root cause: one plane enforces
redactSecrets(), the other doesn't. Fix direction: route these four sinks throughredactSecrets()before write, and set mode 0o600 on the ledger/JSONL appends. Watch item (no current leak):observability/trace-id.jstraceEnv()returns fullprocess.env— no spawn consumers today, but a loaded gun; allowlist it.Severity MEDIUM (local same-user / backup exposure, not remote). Not fixed in the v1.6.4 audit loop (CRITICAL/HIGH were prioritized); filing so it's tracked.