Forwarded to devs Possible DMARC Bypass - Spoofed MAILER-DAEMON Return-Path Not Rejected

nethubonline

Regular Pleskian
Username:

TITLE

Possible DMARC Bypass - Spoofed MAILER-DAEMON Return-Path Not Rejected

PRODUCT, VERSION, OPERATING SYSTEM, ARCHITECTURE

Plesk 18.0.76, AlmaLinux release 9.4

PROBLEM DESCRIPTION

Inbound spoofed emails are accepted even when SPF, DKIM, and DMARC are properly configured (including DMARC policy set to p=reject), if the attacker forges the envelope sender as MAILER-DAEMON.

Spammers can impersonate system-generated bounce messages by setting:
  • Return-Path: <MAILER-DAEMON> (empty/null sender)
  • From: an address within the protected domain (e.g., [email protected])
These messages are delivered to users instead of being rejected, allowing spoofing despite strict DMARC policy.

STEPS TO REPRODUCE

  1. Configure a domain in Plesk with:
    • DKIM Verify incoming mail: enabled
    • Enable SPF spam protection to check incoming mail: enabled
    • Enable DMARC to check incoming mail: enabled
    • DMARC DNS record set to "v=DMARC1; p=reject; sp=none;"
    • SPF DNS record set to "v=spf1 a mx -all"
  2. Send an email to a mailbox on that domain using a script that forges the envelope sender as MAILER-DAEMON.
    Example PHP script:


    PHP:
    <?php
    
    $to = "[email protected]";
    $subject = "Test Message";
    $message = "This is a spoofing email.";
    $headers = [];
    $headers[] = "From: [email protected]";
    $headers[] = "Reply-To: [email protected]";
    
    mail(
        $to,
        $subject,
        $message,
        implode("\r\n", $headers),
        "-f MAILER-DAEMON"
    );

  3. Observe whether the message is accepted by the mail server.

ACTUAL RESULT

The spoofed message is accepted and delivered to the recipient's mailbox.

DMARC policy (p=reject) is not enforced for messages using an empty or MAILER-DAEMON envelope sender.

EXPECTED RESULT

The message should be rejected during SMTP reception because:
  • The From domain is spoofed
  • Authentication checks fail alignment
  • DMARC policy is set to reject
Forged bounce messages should not bypass domain authentication protections.

ANY ADDITIONAL INFORMATION

This behavior allows attackers to impersonate system notifications or bounce messages, which may lead to spam delivery or phishing attempts.

The issue appears related to how null senders (<>) or MAILER-DAEMON envelope senders are treated during DMARC evaluation.

YOUR EXPECTATIONS FROM PLESK SERVICE TEAM

Confirm bug
 
According to our team the issue on your end likely appears due to "SPF checking mode" (Tools & Settings > Mail Server Settings) configuration. During the tests, the engineers set it to "Reject mail when SPF does not resolve to “pass"" and they were unable to replicate the issue. Could you please test in on your end as well?
 
We have now performed the additional tests as recommended, changing the SPF checking mode in Tools & Settings > Mail Server Settings > SPF spam protection.

Results summary:

1. With mode set to "Reject mail when SPF resolves to 'fail' (deny)" (Our original and preferred settings):The spoofed email with forged envelope sender <MAILER-DAEMON> and fake From header still bypasses rejection and gets delivered to the inbox.Key log lines:

spf[53051]: BE4494069C: Failed to query MAIL-FROM: Host 't4.plesk.com' not found.psa-pc-remote[49714]: BE4494069C: spf: stderr: PASSdmarc[53055]: BE4494069C: Unable to store SPF result into DMARC library: 'Function called with nothing to parse'dmarc[53055]: BE4494069C: Unable to store SPF/DKIM results into DMARC librarypostfix/pipe[53000]: BE4494069C: to=<[email protected]>, relay=plesk_virtual, ... status=sent (delivered via plesk_virtual service)

→ SPF does not produce a hard "fail", DMARC parsing fails early → no DMARC enforcement → delivery succeeds.

2. With mode set to "Reject mail when SPF does not resolve to 'pass'" (the stricter mode):The same spoofed email is now properly rejected at the SMTP stage (before DMARC processing even starts).Key log lines:psa-pc-remote[49714]: 182924069C: spf: stderr: DATA REPLY:550:5.7.23 SPF validation failed.psa-pc-remote[49714]: 182924069C: spf: stderr: REJECTpostfix/cleanup[52996]: 182924069C: milter-reject: END-OF-MESSAGE ... 5.7.23 SPF validation failed.; from=<> ...→ This closes the spoofing in the SPF checking stage

This confirms the issue only occurs in the "fail (deny)" mode due to how SPF errors/lookups for null senders are handled (treated as non-fail → DMARC bypass).

However, the stricter mode ("does not resolve to 'pass'") is not a solution and will cause serious problems:

