DMVDepartment of Machine Verification (let your agent join the community)Visit DMV →
aid · 2026-06-22

What Makes a Trust Anchor External

An endpoint proof is only as strong as the independence of the channel that publishes the key from the endpoint that holds it. Why AID anchors the key in DNS, what that buys, and what it does not.

Balázs NemethiContributor

What makes a trust anchor external.

The signature is the easy part. The security is in who vouches for the key.

Date: 22 June 2026


AID's endpoint proof, PKA, tends to get read one of two ways: as "a signature on the endpoint," or as DNSSEC with extra steps. Neither reading finds where the security actually is. It is in a property that has nothing to do with the algorithm: whether the thing that publishes the key is independent of the thing that holds it.

This post pins that property down and turns it into a test you can run against any agent-identity scheme.

Four layers, four different proofs

It helps to be exact about what each layer under an agent connection actually proves, because they are easy to blur together.

LayerWhat it proves
DNS TXTThe domain's zone owner declared this endpoint and this key.
DNSSECThe DNS answer was not altered in transit.
TLSYou reached the host the certificate names.
PKAThe endpoint controls the private key the domain published.

None of the first three prove possession of a key the domain vouches for. DNSSEC protects the record in flight. TLS proves you reached a named host, and a named host can be a fresh cloud instance an attacker spun up an hour ago. PKA adds the missing piece: the endpoint answering you controls a private key that the domain, separately, said was its own. It does not replace the other three layers. It sits alongside them.

The live proof is the easy part

The mechanism is Ed25519 keys and RFC 9421 HTTP Message Signatures. The client sends a fresh challenge, the endpoint signs it, the client checks the signature against the published key. That is a good, boring, well-specified handshake, and anyone can implement it in an afternoon. Web Bot Auth uses the same primitives.

Because it is easy, it is also the part that tells you the least. A signature proves the signer holds a private key. It does not tell you whose key it is, or who said so. Treat "it signed my challenge" as "it is who it claims to be" and you have skipped over where the public key came from, which is the actual subject here.

The invariant

An endpoint proof is only as strong as the independence of the channel that publishes the key from the endpoint that holds it.

Independence is necessary but not sufficient. The publishing channel also has to be at least as hard to compromise as the endpoint it vouches for; a pastebin is independent of your server and worthless as an anchor. So the test has two clauses: independent, and no weaker.

Call a key externally anchored when it is published somewhere the endpoint being proved does not control. Call it self anchored when one authority publishes the key, holds the private key, and signs the challenge. A self-anchored proof is the endpoint vouching for itself. That can still be useful, since it shows the endpoint is consistent with its own published metadata. But consistency is not identity, and the two get mistaken for each other constantly.

Three cases

An attacker takes over the web server at api.acme.com. They can edit any file the host serves, and they hold every private key on the box. What the takeover buys them depends entirely on where the anchor sits. If the key is published in a file on that same host, they mint a fresh keypair, overwrite the file, and keep answering challenges. Every proof verifies and nothing looks wrong, because the scheme was only ever checking the endpoint against itself. If the key is published in acme.com's DNS zone, they now own a server that can serve traffic but cannot prove anything. The zone key matches nothing they hold, and the web server gives them no way to change it. Verification fails, which is the system working.

Three cases generalize this.

Three anchoring cases for an endpoint proof. Case 1, same-origin file: one authority publishes the key, holds it, and signs, so the endpoint vouches for itself and trust collapses to TLS. Case 2, apex or independent file: the publisher is independent of the endpoint, but the anchor is rooted in the certificate authority. Case 3, DNS: the key lives in the domain's zone, independent of the endpoint's host and rooted in DNSSEC rather than a CA.

Same-origin file. A key at https://api.acme.com/.well-known/agent.json certifying an endpoint at https://api.acme.com. One authority publishes the key, holds it, and signs with it; compromise that host and you own all three. TLS already proved you reached api.acme.com, so the proof adds self-consistency on top of the certificate and nothing more. This is not an exotic misconfiguration, either. It is the default shape of most .well-known based identity schemes on the web today.

Apex or independent file. A key at https://acme.com/.well-known/agent.json certifying an endpoint at https://vendor.example. The publisher is now independent of the endpoint, so the proof does real work: it shows the far endpoint holds a key acme published. The anchor itself, though, rests on whichever certificate authority issued acme.com's cert, so what you have is an independent anchor with a CA root. In fairness, the CA system is better than its caricature these days; certificate transparency logs and CAA records make mis-issuance loud. That is fine, as long as you meant to.

DNS. A key in the zone at _agent.acme.com, certifying an endpoint anywhere. The key lives on a plane the endpoint's web host never touches, which is what the attack story above showed. Two guarantees hide inside this case and they are worth pulling apart. Publisher independence, meaning the web host cannot alter the key, holds whether or not the zone is signed. Transit integrity, meaning nobody rewrote the DNS answer on its way to you, requires DNSSEC, and most zones are not signed. An unsigned zone still gives you the independence. It leaves the channel itself to however much you trust your resolver path.

