@bobfrankston/rmfmail 1.2.314 → 1.2.315

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.commitmsg CHANGED
@@ -1,27 +1,17 @@
1
- Self-spoof: a DMARC-proved From is not a spoof, whatever else failed
1
+ Self-spoof: the From domain's own SPF or DKIM pass is proof, DMARC verdict or not
2
2
 
3
- Bob 2026-09-09, the ISOC Internet Policy list post, red banner "This
4
- message is not what it says it is claims to be from your own address,
5
- internetpolicy@elists.isoc.org, but it did not come from your account.
6
- DKIM authentication failed". The list rewrote From to itself and signed
7
- it; iecc.com recorded dkim=pass d=elists.isoc.org and dmarc=pass
8
- header.from=elists.isoc.org and dkim=fail for the original author's
9
- standardstrack.com signature the list had broken. Delivered-To was the
10
- list address, so it counted as one of Bob's own, and selfSpoof read every
11
- Authentication-Results and every signature and took the one failure as
12
- "did not come from your account". One broken signature on a message whose
13
- From domain passed DMARC aligned is not evidence about the From line; the
14
- pass is. selfSpoof now returns before the failure scan when dmarcProof
15
- passes for the actual From domain (a pass for some other domain still
16
- proves nothing — tested).
3
+ Follow-up to v1.2.314 (which vetoed the self-spoof finding on a DMARC pass).
4
+ The AMW list (berglist.com) publishes no DMARC policy, so its posts carry
5
+ no dmarc= verdict at all but iecc.com recorded spf=pass for
6
+ amw-bounces@berglist.com and dkim=pass d=berglist.com, which is the very
7
+ evidence DMARC would have aligned on. The dkim=fail beside them was the
8
+ gmail.com author signature the list broke, and the post was red as a spoof
9
+ of the list's own address (Delivered-To). New alignedPass() in trust.ts:
10
+ a verified signature for the From domain, or an SPF pass for an envelope at
11
+ the From domain, computed as DMARC's relaxed alignment; a forger's pass for
12
+ their own domain clears nothing (tested).
17
13
 
18
- Measured over the last 120 days: 977 messages whose From is their own
19
- Delivered-To, 35 self-spoof findings before, 20 after; the 15 cleared are
20
- all ISOC list posts, the 20 that remain are the sextortion/phish/NDA-scam
21
- mail the check exists for.
22
-
23
- Also: a danger banner on a proved-list post now says which list delivered
24
- it and that trusting the list (right-click the From address) would not
25
- clear the finding — a red banner with no way forward sends the reader
26
- hunting (Bob: "right mouse on the From … that's not obvious to the normal
27
- user"). mailx-types 0.1.90.
14
+ Store, last 120 days, messages whose From is their own Delivered-To: 977;
15
+ self-spoof findings 35 before v1.2.314, 20 after it, 15 now. The 15 that
16
+ remain are the sextortion, "failed to deliver", NDA-review and
17
+ document-share phishes the check exists for. mailx-types 0.1.91.
@@ -40,6 +40,10 @@ tests/trust.test.ts, .commitmsg, TODO.md C165, root version 1.2.311. Then rebuil
40
40
  ## Follow-up 2026-09-09 evening
41
41
  - Button beside the chip ("Trust the ‹List-Id› list"), From-menu item now toggles (Stop trusting…), docs reworded re editing allowlist.jsonc. Danger banners keep no list button: 123/123 proved-list danger cases in 120 days were URL phish/malware listings.
42
42
 
43
+ ## Self-spoof false positive (found from Bob's screenshot, 2026-09-09 late)
44
+ - ISOC + berglist posts red as "claims to be from your own address": Delivered-To = list address = From, and selfSpoof took ANY dkim=fail in ANY Authentication-Results as proof of forgery. v1.2.314: DMARC-aligned pass vetoes. Next (v1.2.315): alignedPass() — From domain's own SPF pass or DKIM pass vetoes (relaxed alignment for domains with no DMARC policy). Store: 35 → 20 → 15 findings; the 15 are real phish.
45
+ - Danger banner on a proved-list post now names the list and says right-click From / that trust would not clear it.
46
+
43
47
  ## Status
44
48
  - [x] trust.ts
45
49
  - [x] settings/store/service/web
@@ -2267,6 +2267,23 @@ function dkimSigners(input) {
2267
2267
  }
2268
2268
  return out;
2269
2269
  }
2270
+ function alignedPass(input) {
2271
+ const fromDomain = (bare(input.fromAddress).split("@")[1] || "").toLowerCase();
2272
+ if (!fromDomain)
2273
+ return "";
2274
+ if (dkimSigners(input).some((d) => sameOrg(d, fromDomain)))
2275
+ return "dkim";
2276
+ const auth = headerAll(input.headerLines, "authentication-results")[0] || "";
2277
+ for (const part of auth.split(";")) {
2278
+ if (!/\bspf=pass\b/i.test(part))
2279
+ continue;
2280
+ const mailfrom = (part.match(/(?:spf|smtp)\.mailfrom=([^\s;,]+)/i)?.[1] || "").toLowerCase();
2281
+ const domain = mailfrom.includes("@") ? mailfrom.split("@")[1] : mailfrom;
2282
+ if (domain && sameOrg(domain, fromDomain))
2283
+ return "spf";
2284
+ }
2285
+ return "";
2286
+ }
2270
2287
  function provedIntermediary(input) {
2271
2288
  const list = (input.trustedIntermediaries || []).map((d) => (d || "").trim().toLowerCase()).filter(Boolean);
2272
2289
  if (!list.length)
@@ -2483,7 +2500,7 @@ function selfSpoof(input) {
2483
2500
  const auth = headerAll(input.headerLines, "authentication-results").join(" ; ");
2484
2501
  if (!auth)
2485
2502
  return null;
2486
- if (dmarcProof(input).pass)
2503
+ if (dmarcProof(input).pass || alignedPass(input))
2487
2504
  return null;
2488
2505
  const failed = [
2489
2506
  /\bspf=(fail|softfail)\b/i.test(auth) ? "SPF" : "",