Skip to main content

The DMARCbis np tag and its DNSSEC blind spot: what every admin must check

By CaptainDNS
Published on July 7, 2026

The DMARCbis np tag meant to block non-existent subdomains, bypassed by a NOERROR response on a DNSSEC zone using compact denial
TL;DR
  • The DMARCbis np tag (RFC 9989, May 2026) applies a policy to subdomains that do not exist in your DNS. It is the new weapon against the spoofing of fabricated subdomains.
  • np relies on one thing only: the NXDOMAIN response code. The DMARC evaluator triggers it only if the DNS confirms, through a strict NXDOMAIN, that the name does not exist.
  • Many modern DNSSEC zones answer NOERROR, not NXDOMAIN. To save on signatures, they practice compact denial of existence or "black lies". The evaluator then believes the subdomain exists and falls back to sp.
  • The result: np=reject is neutralized without a single error message as soon as sp is more permissive. A spoofed email from invoice.captaindns.com gets through.
  • The fix takes one line of configuration: make sp as strict as np, and publish explicit DMARC records on your legitimate sending subdomains.

DMARCbis is a published standard. RFC 9989, 9990 and 9991 (May 2026) replace the old RFC 7489 and introduce the np tag, a clean answer at last to an old hole in DMARC: the subdomain that was never declared. Before np, an attacker could send from invoice.captaindns.com with no policy applying, because that name existed nowhere in the zone. The np tag closes that door, in theory.

In theory. Because np relies on a precise DNS signal, the NXDOMAIN code, and that signal has quietly vanished from a large share of the DNSSEC zones actually deployed. On a zone signed by Cloudflare, AWS Route 53, Microsoft Azure DNS or NS1, a query for a non-existent name does not return NXDOMAIN. It returns NOERROR. And to a DMARC evaluator, NOERROR means "this subdomain exists". So it applies sp, not np. If sp is more permissive, the protection evaporates.

Verdict. Who is affected: any domain that relies on np being stricter than sp, hosted on a DNSSEC zone using compact denial. Severity: silent degradation, not an outage. Nothing breaks, no log lights up, your legitimate mail leaves as before. Only the anti-spoofing promise of np is hollowed out. This is not a DNSSEC flaw: DNSSEC does exactly what it is asked to do. It is a DMARCbis assumption that no longer holds against modern DNS.

Check your domain's DMARCbis and DNSSEC compatibility

What is the np tag for, and how does it differ from sp?

The np tag defines the DMARC policy applied to subdomains that do not exist in the DNS, whereas sp defines the policy for subdomains that do exist. The difference comes down to a single word: non-existent. That is where the whole problem lies.

Let's revisit the problem np solves. Your domain captaindns.com publishes its mail servers, its SPF and DKIM records, a strict DMARC policy. But an attacker does not need a subdomain you declared. They make their own. They send a fake invoice from invoice.captaindns.com, a name you never created in your zone. Under DMARC v1, no policy reliably reached down to that level for undeclared names, and the spoofing slipped under the radar. The np tag fills exactly that hole. For all the context on the standard, see our DMARCbis guide.

DMARCbis therefore distinguishes three scopes, with a strict fallback chain:

TagApplies toValuesFallback if absent
pThe organizational domain itselfnone / quarantine / rejectNone (required)
spSubdomains that exist in the DNSnone / quarantine / rejectFalls back to p
npNon-existent subdomains (NXDOMAIN)none / quarantine / rejectFalls back to sp, then p

A typical use case: p=none, sp=none, np=reject

The most common configuration among organizations that deploy np looks like this:

_dmarc.captaindns.com. 3600 IN TXT "v=DMARC1; p=none; sp=none; np=reject; rua=mailto:dmarc@captaindns.com"

The administrator's logic is reasonable. The root domain is in monitoring mode (p=none), because you need to watch legitimate traffic before tightening. The real subdomains too (sp=none), while you map out the services that send. But nobody has a legitimate reason to use subdomains that do not exist: might as well reject them right away (np=reject). That is the right instinct. The problem is not the logic. The problem is that, on a modern DNSSEC zone, this np=reject may never fire.

Keep the fallback mechanics in mind: np is consulted only if the receiver has established that the subdomain does not exist. Otherwise, it applies sp. The entire flaw hangs on that "has established that the subdomain does not exist".

