fix(sentry): protect the rootkey by key name, not value shape#204
Merged
Conversation
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
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.
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, seeLegacyRootKeyDecoder, 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 therootKeyfield 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 aBufferwhose 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:
rootKeymarker regex now consumes an optional quote after the separator. Previously{"rootKey":"…"}(a logged init frame) androotKey: '…'(aconsole.warn'd message object, exactly whatutil.formatproduces) both passed through unredacted — verified against the old regex. These are the two realistic leak shapes.rootKey/root_key/root-keyjoins lat/lng inSENSITIVE_KEY_PATTERN, so a structured{rootKey: …}inextra/contexts/breadcrumb data is redacted whatever the value looks like — base64, hex, or anything future. (The walker already did this for coordinates; the rootkey was the inconsistency.)simple-rpc.jslogged the full message object on the invalid-message path — on the very socket the init frame travels — and bothsimple-rpc.jsandcomapeo-rpc.jslogged the parseErroronmessageerror, whose message embeds a snippet of the raw input under V8 ("…{"rootKey":"MDEy…" is not valid JSON). They now log only the frametype/ error name. With the debug-onlyconsoleIntegrationon, these were the only real paths for a key to reach a Sentry payload.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. Therootkeymetric 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.jscover the JSON-quoted,util.inspect-quoted, androot_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 newsimple-rpctest 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