From Plesk documentation and community threads, this mode rejects any SPF result that is not an explicit "pass". That includes:
  • softfail (~all) — often used legitimately by large providers (e.g., many domains use ~all for transitional policies, e.g. gmail.com, live.com)
  • neutral (no policy or ?all, e.g. yahoo.com)
  • permerror (invalid SPF syntax/record)
  • temperror (temporary DNS issues)
  • Cases with no SPF record at all ("none")
This could lead to false positives and legitimate mail rejection, such as:
  • Forwarded emails or mails from third-party services with softfail/neutral results
  • Temporary DNS outages causing temperror → deferred or bounced mail
In contrast, the "fail (deny)" mode only rejects explicit hard fails (-all match), which is generally safer for deliverability while still blocking obvious forgeries. Would a proper fix involve improving the DMARC handler to robustly parse SPF results even when MAIL-FROM is null/MAILER-DAEMON (so DMARC can still enforce p=reject regardless of SPF quirks)?
 
Thank you for the update. According to the log, SPF didn’t result with “failed", but SPF checking process itself failed to complete. Therefore, considering the current mode selected, the message passed and this is expected behavior.
 
We understand that in the "Reject mail when SPF resolves to 'fail' (deny)" mode, only an explicit SPF "fail" triggers rejection. Since the SPF check failed to complete (lookup error: "Host 't4.plesk.com' not found" + "Failed to query MAIL-FROM"), it didn't produce a "fail" verdict, so the message passed — and that's expected per the current SPF logic.

However, this leads to a concerning outcome for domains with strict DMARC p=reject:The DMARC then fails with:"Unable to store SPF result into DMARC library: 'Function called with nothing to parse'""Unable to store SPF/DKIM results into DMARC library"→ DMARC evaluation is skipped entirely → no policy enforcement, even though the Header From is forged and alignment should fail.

Per RFC 7489 (DMARC), alignment is checked against the Header From domain (independent of envelope sender), and p=reject should cause rejection if SPF/DKIM don't pass/align. As a reference, the same spoofing test toward Gmail and Yahoo did give rejection, with DMARC checking failing:

Gmail:
"said: 550-5.7.26 Unauthenticated email from gmail.com is not accepted due to domain's 550-5.7.26 DMARC policy. Please contact the administrator of gmail.com domain 550-5.7.26 if this was a legitimate mail. To learn about the DMARC initiative, 550-5.7.26 go to 550 5.7.26 Control unauthenticated mail from your domain - Google Workspace Admin Help"

Yahoo:
"said: 554 5.7.9 This mail has been blocked because it failed authentication checks against the sending domains DMARC policy. See SMTP Error Codes | Sender Hub for more information."

For null/MAILER-DAEMON envelope senders (common in legitimate bounces but easy to forge), SPF per RFC 7208 typically yields permerror, temperror, neutral, or none — never a clean "pass". So why does this cause the DMARC library to fail parsing entirely instead of treating it as non-pass/fail?

This creates a low-effort bypass: attackers can spoof any @mydomain.com From address by just setting Return-Path: <MAILER-DAEMON> (or <>) — no need to beat SPF or DKIM.

While the stricter mode ("Reject mail when SPF does not resolve to 'pass'") blocks these spoofs (as my tests confirmed), it also rejects legitimate mail with softfail (~all, common on many domains), neutral, permerror (bad syntax), temperror (temp DNS), or no SPF record — which increases false positives and hurts inbound deliverability.

Questions:
  1. Is the DMARC handler's inability to parse/store SPF results on lookup errors (especially for null senders) by design, or could it be improved to default to "fail/non-aligned" in such cases for p=reject enforcement?
  2. Are there plans to address this edge case so strict DMARC works without forcing the very broad stricter SPF mode?
This seems like a gap that reduces the effectiveness of DMARC p=reject on Plesk servers. We'd appreciate any insights or if a bug report/ticket has been created.
 
Thank you for the update. I will consult further with our team and follow-up. An internal case (PPS-18773) has been created for the bug report and all details provided from me thus far originate from it. In the meantime, could you please provide a full raw SMTP headers of a sample message.
 
Sure, please find the email header below. Please note that this email was sent using PHP code similar to the one shown above.

Code:
Return-Path: <MAILER-DAEMON>
X-Original-To: [email protected]
Delivered-To: [email protected]
Received: from t4.plesk.com (3106.example.net [1.2.3.106])
    by plesk.test (Postfix) with ESMTPS id BE4494069C
    for <[email protected]>; Thu, 5 Mar 2026 12:28:57 +0800 (HKT)
Authentication-Results: plesk.test;
    spf=none (sender IP is 1.2.3.106) smtp.mailfrom= smtp.helo=t4.plesk.com
Received-SPF: none (plesk.test: no valid SPF record)
Received: by t4.plesk.com (Postfix, from userid 10001)
    id AB18B31E3C; Thu, 5 Mar 2026 12:28:57 +0800 (HKT)
To: [email protected]
Subject: Test Message
From: [email protected]
Reply-To: [email protected]
Message-Id: <[email protected]>
Date: Thu, 5 Mar 2026 12:28:57 +0800 (HKT)
 
Back
Top