Redact secrets in decoded JSON values, not the serialized line - #682
Conversation
PR Summary by QodoRedact secrets structurally within decoded JSON values
AI Description
Diagram
High-Level Assessment
Files changed (6)
|
Code Review by Qodo
1. Comments produce invalid JSON
|
0c80353 to
18ef70f
Compare
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit 18ef70f |
18ef70f to
d7f2cfa
Compare
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit d7f2cfa |
315b7e9 to
f544928
Compare
|
/agentic_review |
|
Code review by qodo was updated up to the latest commit f544928 |
A pattern run over the serialized line matches past the value it found into the surrounding structure, and the server drops an unparseable line without a word. Mirroring every token through a Utf8JsonWriter makes malformed output unrepresentable. The reader's depth limit is the writer's own ceiling, so what one accepts the other can emit and the fallback sees only unparseable input. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
f544928 to
6b89a48
Compare
Closes #681 — AI-2262
What & why
SecretRedactor.RedactLineran its patterns over the serialized JSONL line. Several value classesexclude
"and\but not{,},[,],,or:, so a match beginning inside a stringvalue ran past it and swallowed the JSON that followed — and the server drops what it cannot parse
without reporting it, so transcripts lost turns invisibly. Redaction now walks tokens with a
Utf8JsonReaderand re-emits every one through aUtf8JsonWriter, scanning only decoded stringvalues, which also keeps a serialized tool result carried as a string in scope. A secret-bearing key
arms its whole subtree rather than just a string directly under it, so
{"auth":["b1","b2"]}redacts both elements and keeps the array.
Where to look
Rewrite's token loop. ThesecretDeptharm/disarm is what keeps a secret key off its siblings —a container reports the same depth on the way out as on the way in, which is what makes it exact.
One gap worth knowing, and one behaviour change:
Set-Cookie: session=\"x\"inside textVerification
The three shapes from #681, none of which parsed before:
dotnet run --project test/Capacitor.Cli.Tests.Unit→ 3738 passed, 0 failed, 19 skippeddotnet run --project test/Capacitor.Cli.Core.Tests.Unit→ 2372 passed, 0 failed, 2 skippeddotnet publish src/Capacitor.Cli -c Release→ no IL2xxx/IL3xxxA seeded generative test runs 3000 documents through it: none throw, all outputs parse, and over a
third are actually rewritten. Same-process timing against the previous shape: 163 vs 165 µs on a
clean 13.8 KB line.