Repository navigation
fix(privacy): redact flagged object keys in place - #4515
Merged
ScriptedAlchemy merged 4 commits intoOct 25, 2026
Merged
ScriptedAlchemy merged 4 commits into
ScriptedAlchemy merged 4 commits into
Conversation
|
ScriptedAlchemy
enabled auto-merge (squash)
October 24, 2026 14:47
ScriptedAlchemy
force-pushed
the
fix/privacy-redact-keys-in-place
branch
from
October 24, 2026 17:56
9deb752 to
12db5fa
Compare
ScriptedAlchemy
disabled auto-merge
October 24, 2026 18:33
ScriptedAlchemy
enabled auto-merge (squash)
October 24, 2026 18:36
JSON and TOML documents whose keys read as high-entropy tokens are withheld whole today. Pin the target behavior: the key becomes a placeholder unique within its object, the values under it are redacted, and passphrase-shaped secrets stay redacted in every position. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A JSON or TOML object key that trips a credential or entropy detector withheld the whole document, because the sanitizer had no way to rewrite a key. Long identifiers used as keys (schema $defs type names, benchmark target names, path keys) score above the entropy floor, so files such as dashboard-contracts.schema.json were never indexed. The span-reporting JSON and TOML parsers already give each key's byte range. Replace a flagged key with a placeholder unique within its object (TraceDecay-redacted-key-N), redact every scalar under it, and keep the rest of the document byte-exact. Detection is unchanged: no token is exempted. A document is still withheld when the key has no span (YAML) or the rewritten text no longer parses as its format. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ScriptedAlchemy
force-pushed
the
fix/privacy-redact-keys-in-place
branch
from
October 25, 2026 01:13
12db5fa to
08f86e7
Compare
This was referenced Oct 25, 2026
ScriptedAlchemy
changed the base branch from
master
to
fix/lcm-retry-transient-summarizer-failures
October 25, 2026 01:30
ScriptedAlchemy
merged commit Oct 25, 2026
95e49f5
into
fix/lcm-retry-transient-summarizer-failures
6 checks passed
This was referenced Oct 25, 2026
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.
Stack order (merge first → last): #4473 → #4478 → #4521 → #4526 → #4515 → #4510 → #4516 → #4524 → #4489 → #4488 → #4485
This PR is layer 5/11, based on #4526. Next: #4510.
Merge bottom to top using merge commits. After each parent merges, retarget its child to master before merging the child; this preserves the ancestry already integrated and avoids reintroducing conflicts.
Stacked on #4512. This branch is based on
revert/privacy-compound-identifier-exemption(the revert of #4490), which has not merged yet. Until it merges, this PR's diff also shows that revert commit. The two commits that belong to this PR aretest(privacy): expect high-entropy object keys redacted in placeandfix(privacy): redact flagged object keys in place.Problem
A JSON or TOML file whose object key trips the credential or entropy detector is withheld from the index whole (
privacy sanitizer quarantined credential-bearing keys). Long identifiers used as keys score above the 4.2 bits/char entropy floor, so ordinary files never reach the index. Indexing this repo with an isolated daemon built from the base branch withholds exactly two files for this reason:The flagged keys are 8
$defstype names (WorkDuplicateAdjudicationAppendOutcomeV1and similar) and one benchmark target name (clone_peak_rss_added_at_most_1_gib_for_39582_symbols). #4451 item 3 reports the same class.Root cause
collect_tree_fieldsinstructured_text.rsran the detectors on every key, but it could only record a quarantine finding, because the walk did not keep the key's location. A flagged key therefore withheld the whole document, even though the JSON (jsonc_parser) and TOML (DeTable) parsers already report each key's byte range.#4490 tried to exempt "compound identifiers" from detection by shape. That was reverted, because no shape rule separates identifiers from passphrase secrets.
Fix
Detection is unchanged and no token is exempted. Only the response to a flagged key changes.
DocumentNode::Objectnow carries aDocumentKey { name, span }. JSON keys get the span of the body inside the quotes. TOML keys get the span of the whole token, quotes included.TraceDecay-redacted-key-N. N is unique within the object, numbered in document order, and skips any sibling's literal name. The placeholder is a valid bare TOML key and needs no JSON escaping. Every scalar under the key is redacted with the existing sensitive-field marker. Nested keys stay, and each one is still scanned. Everything else in the document stays byte-exact, so the file is indexed.Redacted, and the receipt isRedacted/Secret.constextraction, come from the sanitized bytes. They are named by the placeholder and never contain the key.The document is still quarantined (
CredentialKeyQuarantine) when in-place redaction is impossible:serde_yaml_ng.[secret]then[secret.child]). The parser reports one key span, and the raw-scan redaction of the second header breaks the syntax.sanitize_structured_payload/redact_sensitive_values, which serves LCM JSON payloads, memory facts, and observation records) is unchanged and still quarantines flagged keys.Long Rust type names in source text are still redacted by the raw scan. That false positive is known, and this PR does not touch it.
Verification
Focused tests (
bazel test //crates/tracedecay-privacy/...): 150 passed. The newstructured_text_tests::key_redactionsuite has 10 tests. Before the fix, 7 failed (the documents were quarantined) and 3 passed (the guards). After the fix, all 10 pass. The suite covers:violin-pocket-jungle-quartz-island-778,RocketButtonStapleBridgeYellowOrange90, andMySuperSecretPasswordForProduction2024Admin. As keys (including{"api_keys": {"<secret>": "admin-user"}}) they become placeholders and the value under them is redacted. As values, in URL paths, and in free text afterlet/use/type, they stay redacted.Two tests asserted the old TOML key-quarantine behavior. They are replaced by
credential_keys_redact_in_place_on_code_source_and_lcm_text_routes. Clippy (--config=clippy //crates/tracedecay-privacy/...) and rustfmt are clean.Real surface: an isolated daemon (
TRACEDECAY_DATA_DIRandHOMEin a temp dir) ran the built binary and indexed this worktree. A scratchprivacy-probe.jsonwith passphrase keys was added for the run and deleted afterwards.A byte grep of the isolated data dir finds 0 occurrences of each of the 9 flagged keys and of both probe passphrases.
//crates/tracedecay-code-index-runtime:unit_testhas one failure,git_transactions::native::tests::unbounded_snapshot_captures_a_listing_beyond_the_default_read_limit(Err(NeedsInspection)). It fails the same way on the base branch without this change, and that module does not use the sanitizer.🤖 Generated with Claude Code