How does DMARCbis decide that a subdomain does not exist?

DMARCbis treats a subdomain as non-existent only when the DNS returns the NXDOMAIN code. It is a strict criterion, inherited from a DNS principle formalized by RFC 8020: "nothing underneath". If a name returns NXDOMAIN, then that name and anything that might exist below it do not exist. The DMARC receiver relies on this guarantee to choose between sp and np.

The word "NXDOMAIN" here is anything but incidental. It does not mean "I found nothing". It means precisely "this name does not exist in the zone". And DNS distinguishes two situations of absence that people often conflate.

The difference between NXDOMAIN and NODATA

Two DNS responses mean "absence", but they do not say the same thing. The DMARC receiver reacts to the first one only.

  • NXDOMAIN (status code NXDOMAIN): the name itself does not exist. No record of any type at that name. This is what DMARCbis expects in order to trigger np.
  • NODATA (status code NOERROR, empty answer section): the name exists, but not for the requested type. For example, blog.captaindns.com has an AAAA record but no MX. The MX query returns NOERROR with no data. The name exists. np does not apply.

The distinction is perfectly logical in classic DNS. An attacker sending from a fabricated subdomain triggers an NXDOMAIN, because the name was never created. np bites. All good. The slippage happens when the zone is signed with DNSSEC and decides to never return NXDOMAIN again.

The tightening introduced by DMARCbis

A historical detail explains why the flaw is wider than people think. The earlier experimental extension, RFC 9091 (PSD DMARC), was more tolerant: to judge a subdomain's existence, it also accepted an absence of data on the A, AAAA and MX types, not just a pure NXDOMAIN. In other words, a NODATA on those types counted as "this subdomain does not receive mail".

DMARCbis tightened that test. RFC 9989 relies on NXDOMAIN alone as the signal of non-existence. This choice makes the standard cleaner on paper: a single, type-unambiguous criterion. But it removes the safety net that, under RFC 9091, would have caught some of the DNSSEC zones that answer NOERROR. The tightening, meant for rigor, is precisely what opens the blind spot against compact denial.

What is compact denial of existence?

Compact denial of existence is a DNSSEC technique that proves a name's non-existence by returning NOERROR with a single NSEC record synthesized on the fly, instead of the classic NXDOMAIN. Many large signed DNS hosts have adopted it for one simple reason: cost.

Proving an absence in DNSSEC is expensive. The traditional method (NSEC or NSEC3) requires returning records that bracket the requested name in the zone's canonical order, each accompanied by its RRSIG signature. For a service that signs millions of zones and sees floods of queries for non-existent names (scans, typos, probes), that means signatures to compute, store and transmit continuously. Compact denial sidesteps the problem: instead of digging up the real neighbors, the server fabricates a minimal NSEC interval around the requested name on the fly, signs it once, and answers NOERROR. Less computation, fewer bytes on the wire, a single signature.

To signal that the absence is real and not a mere NODATA, the technique marks the response with a pseudo-type named NXNAME (type 128). A resolver that understands this marker knows that "the name does not exist" hides behind this NOERROR. The catch: this translation stays inside the resolver, it does not travel up to the DMARC evaluator as an NXDOMAIN.

The CO flag that could change everything

The specification provides a safeguard, in theory. An optional resolver-side flag, "CO" (Compact Answers OK), lets the resolver announce that it handles compact denial and, in return, reconstruct a real NXDOMAIN for its client when the response carries the NXNAME marker. On paper, this mechanism closes the blind spot.

In practice, nobody enables it. The major public resolvers do not set this flag by default, and the DMARC evaluator running behind them receives the raw NOERROR. The fix exists in the text, not in real traffic.

Going further. NSEC and NSEC3 are the two historical mechanisms for proving absence in DNSSEC; NSEC3 hashes names to make zone enumeration harder, NSEC exposes them in the clear. Resolvers' aggressive caching (RFC 8198) allows an NSEC proof to be reused to answer other non-existent names without a query, but it does not restore the NXDOMAIN code either when the proof is a synthetic NSEC in NOERROR. Caching speeds things up, it fixes nothing for np.

