aboutsummaryrefslogtreecommitdiffstats
path: root/tests/fixtures/leaky.eml
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-09 19:38:18 +0200
committerDanilo M. <danix@danix.xyz>2026-09-09 19:38:18 +0200
commit2aa840e2ce75a04628085ccecd6382f8e5e9734a (patch)
tree5815dd2dca3dc256d1e8e39698ac3597aa9e58f7 /tests/fixtures/leaky.eml
parentf1b37bc5dea7493a6d98e552c48cb6e6f9f3f0ec (diff)
downloadabusectl-2aa840e2ce75a04628085ccecd6382f8e5e9734a.tar.gz
abusectl-2aa840e2ce75a04628085ccecd6382f8e5e9734a.zip
feat: build the machine-readable feedback report part
An RFC 5965 envelope carrying x-arf fields. 5965 reports are about a message and these are about indicators, so x-arf's Source fills the gap while the report-type keeps a standards parser working. Field values are percent-encoded against header injection. This is reachable, not theoretical: redact.url_valued_parameters() URL-decodes a redirector's destination to recover it as an indicator, so a body carrying "?next=http%3A%2F%2Fa.invalid%2Fx%0AFeedback-Type%3A%20not-abuse" produces, through parse.iocs() on a real message, an IOC whose value holds a literal newline followed by text shaped like a field. Emitted verbatim it forges a field in a report carrying the reporter's identity. Encoding rather than dropping keeps a genuine redirect target; encoding rather than stripping keeps the indicator recoverable, since a stripped URL is a different URL a desk would then act on. The escape covers everything str.splitlines() breaks on, because Python's own email module raises on U+2028 as readily as on LF, and it runs over UTF-8 bytes and escapes "%" so the reversal is a true inverse rather than a second injection one step later. Four corrections to the plan. Source-IP is emitted once, not once per IP: RFC 5965 gives it "once maximum" and a repeat displaces the primary rather than adding an address. Source is omitted when there is no typed indicator rather than emitted empty, since an empty field asserts that the reported thing is the empty string. Arrival-Date is dropped rather than copied from the sender's Date header, which is attacker-controlled and means when the sender claimed to send, not when our MTA received. sha256 and observation are left to the text part rather than forced into the nearest field. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xj1ayFRSUQ2u7cwb3S4axE
Diffstat (limited to 'tests/fixtures/leaky.eml')
0 files changed, 0 insertions, 0 deletions