diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-09 19:30:51 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-09 19:30:51 +0200 |
| commit | f1b37bc5dea7493a6d98e552c48cb6e6f9f3f0ec (patch) | |
| tree | a35f29b8018c23264d43e83fa6cf405e8ff58d6d /.gitignore | |
| parent | b0031f905eb63fc76aa6cad0421c4623ebad2b88 (diff) | |
| download | abusectl-f1b37bc5dea7493a6d98e552c48cb6e6f9f3f0ec.tar.gz abusectl-f1b37bc5dea7493a6d98e552c48cb6e6f9f3f0ec.zip | |
fix: escape the continuation marker so a value cannot forge one
The marker was an unescaped trailing backslash, and a backslash is legal in
a URL path, so a value ending in one was indistinguishable from a wrap. An
attacker who read this source could append one and make their own indicator
garble itself in the report an abuse desk reads: an adversarial trigger on
attacker-supplied text, not an edge case.
The short case needed no wrapping at all to corrupt. unwrap() ate the
following line regardless, merging an indicator with its own origin
annotation. On Subject it was worse, absorbing the Date beneath it and
making the "Message as declared" block misstate what the message declared,
which is the one thing that block exists to report faithfully.
Every backslash is now doubled before wrapping and halved on the way back,
and unwrap() tells a marker from content by the PARITY of the trailing run.
Doubling only a trailing one would leave "x\\" encoding as "x\" plus a
marker, the same bug one character along.
A second defect surfaced only under a randomised sweep, after the first fix
and a green suite: a break landing BETWEEN the halves of an escaped pair
splits the run whose parity unwrap() counts, so a real marker reads as
content and the tail is silently dropped. It needs a backslash at exactly
the break column, so no hand-written case found it and 454 of 3538 random
ones did. The wrap now backs off a character rather than splitting a pair.
Verified over 9132 adversarial values, including every backslash pattern up
to length 9 and values that are entirely backslashes: 0 round-trip failures,
0 header-block corruptions, no line over 72 columns.
Values are escaped, never rejected or sanitised: the report says what the
message contained.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xj1ayFRSUQ2u7cwb3S4axE
Diffstat (limited to '.gitignore')
0 files changed, 0 insertions, 0 deletions