The step-by-step scenario: when NOERROR makes np fall back to sp

Here is the full sequence, from the fraudulent send to delivery. The captaindns.com zone is signed with compact denial and publishes p=none; sp=none; np=reject. An attacker sends a fake invoice from invoice.captaindns.com, a subdomain that does not exist in the zone.

  1. The email arrives at the receiver with From: accounting@invoice.captaindns.com. SPF and DKIM authentication fails, which is expected: the attacker does not control the domain.
  2. The receiver runs the DMARCbis tree walk and climbs the labels until it finds the policy. It discovers it on _dmarc.captaindns.com: p=none; sp=none; np=reject.
  3. It must now decide: does this subdomain invoice.captaindns.com exist or not? The choice between sp (existing) and np (non-existent) depends on the answer.
  4. It queries the DNS for invoice.captaindns.com. The zone is signed with compact denial.
  5. The response comes back as NOERROR, with a synthesized NSEC carrying the NXNAME marker. The status code, the one the DMARC evaluator reads, is NOERROR, not NXDOMAIN.
  6. The receiver concludes that the subdomain exists. To it, NOERROR means presence. It discards np and selects sp.
  7. It applies sp=none. The fake invoice is delivered. The published np=reject was never consulted.

Seven steps, no error, no anomaly log. The administrator published np=reject in good faith and believes their non-existent subdomains are protected. They are not.

The observation is reproducible. Here is what a direct query for a non-existent name returns on a zone signed by Cloudflare:

$ dig +dnssec +norecurse randomabc123.cloudflare.com A @ns3.cloudflare.com
;; ->>HEADER<<- opcode: QUERY, status: NOERROR
randomabc123.cloudflare.com. IN NSEC \000.randomabc123.cloudflare.com. RRSIG NSEC TYPE128

The status is NOERROR. The NSEC covers a minimal interval (\000.randomabc123...) and the presence of type 128 (NXNAME) confirms compact denial. A DMARC evaluator sitting behind a classic resolver will see this NOERROR as-is.

On a compact denial zone, the NOERROR response makes DMARC fall back from np=reject to sp=none and the spoofed email gets through

For contrast, a signed zone that answers correctly:

$ dig +dnssec randomabc123.fbi.gov A
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN

Status NXDOMAIN, absence proof in NSEC3. Here, np fires normally. Same protocol family, opposite behavior. The DNS provider makes all the difference.

Who is really affected by this blind spot?

Three conditions must be met at the same time for the flaw to bite. If one is missing, your np stays honored. This is what many articles leave unsaid: the problem is neither universal nor inevitable.

Three conditions must be met

  1. Your policy publishes np stricter than the sp fallback. If np and sp are identical, there is nothing to lose: whether the receiver applies one or the other, the result is the same.
  2. Your zone is DNSSEC signed and practices compact denial or "black lies". An unsigned zone, or one that is signed but returns a real NXDOMAIN, does not pose this problem.
  3. The receiver's DMARC evaluator trusts the response code. This is the default behavior of nearly all implementations: they read NOERROR versus NXDOMAIN, not the NXNAME pseudo-type.

The nuance everyone misses: np versus sp

The decisive point: np is only defeated if it is stricter than sp. As long as the receiver falls back to sp, it is the value of sp that decides the fate of the spoofed email.

Published policyWhat np promisesApplied on a compact denial zoneExposed?
sp=none; np=rejectReject bogus subdomainssp=none: the mail gets throughYes, gaping hole
sp=quarantine; np=rejectRejectsp=quarantine: spam instead of rejectPartial
sp=reject; np=rejectRejectsp=reject: reject anywayNo
sp absent, p=reject, np=rejectRejectFalls back to p=rejectNo

The bottom rows are your way out. If sp (or its fallback) is already as strict as np, the blind spot has no effect. That is the basis of the fix.

The wildcard trap

Compact denial is not the only way to neutralize np. A DNS wildcard does it too, and without any DNSSEC. If your zone contains *.captaindns.com, then any name under captaindns.com returns a positive response: the wildcard fabricates existence for everyone. A subdomain you never declared now "exists" from the DNS's point of view, so np never applies and the receiver falls back to sp. A broad A or AAAA wildcard cancels your np just as surely as a compact denial zone.

On the hosting side, our own dig tests, which you can reproduce, yield the following table. Several of the largest managed DNS services answer NOERROR instead of NXDOMAIN on the zones they sign:

DNS hostSigned domain testedResponse to non-existent namenp honored?
Cloudflarecloudflare.comNOERROR + NSEC with NXNAME (type 128)No
NS1 (IBM)ns1.comNOERROR + NSEC with NXNAMENo
AWS Route 53login.govNOERROR + minimal NSEC, no NXNAMENo
Azure DNSoffice.com, hhs.govNOERROR + minimal NSEC, no NXNAMENo
Google Cloud DNSfbi.govNXDOMAIN (NSEC3)Yes

Two takeaways. First, two distinct variants break np. Strict compact denial with the NXNAME marker (Cloudflare, NS1) and the older "black lies", a bare NOERROR with no NXNAME (Route 53, Azure). The variant does not matter: the common denominator is the code, NOERROR instead of NXDOMAIN. That widens the perimeter significantly. Second, it is not inevitable: Google Cloud DNS returns a classic NXDOMAIN and lets np work. The provider counts.

A word of honesty on scope. We put forward no percentage: measuring the exact prevalence of compact denial zones would require a global sweep we did not conduct. But Cloudflare is among the biggest DNS hosts in the world, and Route 53 as well as Azure DNS weigh heavily in enterprise infrastructure. When four players of that caliber return NOERROR on their signed zones, a large share of the DNSSEC zones actually deployed is affected. For Oracle Cloud DNS and Dyn, we did not observe an exploitable signed zone: we place them in neither camp.

Decision tree: am I affected by the np blind spot on DNSSEC depending on my provider and my sp policy

How to check whether your np is honored?

Three checks are enough to know whether your np is actually applied. Each answers one of the three conditions of the flaw. Count on five minutes.

Step 1: is your zone DNSSEC signed?

Start with the simplest. If your zone is not signed, the compact denial blind spot does not touch you (still, watch out for the wildcard trap seen above). Check for the presence of DNSKEY and DS records with the CaptainDNS DNSSEC checker, or on the command line:

dig DNSKEY captaindns.com +short
dig DS captaindns.com +short

A signed zone returns at least one DNSKEY key and, on the parent side, a DS record. Signed zone: move on to step 2. Unsigned zone: step 3 is still useful for the wildcard case.

Step 2: does a bogus subdomain return NXDOMAIN or NOERROR?

This is the central test. Query a name you never created and read the status code, not the data:

dig +dnssec a-name-that-does-not-exist-9x7q.captaindns.com A

Spot the ;; ->>HEADER<<- line. Two possible outcomes:

  • status: NXDOMAIN: perfect, your np fires normally. You are in the Google Cloud DNS case.
  • status: NOERROR: your zone hides the non-existence behind a NOERROR. Your np falls back to sp. Move on to step 3 to measure your real exposure.

Test from a public resolver while you are at it, because that is what mail receivers see. Our trials confirm that 8.8.8.8, 1.1.1.1 and 9.9.9.9 relay the NOERROR without reconstructing NXDOMAIN. With the CO flag not enabled, the downstream DMARC evaluator does receive a NOERROR.

Step 3: is np stricter than sp?

Last question, the most decisive. Retrieve your record and compare np to sp (and to the p fallback if sp is absent):

dig TXT _dmarc.captaindns.com +short

Match the values against the table in the previous section. If np is stricter than the sp fallback, and step 2 returned NOERROR, your protection of non-existent subdomains is neutralized. To read the full syntax and spot a malformed tag, run the record through the DMARC record checker. If np and the fallback are already at the same level, breathe easy: the blind spot has no grip on you.

How to secure your subdomains right now?

The fix does not depend on a future patch to DNS or from the IETF. You deploy it today, on the configuration side, by making your policy indifferent to whether np can be ignored. The principle: never let np alone carry a protection that sp does not provide.

The belt-and-suspenders recipe

Align sp with np. If you want to reject non-existent subdomains, also reject existing but illegitimate subdomains, and make it your fallback:

_dmarc.captaindns.com. 3600 IN TXT "v=DMARC1; p=reject; sp=reject; np=reject; rua=mailto:dmarc@captaindns.com"

