From 92dba06905ded925bc78e4bac74989363aad62d7 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Tue, 8 Sep 2026 16:28:14 +0200 Subject: feat: flag an address spoofed into a display name A display name naming a recognisable address is a deliberate act and a real signal, so it is reported rather than merely ignored once _domain_of() stopped mistaking it for the sender. The IOC carries no value. One of the identities an attacker impersonates is the recipient themselves, so publishing the impersonated domain would leak the recipient's own domain in exactly the case worth flagging. What travels is only that it happened; the reviewer has the message and can see who was impersonated, and a third party does not need to. display_name_addresses() still returns the full address for local review. Only the published IOC list is stripped. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_019NHaqA1Rz5ybed7wFUeQbK --- tests/test_parse.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'tests/test_parse.py') diff --git a/tests/test_parse.py b/tests/test_parse.py index de78b5a..60c1fb5 100644 --- a/tests/test_parse.py +++ b/tests/test_parse.py @@ -115,6 +115,22 @@ class TestSenderDomains(unittest.TestCase): domains = parse.sender_domains(load("leaky.eml")) self.assertEqual(domains["from"], "sender.example.invalid") + def test_a_display_name_address_is_kept_as_its_own_indicator(self): + # Spoofing a recognisable address in the display name is a real + # signal, so it is reported, but as a spoof rather than as a sender. + spoofed = parse.display_name_addresses(load("leaky.eml")) + self.assertEqual(spoofed, {"from": "you@example.org"}) + + def test_the_spoof_reaches_the_iocs_as_a_flag_carrying_no_value(self): + # The impersonated identity can be the recipient's own, so the IOC + # records only THAT it happened. A domain here would leak in the + # exact case the flag exists to report. + iocs = parse.iocs(load("leaky.eml"), trusted=["192.0.2.0/24"]) + flags = [i for i in iocs if i["type"] == "observation"] + self.assertEqual(len(flags), 1) + self.assertEqual(flags[0]["origin"], "display-name-from") + self.assertNotIn("example.org", flags[0]["value"]) + class TestAuthResults(unittest.TestCase): def test_verdicts_are_read_as_the_server_recorded_them(self): -- cgit v1.2.3