1 June 2026 · 9 min read
Most people who reach p=reject assume the job is finished. The root domain is locked down, the dashboards are green, and forged mail claiming to come from yourcompany.com is being rejected at the gateway. That is real progress, and it protects the address most of your customers actually see. But there is a quiet gap that a determined spoofer will find within minutes: your subdomains. A domain that enforces p=reject at the root can still leave mail.yourcompany.com, news.yourcompany.com or invoices.yourcompany.com wide open, depending on exactly how your DMARC record is written.
This article explains why that happens, what the sp (subdomain policy) tag does, and how to close the gap without breaking the legitimate mail that flows from your subdomains. It assumes you already understand the basics of DMARC; if you do not, start with How DMARC works and the DMARC checker, then come back.
What the sp tag actually controls
A DMARC record published at _dmarc.yourcompany.com contains a policy tag, p, that tells receiving mail servers what to do with messages that fail DMARC for the organisational domain. The values are none, quarantine and reject.
The sp tag sets a separate policy specifically for subdomains of that organisational domain. It takes the same three values:
sp=nonemeans failing mail from subdomains is delivered normally and only reported.sp=quarantinemeans failing subdomain mail is sent to the spam or junk folder.sp=rejectmeans failing subdomain mail is rejected outright.
So a complete enforcing record might look like this:
v=DMARC1; p=reject; sp=reject; rua=mailto:reports@yourcompany.com
Here p=reject governs mail from yourcompany.com itself, and sp=reject governs mail from every subdomain that does not publish its own DMARC record. The two tags are independent. You can have p=reject with sp=none, or p=none with sp=quarantine, or any other combination. That independence is exactly where the gap hides.
You can generate a record with the right tags using the DMARC generator, and verify what is currently published with the DMARC checker.
The inheritance rule, and the trap inside it
DMARC, defined in RFC 7489, uses a simple inheritance model. When a receiver evaluates a message, it looks up the DMARC record for the exact subdomain in the From header first. If news.yourcompany.com has its own record at _dmarc.news.yourcompany.com, that record is used and nothing else matters. If there is no such record, the receiver walks up to the organisational domain, finds the record at _dmarc.yourcompany.com, and applies a policy from there.
This is where most people get caught out. When the receiver falls back to the organisational record, it does not apply p. It applies sp if sp is present, and only falls back to p if sp is absent.
Read that again, because it is the entire point of this article. The behaviour splits into two cases:
- If you publish
sp, subdomains use thespvalue. Your carefully chosenp=rejectis irrelevant to subdomains; what matters to them is whatever you put insp. - If you omit
spentirely, subdomains inherit thepvalue.
That second case is the safe default and the reason many records work fine without ever mentioning sp. A record of v=DMARC1; p=reject; rua=... with no sp tag does enforce reject on subdomains, because they inherit p.
The dangerous case is the half-finished migration. Imagine a record like this:
v=DMARC1; p=reject; sp=none; rua=mailto:reports@yourcompany.com
The root is at full enforcement. Every subdomain, however, is at sp=none, which means no enforcement at all. Anyone can send mail as billing.yourcompany.com or noreply.yourcompany.com and it will sail straight into inboxes, because the explicit sp=none overrides the p=reject you were relying on. The checker will show a green p=reject and you will feel protected. You are not.
Why a spoofer targets subdomains
Attackers read DNS too. When they find your organisational domain enforcing reject, the natural next move is to test subdomains. There are two flavours of attack that the subdomain gap enables.
The first is non-existent subdomain spoofing. Nothing stops an attacker putting accounts-update.yourcompany.com in the From header of a phishing email, even though you have never created that subdomain and it has no DNS records of its own. Receivers will look for _dmarc.accounts-update.yourcompany.com, not find it, fall back to the organisational record, and apply sp. If sp is none or missing in a way that resolves to weak enforcement, the forged mail is delivered. To a human recipient, accounts-update.yourcompany.com looks at least as trustworthy as the bare domain, sometimes more so, because it reads like an official system address.
The second is abandoned or forgotten subdomains. Marketing spun up promo.yourcompany.com two years ago on a platform you no longer use. A developer created staging.yourcompany.com. These have a habit of accumulating, and each one is a potential From address. Without a subdomain policy, each is a free pass for spoofing.
The lesson is that root-domain enforcement protects exactly one address. Subdomain policy is what protects the rest of the namespace, including subdomains you have never even thought about.
Should sp match p, or differ from it?
In a steady state, the simplest and safest posture is to make sp match p. If your root is at reject, set sp=reject. If you have explicitly written an sp tag, this removes any ambiguity and closes the non-existent-subdomain hole completely.
There is, however, a legitimate reason to make them differ, and it is about staged rollout rather than carelessness. Subdomains often carry their own distinct mail streams that are not yet aligned. A common, sane interim posture during a migration is:
v=DMARC1; p=reject; sp=none; rua=mailto:reports@yourcompany.com
This is the very record I called dangerous above, and it is dangerous as a permanent state. As a deliberate, temporary, monitored state it can be the correct choice. The reasoning is that you have already verified and aligned the root domain's senders, but you have not yet finished checking every subdomain sender. Rather than break subdomain mail you have not audited, you hold subdomains at none and keep collecting reports while the root stays protected.
The critical word is temporary. An sp=none under a p=reject should be a stage in a plan with a date attached, not a setting that quietly lives in your DNS for three years. The honest failure mode here is forgetting. Teams reach p=reject, celebrate, and never revisit the sp=none they set as a stepping stone. This is one of the most common findings in a real-world audit: full enforcement on paper, wide-open subdomains in practice.
How to find out where you stand right now
Before you change anything, find out what is actually published and what is actually flowing. Three steps:
- Read your current record. Run the DMARC checker against
yourcompany.com. Note whether ansptag is present, and if so, its value. If there is nosptag andpis atquarantineorreject, your subdomains are already inheriting enforcement, and you are in reasonable shape. Ifspis present and weaker thanp, you have a gap.
- Look at your aggregate reports. Your
ruareports show the source IPs and, crucially, theFromdomains of mail being evaluated. This is where you discover which subdomains are actually sending. You will often find subdomains you forgot existed. The DMARC report analyzer parses these XML reports into something readable, and reading your first DMARC report walks through what the fields mean.
- List your active subdomain senders. For each subdomain that legitimately sends mail (transactional platforms, marketing tools, ticketing systems), confirm it has aligned SPF and DKIM. You can check individual pieces with the SPF checker and the DKIM checker. A subdomain that is not aligned will start failing the moment you tighten
sp, so you must know about it first.
If a subdomain has a substantial, complex mail stream of its own, it can be cleaner to give it a dedicated DMARC record at _dmarc.subdomain.yourcompany.com rather than governing it through the parent's sp. The trade-offs are covered in Do I need a DMARC record for each subdomain?.
Closing the gap safely, step by step
The goal is to get to sp=reject (or to match whatever your p enforcement is) without bouncing legitimate subdomain mail. Here is the sequence that works in practice.
Step one: enforce the root first. Do not try to tackle subdomains while the organisational domain is still at p=none. Get p to quarantine, then reject, with all your primary senders aligned. If you are still wrestling with the root, why p=none is a false sense of security explains why you cannot stop there.
Step two: hold subdomains while you audit. During the root rollout, an explicit sp=none lets you protect the root immediately while you gather subdomain data. Keep it only as long as you are actively auditing.
Step three: align every subdomain sender. For each subdomain found in your reports, make sure the sending service passes SPF with alignment or, better, signs with DKIM under that subdomain. DKIM alignment is more robust than SPF alignment because it survives forwarding, and it is what lets a subdomain pass DMARC reliably. If you hit the SPF ten-lookup limit while doing this, SPF PermError and the 10-lookup limit explains the fix, and how SPF flattening works covers the mechanism.
Step four: tighten in stages. Move sp from none to quarantine first. Watch reports for a week or two. If nothing legitimate is being quarantined, move sp to reject. This mirrors the staged approach you used for p, and for the same reason: it gives you a safety net where failures land in spam rather than being bounced.
Step five: handle exceptions with dedicated records. If one subdomain genuinely cannot reach alignment yet, do not hold your entire sp back for it. Publish a specific record at _dmarc.thatsubdomain.yourcompany.com with its own softer policy, and let the rest of your subdomains go to reject via sp. A subdomain-specific record overrides inheritance entirely for that subdomain.
A worked example of the end state:
; organisational record
_dmarc.yourcompany.com. TXT "v=DMARC1; p=reject; sp=reject; rua=mailto:reports@yourcompany.com; ruf=mailto:forensics@yourcompany.com; fo=1"
; exception for one lagging subdomain
_dmarc.legacy.yourcompany.com. TXT "v=DMARC1; p=quarantine; rua=mailto:reports@yourcompany.com"
Everything except legacy is fully enforced. legacy sits at quarantine until its sender is sorted, then you delete its record and let it fall back to sp=reject like everything else.
A note on alignment and subdomains
It is worth being precise about one subtlety. DMARC alignment compares the domain in the From header with the domain that SPF or DKIM authenticated. In relaxed alignment (the default), a From of news.yourcompany.com aligns with an SPF or DKIM domain anywhere under yourcompany.com. In strict alignment (aspf=s or adkim=s), the domains must match exactly.
This matters for subdomains because relaxed alignment is forgiving across the subdomain boundary, which is usually what you want, while strict alignment is not. If a subdomain's mail is failing DMARC despite passing SPF or DKIM, an over-tight strict alignment setting is a frequent cause. The glossary entry on subdomain policy and the broader glossary cover the alignment tags in more depth.
The practical takeaway
A green p=reject is necessary but not sufficient. It protects your organisational domain and nothing more. The full picture is:
- If you have no
sptag, subdomains inheritp, so a root atrejectalready enforcesrejecton subdomains. Good, but confirm it is intentional. - If you have an explicit
spweaker thanp, your subdomains are a spoofing surface, including subdomains that do not exist. Treat that as a temporary migration state with a deadline, never a permanent one. - The end goal for most organisations is
spmatchingpat enforcement, with dedicated records only for genuine exceptions.
Check what you have published today with the DMARC checker, confirm the sp value, and look at your aggregate reports to see which subdomains are actually live. If you would rather not hand-edit DNS and track every subdomain sender yourself, DMARC Engine hosts your records and runs the staged rollout for you, root and subdomains together, taking you safely from p=none to a fully enforced reject and sp=reject without an email outage. You can also set up emailed monitoring with change alerts so that if anyone ever loosens sp again, you hear about it the same day.