With sp=reject, it does not matter whether the receiver believes the subdomain exists or not: in both cases it rejects. Compact denial no longer has any grip. This is the only configuration that closes the blind spot regardless of your DNSSEC zone's behavior. If your root domain is not ready for p=reject, you can keep p softer, but keep sp and np at the same strict level.

Publish records on your sending subdomains

sp=reject blocks anything not explicitly authorized. Your subdomains that send legitimately (newsletter.captaindns.com, notifications.captaindns.com) must therefore carry their own authentication setup and, ideally, their own DMARC record. First map your senders through the rua aggregate reports, then publish a dedicated record for each before tightening sp. This inventory is also what saves you from mistakenly rejecting an internal service.

A clean record, with consistent p, sp and np, is generated and validated effortlessly. The DMARCbis migration tool takes your existing record and brings it up to standard without breaking v=DMARC1 backward compatibility.

Your DNS provider choice matters

The absence-proof behavior is not configurable at most managed hosts: it is imposed by the service. If you require np to work on the receiver side without depending on sp, your provider's NXDOMAIN behavior becomes a selection criterion in its own right, on par with latency or price. This is no reason to flee Cloudflare or Route 53, whose advantages remain real. It is a reason to know their answer to a non-existent name, and to configure your sp accordingly. As long as sp is aligned with np, the provider stops being a problem.

Where does the IETF stand on this?

As of today, no solution is settled. The tension between the np tag and compact denial of existence has been raised within the IETF dmarc working group, but it has not yet led to a normative fix, and RFC 9989 does not address the question. That is one more reason to secure things on the configuration side, without waiting.

Three avenues are circulating, none decided:

  • Read the NXNAME pseudo-type. DMARC libraries could learn to interpret the NXNAME marker (type 128) as an NXDOMAIN, which would restore np for strict compact denial zones. That would leave out the "black lies" without NXNAME, like those from Route 53 or Azure.
  • Deploy the CO flag. The ecosystem could generalize enabling the Compact Answers OK flag on the resolver side, to reconstruct NXDOMAIN upstream of the DMARC evaluator. That assumes broad coordination that nothing signals in the short term.
  • Reintroduce NODATA. A future revision of the standard could restore the RFC 9091 tolerance, once again accepting a NODATA on A, AAAA and MX as a signal of non-existence.

None of these avenues has a timeline. Do not count on a quick fix. The good news: you do not need one. Aligning sp with np neutralizes the blind spot today, whatever the IETF decides.

🎯 Action plan: secure np on a DNSSEC zone

  1. Test your zone. Query a non-existent name: dig +dnssec bogus-9x7q.captaindns.com A. A status: NOERROR signals the blind spot.
  2. Compare np and sp. Retrieve your _dmarc record and check whether np is stricter than the sp fallback. If so, and step 1 returned NOERROR, you are exposed.
  3. Align sp with np. Publish sp=reject; np=reject (or the strict level you are aiming for) to make the protection independent of the DNS response code.
  4. Inventory your senders. Map the subdomains that actually send via the rua reports, before tightening sp, so you reject nothing legitimate.
  5. Publish dedicated records on each legitimate sending subdomain.
  6. Eliminate broad wildcards (*.captaindns.com in A/AAAA) that make any name "exist" and cancel np, DNSSEC or not.
  7. Factor in the NXDOMAIN behavior of your DNS host in your criteria, without making it a reason for a rushed migration.

FAQ

Does the np tag really protect my non-existent subdomains?

Yes, but on one condition that is not always met: the DNS must return a real NXDOMAIN for non-existent names. If your zone is DNSSEC signed and practices compact denial of existence, it returns NOERROR instead. The DMARC evaluator then believes the subdomain exists, discards np and applies sp. If sp is more permissive than np, the protection is neutralized with no signal at all.

How do I know if my DNSSEC zone answers NOERROR or NXDOMAIN?

Query a name you never created and read the status code: dig +dnssec a-bogus-name-9x7q.captaindns.com A. Spot the ;; ->>HEADER<<- line. A status: NXDOMAIN means np works. A status: NOERROR signals that your zone hides the non-existence, and that np falls back to sp.

Does compact denial of existence also break SPF or DKIM?

