Skip to content

fix(agent): redact row values MySQL inlines into its error line - #7

Merged
dabelle merged 1 commit into
mainfrom
fix/mysql-row-value-leak
Sep 19, 2026
Merged

dabelle merged 1 commit into
mainfrom
fix/mysql-row-value-leak

Conversation

@dabelle

@dabelle dabelle commented Sep 19, 2026

Copy link
Copy Markdown
Collaborator

A verification pass caught a leak the earlier redaction fix missed.

Postgres isolates row data in DETAIL and CONTEXT, so dropping whole segments removes it. MySQL does not: it puts the offending value on the same ERROR line as the reason, so segment filtering never touched it and the value went out on the wire to the control plane, and from there into alert bodies.

before: Duplicate entry 'alice@example.com' for key 'users.email'
after:  Duplicate entry '[redacted]' for key 'users.email'

Only the quoted value is replaced. Dropping the whole line would take the reason with it, and the identifier after for key or for column is schema rather than data, so naming the constraint that failed still works.

The test that should have caught this carried dave@example.com in its input and only asserted the DETAIL line was hidden, so the suite stayed green while the address shipped. Same shape as the original bug: a test asserting something adjacent to the thing that matters. It now asserts the value is gone and the constraint name survives, plus two new cases covering Duplicate entry and Incorrect … value:.

SECURITY.md stops overclaiming. This is pattern matching against known engine output, it has now been wrong twice, and the page says so and points at standalone mode as the version of the promise that does not depend on us keeping up with database vendors.

Also renames the cron example's results file: --json emits pretty-printed objects, so .jsonl promised one-per-line and would break the obvious tail -1 | jq.

A verification pass caught a leak the earlier redaction fix missed. Postgres
isolates row data in DETAIL and CONTEXT, so dropping whole segments removes
it. MySQL does not: it puts the offending value on the same ERROR line as the
reason, so segment filtering never touched it and a user's data went out on
the wire.

  before: Duplicate entry 'alice@example.com' for key 'users.email'
  after:  Duplicate entry '[redacted]' for key 'users.email'

Only the quoted value is replaced. Dropping the whole line would take the
reason with it, and the identifier after "for key" or "for column" is schema
rather than data, so naming the constraint that failed still works.

The test that should have caught this carried dave@example.com in its input
and only asserted the DETAIL line was hidden, so the suite stayed green while
the address shipped. That is the same shape as the original bug: a test
asserting something adjacent to the thing that matters. It now asserts the
value is gone and the constraint name survives.

SECURITY.md stops overclaiming. This is pattern matching against known engine
output, it has now been wrong twice, and the page says so and points at
standalone mode as the version of the promise that does not depend on us
keeping up with database vendors.

Also renames the cron example's results file: --json emits pretty-printed
objects, so a .jsonl extension promised one-per-line and would break the
obvious `tail -1 | jq`.
@dabelle
dabelle merged commit ba9faea into main Sep 19, 2026
4 checks passed
@dabelle
dabelle deleted the fix/mysql-row-value-leak branch September 19, 2026 13:40
dabelle pushed a commit that referenced this pull request Sep 19, 2026
fix(agent): redact row values MySQL inlines into its error line
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant