How to securely automate ARF authentication-failure reports without forged feedback loops or report floods

dmarctutorial

An authentication-failure report can be useful seconds after a message fails. It can also be a forged email carrying hostile MIME, a privacy-sensitive copy of somebody else's message, or the first packet in a denial-of-service campaign.

That combination makes ARF automation a security design problem, not just a parsing task. A safe system does not ask, "Does this message look like an ARF report?" It asks four separate questions:

  1. Is the report syntactically an ARF message?
  2. Is the reporting system one that is authorized to send reports to this receiver?
  3. Is the report content plausible and safe to process?
  4. Is there enough independently verified evidence to justify an action?

The last question is the one most likely to be skipped. ARF fields are assertions made by the report generator. Even a well-formed report is not, by itself, proof that an authentication failure occurred.

What an ARF authentication-failure report contains

RFC 5965 defines the Abuse Reporting Format as a MIME message with a top-level multipart/report content type and report-type=feedback-report. A normal report has three parts:

  • a human-readable explanation
  • a message/feedback-report machine-readable part
  • a message/rfc822 copy of the original message, or a text/rfc822-headers copy of its headers

The third part is evidence, not a trusted instruction. It may be redacted, incomplete, or maliciously constructed. The human-readable part is even less suitable for automation because it is intended for people and can conflict with the structured fields.

RFC 6591 adds the auth-failure feedback type for reports about a particular authentication method. Depending on the failure, the machine-readable part can contain fields such as:

  • Feedback-Type: auth-failure
  • Auth-Failure: spf, signature, bodyhash, revoked, or another registered value
  • Authentication-Results
  • Original-Envelope-Id, Original-Mail-From, and Source-IP
  • Reported-Domain
  • DKIM-Domain, DKIM-Identity, and DKIM-Selector
  • SPF-DNS
  • Delivery-Result

These fields describe what the reporting ADMD claims it observed. User-Agent is documentation only and is trivially forged. Source-IP, Reported-Domain, and the Authentication-Results field inside the report are not a replacement for checks performed by the reporting system or for authentication of the report message itself.

There are two related report families worth keeping separate:

  • A complaint or abuse feedback loop generally uses Feedback-Type: abuse and reports a recipient complaint or other abuse signal.
  • An authentication-failure report uses Feedback-Type: auth-failure and describes a failed SPF or DKIM check. Current DMARC failure reporting also uses ARF and adds the dmarc failure type and Identity-Alignment, as specified in RFC 9991.

An ARF parser should accept only the report types it has a documented use for. Unknown feedback types and extension fields can be retained as uninterpreted evidence, but should not silently become business logic.

DMARC failure reports can contain message headers or a complete message and may expose personal or confidential data. DMARCPal does not process ruf reports, preserving privacy and keeping DMARC monitoring simple because this message-level channel is only sparsely useful in real-world deployments.

Draw the trust boundaries first

A robust deployment has more than one component. A useful shape is:

Internet SMTP
    |
    v
Dedicated report MX and mailbox
    |
    v
Raw-message quarantine and size gate
    |
    v
Source validation -> strict MIME parser -> normalized event queue
                                             |
                                             v
                                  reviewed policy actions

The public SMTP edge is untrusted. The mailbox or queue is a containment boundary, not a validation result. The parser is another boundary because MIME content, encoded data, and copied message headers are attacker-controlled input. Finally, the action worker needs its own authorization boundary so that a parser compromise cannot directly change DNS, delete campaigns, or alter every suppression list.

Keep raw mail and normalized events separate. The raw object is useful for a controlled investigation, while the normalized event should contain only the fields required for the next decision. Do not let downstream workers reparse arbitrary raw MIME each time they need one field.

Validate the source, not just the shape

There is no universal ARF trust mechanism. The ARF security considerations explicitly leave authentication and trust establishment to local policy. That means an allowlist based only on a claimed From: address is not a security control.

Use an out-of-band reporting relationship for each source that is allowed to trigger automation. Record the expected reporting domains, envelope addresses, DKIM signing domains and selectors where known, permitted report types, and the actions that source is allowed to influence. A source agreement can be narrow, for example, "this receiver may submit diagnostic events for this domain, but may not directly request subscriber deletion."

At the SMTP or message-ingest boundary, collect and evaluate:

  • SPF for the SMTP envelope sender, where an envelope identity exists
  • DKIM verification of the report message, including the signing domain and selector
  • DMARC alignment of the report message when the source supports it
  • the locally observed SMTP peer and Received chain, without treating message-supplied trace data as proof
  • the expected source identity from the out-of-band agreement

SPF and DKIM authenticate domain-level identities, not the truth of every ARF field. A passing DKIM signature on a report says that the signed report content was signed by that domain and was not altered after signing. It does not say the original message was abusive or that the reported authentication result was correct. Conversely, a report from a verifier whose own DKIM infrastructure is broken may fail to authenticate even when the report is legitimate. That is why authentication should produce a confidence and routing result, not a simplistic accept-or-trust flag.

S/MIME can provide stronger bilateral sender authentication when both parties can manage certificates and key rollover, but it is not a practical general Internet requirement. TLS is valuable for protecting a connection in transit; opportunistic SMTP TLS does not identify the report generator once the message is stored or forwarded.

Reject or quarantine reports when the source is unknown, the required source authentication fails, the source is not authorized for the destination domain, or the report type is outside the agreement. Do not make the parser more permissive to compensate for a failed trust decision.

Authenticate and authorize the receiver

The report mailbox is an inbound service. It should not be an ordinary shared inbox with a forwarding rule and a broad set of delegates.

Use a dedicated address and, where possible, a dedicated MX or inbound route. Disable automatic replies, forwarding, vacation messages, list expansion, and bounce generation for the report stream. An ARF report that triggers a reply can create a feedback loop, and an address that forwards to several destinations multiplies both privacy exposure and flood impact.

Protect access to the stored reports with a service identity and least privilege:

  • the SMTP edge may deposit messages but cannot read all stored evidence
  • the validator may read envelope metadata and raw messages, but cannot modify suppression policy
  • the parser may emit normalized events, but cannot call arbitrary administrative APIs
  • the action worker may perform only explicitly listed idempotent actions
  • investigators receive time-limited, audited access to raw content

If a report is handed from the mailbox to an internal HTTP or queue endpoint, authenticate that hop separately with mTLS, a narrowly scoped signed token, or an equivalent mechanism. Authorize the specific sender and operation, not just possession of a network route. Network location and an internal IP address are not sufficient authorization.

Parse as hostile MIME

ARF is deliberately extensible, and that flexibility is a parser attack surface. RFC 5965 says malformed ARF can be ignored or rejected, while its security section warns about extraordinarily large or intentionally malformed fields. Treat those recommendations as an engineering requirement.

Apply limits before full parsing:

  • maximum SMTP message size and maximum decoded MIME part size
  • maximum nesting depth, part count, header count, and line length
  • bounded base64 and quoted-printable decoding
  • bounded character-set conversion and decompression, if an integration permits compressed input
  • parser CPU and wall-clock timeouts
  • queue and disk quotas for both raw and normalized data

Require the top-level content type and report type you support. Require the expected machine-readable part and validate its required fields and multiplicity according to the applicable RFC. Reject duplicate singleton fields, conflicting aliases such as historic and current field names, invalid dates, invalid IP literals, overlarge incident counts, and malformed addresses rather than guessing.

Do not render HTML, execute attachments, open URLs, resolve reported domains, or decode content into a browser-connected analysis process during ingestion. Treat a message/rfc822 part as an inert byte sequence until a separate, isolated analysis step needs it. Strip or escape control characters before putting field values into logs. Never interpolate untrusted values into shell commands, SQL, filesystem paths, email headers, or alert templates.

Preserve the original bytes and validation results for investigation, but pass a typed internal record to business logic. A useful normalized record might include the validated report source, report type, auth-failure method, reported domain, source IP, original envelope ID, original message ID if present, validation outcome, and a reference to restricted evidence. It should not carry arbitrary header names as executable attributes.

Make actions idempotent and evidence-based

The same incident can produce retries, copies, and different report types. Message-ID is useful when present but is not guaranteed to be unique or honest. Original-Envelope-Id is also an assertion from the report generator. Use several fields when constructing an event key, for example:

hash(reporting-domain, report-type, auth-failure, reported-domain,
     original-message-id, original-envelope-id, source-ip, time-bucket)

Include a hash of the raw report for exact duplicate detection. Keep semantic deduplication separate from raw deduplication so a repeated report is not mistaken for a different event merely because a provider reformatted it. Choose the time bucket and fields based on the reporting source, and retain the original evidence when two reports collide.

Every downstream action should be safe to repeat. Applying a suppression should set a state with a reason and evidence reference, not append an unbounded duplicate row. Creating an incident should use a stable incident key. A report must never cause an irreversible action just because it is new to the queue.

Most importantly, do not let one unverified report:

  • change SPF, DKIM, or DMARC DNS records
  • disable a sender or campaign globally
  • delete an account or mailbox
  • send a notification to the alleged source
  • disclose the original message to a third party

Use ARF to prioritize investigation and to correlate with local sending logs. For high-impact actions, require a second signal, such as a matching local message ID, a known receiver agreement, an independent complaint event, or human approval.

Control duplicates, rates, and quotas

There are two flood paths. A hostile actor can send forged reports directly to the mailbox, or can send messages that cause legitimate receivers to generate reports back to the victim. RFC 6591 calls out both automatic generation and distributed report floods. Current DMARC failure-reporting guidance also requires report generators to rate-limit outgoing reports and recommends aggregation with the Incidents field. A receiver cannot control what every reporter does, so the consumer still needs hard limits.

Set quotas at multiple levels:

  • SMTP connections and message bytes per peer and per time window
  • accepted reports per authenticated reporting source
  • reports per reported domain, failure type, source IP, and sender agreement
  • raw storage, parser CPU, decoded-part bytes, and queue depth
  • normalized events and policy actions per hour

Use a token bucket or equivalent bounded rate limiter, with a global circuit breaker. When a source exceeds its budget, keep a small representative sample and counters, then shed excess work. Do not let a single source consume the entire queue. Keep a separate emergency path for authenticated, contractually important sources only if that path has its own quota.

Aggregation and sampling are not the same. Aggregation can preserve an Incidents count and a representative set of fields. Sampling discards detail. Make that loss visible in metrics and alerts. Never interpret a rate-limited stream as evidence that the underlying failure rate is low.

Stop forged loops and report amplification

The safest feedback loop is one that does not answer an ARF report. In particular:

  • do not auto-reply to the report mailbox
  • do not generate a DSN for a rejected report unless the mail architecture requires it and the path is designed for it
  • do not send an ARF report in response to an ARF report
  • use a controlled envelope sender for operational notifications, never the untrusted report's From: or Original-Mail-From
  • keep notification destinations fixed in configuration, not extracted from Reported-URI, Original-Rcpt-To, or message headers

The report itself may contain URLs, recipients, and sender addresses chosen by an attacker. Treat them as data. Never use them as destinations for a reply, webhook, callback, suppression confirmation, or escalation.

On the generation side, create reports only for an approved reporting relationship. Aggregate similar incidents, apply per-recipient quotas, and prefer a bounded diagnostic sample when a stream is exploding. RFC 9991 specifically recommends delaying and consolidating similar reports and rate-limiting outgoing reports to prevent denial of service.

Minimize and retain privacy-sensitive evidence

Failure reports can contain full headers, recipient addresses, message bodies, DKIM canonicalized data, URLs, and forwarding destinations. They can expose information about legitimate messages that merely failed authentication. RFC 9991 recommends limiting the scope and duration of failure reporting, controlling destinations, applying redaction, and using secure channels.