No. SPF and DKIM do not depend on detecting a subdomain's non-existence. Compact denial only affects the DMARCbis logic that chooses between sp and np depending on whether the name exists. Your SPF and DKIM checks, as well as your root domain's p policy, are not affected.

Am I affected if I don't use DNSSEC?

Generally no: an unsigned zone returns a classic NXDOMAIN for non-existent names, and np fires normally. One exception: wildcards. An *.captaindns.com record in A or AAAA makes any name "exist" from the DNS's point of view, which cancels np even without DNSSEC. Make sure you do not have a broad wildcard.

Do I need to disable DNSSEC for np to work?

No, absolutely not. DNSSEC protects the integrity of your DNS responses, and disabling it would open far more serious risks than the np blind spot. The right fix is not to touch DNSSEC, but to align sp with np in your DMARC record, so that the protection no longer depends on the response code.

Which policy should I publish to be protected despite the blind spot?

Make sp as strict as np. For example v=DMARC1; p=reject; sp=reject; np=reject. With sp=reject, it does not matter whether the receiver believes the subdomain exists or not: in both cases it rejects. This is the only configuration that closes the blind spot regardless of your zone's DNSSEC behavior. First publish dedicated records on your legitimate sending subdomains.

Do public resolvers like 8.8.8.8 fix the problem?

No. Our tests confirm that 8.8.8.8, 1.1.1.1 and 9.9.9.9 relay the NOERROR from a compact denial zone without reconstructing NXDOMAIN. The optional CO flag (Compact Answers OK), which would allow this reconstruction, is not enabled by default. The DMARC evaluator sitting behind these resolvers therefore does receive a NOERROR.

Is Google Cloud DNS really spared?

Yes, according to our tests. A query for a non-existent name on a zone signed by Google Cloud DNS returns a classic status: NXDOMAIN, with absence proof in NSEC3. The np tag therefore fires normally. It is the counterexample showing that the problem is not inherent to DNSSEC, but to the compact denial choice made by certain hosts.

Will the IETF fix this behavior?

The question has been raised within the IETF dmarc working group, but no solution is settled as of today and RFC 9989 does not address it. Three avenues exist (read the NXNAME pseudo-type, generalize the CO flag, reintroduce NODATA), none with a timeline. Do not count on a quick fix: secure things on the configuration side now.

Does the np tag replace sp?

No, they are complementary. The sp tag applies to subdomains that exist in your DNS, np to those that do not. The fallback chain goes from np to sp to p. It is precisely because the receiver falls back to sp when it cannot confirm non-existence that the gap between the two values creates the blind spot.

Glossary

  • NXDOMAIN: DNS response code meaning the requested name does not exist in the zone. It is the only signal DMARCbis accepts to trigger np.
  • NODATA: a NOERROR response with an empty data section. The name exists, but not for the requested type. Does not trigger np.
  • NOERROR: DNS status code indicating the absence of an error. Used both for a positive response and, in compact denial, to prove a non-existence, which fools the DMARC evaluator.
  • Compact denial of existence: DNSSEC technique that proves a name's non-existence via a single synthesized NSEC and a NOERROR response, to save on signatures and bandwidth.
  • NXNAME (type 128): pseudo-type that marks, in a compact denial response, that the absence is real (the name does not exist), and not a mere NODATA.
  • Black lies: an older variant of the same principle, a NOERROR with a minimal NSEC but no NXNAME marker, used most notably by AWS Route 53 and Azure DNS.
  • CO flag (Compact Answers OK): a resolver-side option that reconstructs an NXDOMAIN from a compact denial response. Rarely enabled in practice.
  • np tag: DMARCbis policy applied to non-existent subdomains. Fallback: sp, then p.

Generate a clean record in one minute: produce a DMARC policy with consistent p, sp and np using the DMARC generator, then validate the result before publishing.


Sources

  1. RFC 9989: DMARC (DMARCbis)
  2. RFC 9824: Compact Denial of Existence in DNSSEC
  3. RFC 9091: Experimental DMARC Extension for PSDs
  4. RFC 8020: NXDOMAIN, there really is nothing underneath
  5. RFC 8198: Aggressive Use of DNSSEC-Validated Cache

Similar articles