Security
- Fixed a path traversal in the failure report sample filenames written by
--output(GHSA-c284-w5m6-jhjm, affects 9.0.6 through 11.0.0).save_output()named each failure report's message sample after the sample'sSubjectheader, falling back to the raw, unsanitized subject whenever sanitizing it produced an empty string. A subject consisting only of path separators and dots —../../../or/— sanitizes to nothing, so the raw value reachedos.path.join()and the.emlfile was written outside thesamplesdirectory, or at an absolute path. The subject comes from a message that failed authentication, so anyone who can send mail to a monitored mailbox controls it. The filename is now sanitized at write time and falls back tosample, and thefilename_safe_subjectkey that a library caller may supply alongside the subject is no longer trusted. - Fixed unbounded decompression of report attachments (GHSA-43qf-f35w-2x4r, affects all versions through 11.0.0).
extract_report()inflated gzip and zip attachments with no limit on the output size. The attachment's content is chosen by whoever sent it, and deflate reaches compression ratios of about 1000:1 on degenerate input, so a 100 KB attachment from any sender a monitored mailbox accepts inflated to 100 MB, with a peak of about twice that. Extraction now stops at 100 MiB of decompressed data and raisesParserError. The limit is deliberately not configurable: real DMARC aggregate, failure, and SMTP TLS reports are orders of magnitude smaller.
Bug fixes
- CSV output (
failure.csv, and the other CSV renderers) no longer raises_csv.Erroron Python 3.10 when a report field contains a NUL character. Python 3.10'scsvwriter rejects any field containing NUL unless an escapechar is set (CPython issue 97503, a 3.10 regression fixed in 3.11+). Failure report text fields (subject, user agent, authentication results, addresses, and more) come from untrusted mail, so a NUL byte anywhere in one madeparsed_failure_reports_to_csv()— and thereforesave_output()— raise on 3.10, uncaught by the CLI'sexcept (OSError, ValueError)aroundsave_output. The character is now stripped from CSV fields on every Python version, matching the sanitizing already applied to sample filenames.