Before enabling any automated flow, decide:

  • which fields are required for the operational objective
  • whether headers are sufficient instead of a full message
  • which local parts, addresses, URLs, and body content must be redacted or tokenized
  • who can access raw evidence and how access is audited
  • how long raw reports, normalized events, hashes, and aggregate metrics are retained
  • how deletion, legal holds, and incident exports work

Encrypt raw reports at rest and in transit, keep them out of general support mailboxes, and separate retention of raw evidence from retention of aggregate counters. Hashing an address is not automatically anonymization if the input space is easy to guess, so use a keyed construction when a stable privacy-preserving correlation key is needed. Let legal and privacy requirements determine exact retention periods rather than copying a convenient number from another deployment.

Alert on the controls, not only the failures

An alert that says "ARF report received" is rarely useful. Monitor the safety properties of the pipeline:

  • authenticated versus unauthenticated report volume by source
  • rejected, quarantined, malformed, and parser-timeout counts
  • deduplication ratio and Incidents values
  • per-source and global quota consumption
  • raw storage, queue age, and action-worker lag
  • changes in DKIM signing identity or source IP for an agreed reporter
  • reports that claim a domain or message absent from local sending records
  • suppression or other action volume compared with independently verified events
  • delivery failures for the dedicated report mailbox

Alert on deviations from a source's baseline, a sudden new reporter, a source-authentication failure, quota exhaustion, and any action taken without the expected corroborating signal. Send alerts to a separately authenticated operations channel. Do not use an address copied from an incoming report as the alert destination.

A safe deployment workflow

Start with observation, not automatic enforcement:

  1. Inventory the domains, receivers, report types, and business actions that matter. Decide whether aggregate reporting is enough; message-level failure reports should have a specific diagnostic or security purpose.
  2. Establish an out-of-band agreement with each reporter. Document expected identities, signing domains, authorized report types, rate limits, privacy terms, and escalation contacts.
  3. Create a dedicated report address or MX route. Remove auto-replies and forwarding, restrict access, and confirm that it cannot affect ordinary mail flow.
  4. Capture raw reports into quarantine with strict size and storage limits. Verify SPF, DKIM, alignment, and source authorization before allowing a report into the parser queue.
  5. Run the parser in a sandbox with adversarial fixtures: duplicate fields, folded headers, invalid boundaries, huge base64 values, nested messages, malformed dates, conflicting identifiers, HTML, URLs, and attachments.
  6. Emit normalized events and metrics only. Compare them with local MTA logs and known test messages. Verify that duplicates are idempotent and that unknown or failed sources cannot create actions.
  7. Enable low-impact actions first, such as a ticket or dashboard event. Use a fixed quota and require a second signal for suppressions or incident escalation.
  8. Exercise flood controls and failure modes. Disconnect the parser, fill the queue, rotate the reporter's DKIM key, send malformed reports, and verify that the rest of mail operations remain healthy.
  9. Review privacy and retention with the people responsible for data protection and incident response. Then enable a narrow production scope with a rollback switch.
  10. Reassess reporter trust, parser dependencies, signing selectors, quotas, and action permissions on a schedule. A trust relationship that was correct during onboarding can become unsafe after a provider, route, or ownership change.

The desired failure mode is boring: an untrusted or excessive report is retained as limited evidence, counted, and quarantined. It does not trigger an outbound loop, expose a mailbox, or make a high-impact change.

Key takeaway

ARF automation is safe when the report is treated as hostile input carrying potentially useful, potentially false assertions. Authenticate and authorize the reporting source separately from parsing the format. Isolate the mailbox and parser, impose limits before decoding, deduplicate and rate-limit at several layers, minimize sensitive content, and require independent evidence before impactful actions.

That design turns authentication-failure reports into bounded security telemetry instead of a forged feedback loop or a report flood with administrative privileges.

Previous Post