aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_offline.py
AgeCommit message (Collapse)AuthorFilesLines
10 hourstest: cover report.py in the no-socket proofDanilo M.1-1/+29
The offline test enumerates modules by import and report was absent, so the module that writes documents naming hosts and addresses from a message was outside the second property's only actual verification. Exercised through generate() against a real case directory rather than build() alone, so the disk path is covered too. Confirmed the test can fail: a getaddrinfo planted in build() makes it fail. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LByBnw83xr9YP85nskzkyE
26 hoursfeat: store a whitelist of publishable headers in the manifestDanilo M.1-0/+8
report must never open source.eml, so parse decides once what may be published and report formats only what it is given. To, Cc, Delivered-To and X-Original-To are absent by construction rather than stripped. Received is cut to the boundary hop alone, in both directions. Above it are our own relays; below it is the attacker's own writing, and a forged chain names an innocent third party there, so publishing a hop below the boundary puts someone else's address into a report a desk will act on. That is the third property applied to disclosure rather than to sending_ip(). Truncating the chain was not sufficient on its own: the surviving line is written by our own relay and records the envelope recipient in its optional "for <addr>" clause, so the whitelist alone would have published the victim's address verbatim in the one header a report reproduces in full. The clause is removed and the rest of the hop kept. The manifest-wide "no example.org" assertion is narrowed to the headers block only, where the whitelist deliberately publishes our receiving relay's name in a by/authserv-id clause. The address itself is still barred there, asserted separately. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xj1ayFRSUQ2u7cwb3S4axE
35 hourstest: make the offline resolve check tamper-evidentDanilo M.1-0/+7
The test asserted only that resolve() returned one entry. It returns one entry whether the injected fetch answered or the real transport was blocked, because resolve() records a transport failure as a per-entry error rather than raising. So the assertion would have stayed green if someone removed the injection, which is the one thing the test exists to notice. It now asserts the handle that only the injected fetch can produce. Removing the injection fails with KeyError: 'handle'. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wrfqr2xqQfhtXCscU7zrdz
36 hourstest: prove the suite still opens no socketDanilo M.1-0/+76
The umbrella design verifies property 2 by running with sockets raising. Now that a network module exists, that has to stay true for the WHOLE suite rather than for everything except contacts: a network module that can only be tested with a network is a module that stops being tested. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wrfqr2xqQfhtXCscU7zrdz