The handshake never changed across the three cases. Only the anchor did.

What can break the DNS anchor

Being honest about the third case means naming what it does not survive. The zone is not the true root; the registrar account is. Whoever controls the registrar login, or the DNS provider's control panel, controls the anchor, and those are password-and-support-ticket systems with every failure mode that implies. Domains expire and get resold, and the identity follows the domain: buy a lapsed domain and you inherit the authority to publish its _agent record. That is a deliberate trade. AID roots identity in DNS authority rather than in the key itself, the opposite choice from self-certifying schemes like Pkarr, and it means a key change is just a key change rather than a break in some cryptographic lineage. It also means domain ownership is the thing you are ultimately trusting. And keys published at a TTL go stale like everything else in DNS; rotating them is a real operational duty, often owned by a different team than the one running the endpoint.

None of this collapses the case for the zone. Every anchor has an account-recovery story somewhere. The question the invariant asks is whether the anchor's failure modes are independent of the endpoint's, and a registrar compromise is a different attack, against a different system, run by different people, than a web-server takeover. But the claim is "independent," not "invulnerable," and the difference matters.

DANE tried this already

Putting keys in DNS to get out from under the CA system is not a new idea, and anyone reading this from the DNS world is already thinking it. SSHFP put SSH host keys in the zone. DANE put TLS certificate bindings there, made essentially this post's argument more than a decade ago, and mostly did not get deployed.

The honest reading of DANE's stall is that it warns about deployment, not about the anchor. DANE coupled itself to the TLS stack: to matter, it needed validating resolvers along the full path and TLS implementations willing to consult them, infrastructure nobody could ship unilaterally. PKA lives at the application layer instead. The client reads a TXT record and verifies an HTTP signature. No resolver upgrade, no TLS library change, nothing to wait for. And it degrades rather than failing: without DNSSEC you lose transit integrity but keep publisher independence, which is still more than a well-known file gives you. Whether that is enough to escape DANE's fate is a fair question. The deployment surface, at least, is one TXT record and one header.

A test you can apply to anything

The invariant doubles as a test with one question in it: who publishes the key, and is that publisher independent of, and no easier to compromise than, the endpoint it certifies?

Scope first. The test judges schemes that promise cold verification, the ones that say "verify me with no prior relationship." SPIFFE, OAuth, and WIMSE make no such promise. They identify workloads and authorize actions inside a boundary you already joined, which is the question that comes after first contact, and PKA's job is to hand off to them once first contact is settled. Grading them on anchor independence would be grading them on an axis they never claimed.

A signed manifest is in scope, and the question mostly sinks it. A signature over a catalog fetched from an index proves the copy has not changed since signing. It says nothing about whether the key belongs to the domain, and the arrangement inherits the trust posture of whichever index served it.

did:web is the interesting one, because the test cuts through it rather than filing it away. A did:web document is a key list at a domain's HTTPS well-known path. When an apex document vouches for endpoints hosted elsewhere, that is the second case: independent anchor, CA root. When the document sits on the same host as the service it describes, did:web:api.acme.com describing a service on api.acme.com, it is the first case, a self anchor, however decentralized the acronym sounds. One scheme, both buckets, depending on where the file sits relative to what it names. did:web and PKA are the same shape with different roots, and nothing stops a deployment from using both.

Why we put the key in the zone

We publish the key in _agent.<domain> because it is the one channel that keeps the anchor external and CA-independent by default, for anyone who can edit a TXT record.

dns
_agent.acme.com. 300 IN TXT "v=aid2;p=mcp;u=https://agent.acme.com/mcp;k=ebVWLo_mVPlAeLES6K..."

The same principle catches a sibling failure. An endpoint can hold a valid key and still prove it for a domain it never agreed to serve, which falsely implies a relationship. AID v2's domain binding closes that: the endpoint signs the exact domain the client queried, so it cannot be volunteered into an association silently. Both problems are one idea; the party making a claim has to be independent of, and consenting to, the claim being made. And when a proof fails, an AID client does not shrug and continue. Discovery fails, as a security error. The full handshake and the domain-binding profile are in the PKA reference and the specification.

The question to ask

The signature is the part anyone can copy by Friday. The anchor is the part that has to sit outside the endpoint's blast radius, and no signature algorithm can put it there.

So when you evaluate an agent-identity scheme, skip past what it signs with. Ask what vouches for the key, and whether that thing is just the endpoint wearing a second hat.


See also: PKA as an external trust anchor, on why first contact needs a public anchor at all, and ARD finds the agent, AID proves it, on where this sits next to search.