diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/BACKLOG.md | 55 | ||||
| -rw-r--r-- | docs/specs/2026-09-09-report.md | 13 |
2 files changed, 43 insertions, 25 deletions
diff --git a/docs/BACKLOG.md b/docs/BACKLOG.md index 3ab642f..87ec4b3 100644 --- a/docs/BACKLOG.md +++ b/docs/BACKLOG.md @@ -8,7 +8,7 @@ number and gains a status rather than being renumbered. | 1 | Skip boilerplate namespace URLs | XS | open | | 2 | An IDN indicator resolves to no contact | S | open | | 3 | Expose kept cases so qtmaildir can tag spam | ? | open, unsized | -| 4 | `Report-Type: phishing` is unverified against x-arf | XS | open | +| 4 | `Report-Type: phishing` is unverified against x-arf | XS | closed | | 5 | `report.build()` raises KeyError on an identity with no email | XS | closed | ## 1. Skip boilerplate namespace URLs @@ -114,27 +114,38 @@ to qtmaildir. The second is much more in keeping with the rest of the tool. ## 4. `Report-Type: phishing` is unverified against x-arf -**Observed.** `report.feedback_fields()` emits `Report-Type: phishing` in the -machine-readable part. Every other field there was verified against RFC 5965 -itself; this one was not, because no primary source for x-arf's own field -semantics could be reached while building it. The abusix README documents only -the v3 to v4 deprecation and does not define the field. - -**Cause.** Not a defect found in the code. The value follows the worked -example in `docs/specs/2026-09-09-report.md`, so it is internally consistent, -and the hybrid envelope means a strict RFC 5965 parser ignores the field -either way (the RFC requires implementors ignore fields they do not support). -The exposure is limited to x-arf tooling reading a field name or value that -does not exist in the version it implements. - -**Approach.** Find a primary source for x-arf v4 field names, confirm or -correct the value, and record what it was checked against. If x-arf turns out -to name the field differently, the fix is one string and one test. - -**Constraints.** Low urgency: nothing here is a leak, and the failure mode is -a field an x-arf parser skips rather than acts on wrongly. Worth doing before -the first real report is filed, so a desk running x-arf tooling gets what it -expects. +**Closed** against the IANA MARF registry +(`https://www.iana.org/assignments/marf-parameters/marf-parameters.xml`), +checked 2026-09-10, plus RFC 5965 itself. The primary source the item asked +for exists; it is IANA's, not x-arf's. + +Two things were wrong, and neither was a leak. + +`Report-Type` is NOT a registered field. The registry lists 25 field names +and it is absent. It came from the worked example in the report spec rather +than from a decision. It is now REMOVED: `Feedback-Type` already carries what +it was saying. Keeping it would have been harmless, since RFC 5965 section 6 +makes ignoring an unknown field a MUST for the receiver, but that same section +requires an extension field be registered, and a desk should be able to look +up every field in a document this tool sends. + +`Feedback-Type` was `abuse` and is now `fraud`. RFC 5965 registers `fraud` as +"indicates some kind of fraud or phishing activity" and `abuse` as +"unsolicited email or some other kind of email abuse". This tool reports +phishing, so `fraud` is the registered value that says what the report is, +and some desks route it separately from bulk spam. + +A third, cosmetic, finding: the module emitted `Reported-Uri` while the RFC's +ABNF and its IANA registration both spell it `Reported-URI`. The RFC's own +worked example writes `Reported-Uri`, which is where the module's spelling +came from. Field names are case-insensitive per RFC 5322 so nothing was +broken, and it now matches the normative spelling. + +`tests/test_report.py::FeedbackPart::test_no_unregistered_field_is_emitted` +holds the registry's 25 names and asserts every emitted field is one of them. +The single exception is `Source`, which is x-arf's and is the reason the +envelope carries x-arf fields at all; it is named in the test so a NEW +unregistered field cannot arrive unnoticed. ## 5. `report.build()` raises KeyError on an identity with no email diff --git a/docs/specs/2026-09-09-report.md b/docs/specs/2026-09-09-report.md index 12d2157..b3a67ae 100644 --- a/docs/specs/2026-09-09-report.md +++ b/docs/specs/2026-09-09-report.md @@ -111,20 +111,27 @@ second body to keep in sync with the first for no reader. An RFC 5965 envelope carrying x-arf fields inside it. ``` -Feedback-Type: abuse +Feedback-Type: fraud User-Agent: abusectl/0.1.0 Version: 1 -Report-Type: phishing Source: 198.51.100.7 Source-IP: 198.51.100.7 Reported-Domain: example.invalid Arrival-Date: Mon, 08 Sep 2026 09:12:44 +0000 -Reported-Uri: http://login-example.invalid/verify?id=REDACTED +Reported-URI: http://login-example.invalid/verify?id=REDACTED ``` `Feedback-Type`, `User-Agent` and `Version` are the three fields RFC 5965 requires. The rest are optional there or come from x-arf. +**Every field name here is in the IANA MARF registry except `Source`**, which +is x-arf's and is the reason the envelope carries x-arf fields at all. An +earlier draft of this example also carried `Report-Type: phishing`, which is +not registered anywhere; it was removed once the registry was checked, since +`Feedback-Type` already says it. `fraud` rather than `abuse` because RFC 5965 +defines it as "some kind of fraud or phishing activity", which is what this +tool reports. See backlog item 4 for what was checked against what. + **Why an RFC 5965 envelope with x-arf fields inside, rather than either alone.** RFC 5965 is an IETF standard and universally understood, but it was designed for feedback loops, where a report is ABOUT A MESSAGE. These reports |
