Replaces the proposed bare-token base64-22 value rule (#196) with
key-based filtering, and closes the gaps it was compensating for:
- The rootKey marker regex now consumes an optional quote after the
separator, so the two realistic leak shapes — a logged init frame
({"rootKey":"…"}) and a console-formatted message object
(rootKey: '…') — redact. Previously both passed through untouched.
- Object fields keyed rootKey/root_key/root-key are redacted by the
walker regardless of value type or encoding, matching what the
scrubber already did for lat/lng keys. A key-based rule keeps working
if the wire encoding ever changes (the legacy app stored the key as
hex — see LegacyRootKeyDecoder).
- The IPC servers no longer log frame payloads: simple-rpc logs only
the frame type for invalid messages, and both simple-rpc and
comapeo-rpc log only the parse error NAME on messageerror (V8's
JSON.parse SyntaxError embeds a snippet of the raw input, which for
a mangled init frame includes rootkey bytes).
There is deliberately no value-shape rule for bare unmarked tokens: the
key exists as a base64 string only inside the init frame, always next
to its field name (it never enters the RN JS layer); everywhere else it
is a Buffer whose accidental serialisations (hex dump, byte array) a
base64 rule would not match anyway. Notes in both scrubber copies and
docs/sentry-integration.md §8 document the decision.
Closes #77
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F1HTHPYkoyjjcvLgsUpvMk
Closes #77. Replaces #196.
#196 proposed an exact-shape base64-22 value rule to catch bare (unmarked) rootkey tokens. Stepping back from that design: the value-shape approach hard-codes the wire encoding in places nothing keeps in sync with backend/index.js's validator (and the encoding has changed before — the legacy app stored the key as hex, see LegacyRootKeyDecoder, an encoding a base64 rule structurally cannot match without redacting every trace id). Meanwhile, tracing the key end-to-end shows every realistic leak shape carries the rootKey field name right next to the value: the key exists as a base64 string only inside the init frame (native → control socket → backend); it never enters the RN JS layer at all, and past the init handler it is a Buffer whose accidental serialisations (hex dump, byte array) a base64 rule would not match anyway.
So this PR filters on the key, not the value's shape, and fixes the holes the bare-token rule was compensating for:
There is deliberately no value-shape rule for bare unmarked tokens; the decision and its rationale are documented in both scrubber copies and docs/sentry-integration.md §8. The rootkey metric tag-name ban already covers the realistic metrics mistake, so no tag-value scan is added either.
Tests: shared cases in test-support/scrubber-cases.js cover the JSON-quoted, util.inspect-quoted, and root_key-variant forms (and pin that bare tokens still pass, as a deliberate decision); both scrubEvent suites assert key-field redaction works on a hex value to prove encoding-independence; a new simple-rpc test drives real sockets with an unknown-type frame and a truncated init frame each carrying a key and asserts no key material reaches the console.
Verified with npm run lint, npm run build, npm run test (78 passed), npm run backend:test (97 passed), plus a generative check: 1,000 random 16-byte keys through the logged-frame and inspected-object shapes — 0 leaks.
🤖 Generated with Claude Code
https://claude.ai/code/session_01F1HTHPYkoyjjcvLgsUpvMk
Generated by Claude Code