Your Filenames Are for Sale: The .md Namespace Collision

A correction and a follow up to our February investigation. Markdown filenames are buyable domains, because .md is Moldova's country code TLD. We tested one hundred and two of the filenames a developer types every day, and ninety four were already registered. The filenames AI coding agents read as configuration were bought as each convention shipped. This is the defensive half of the work. A confirmed data-exposure case is held back pending vendor notification.

Your Filenames Are for Sale — Audio

Listen to the audio version of this analysis, voiced by a synthetic narrator.

0:00 0:00

Disclosure status: this article deliberately withholds part of the research. We have confirmed one case where a domain in this namespace published a large number of developers’ private filenames into public certificate logs. We are not naming that domain, and we are not publishing the detail that would let a reader locate the exposed data, until the vendor whose tooling created the naming convention has been notified and given a reasonable window to respond. The defensive guidance below stands on its own and costs nobody anything. Every registration claim comes from registry WHOIS, authoritative DNS, or public certificate transparency logs. No HTTP request was made to any of the domains during this follow up. Our February investigation did fetch content, in a sandbox, and we say so where it matters below. FTRCRP

What we got wrong first, and are correcting

This is a correction as much as a follow up. We published .md TLD: Namespace Collision Threat to AI Agents on the fourth of February, and one of its central claims did not survive re-examination. That article now carries a correction notice pointing here.

The February piece noted that .md is Moldova’s country code top level domain (IANA, 2026), which makes common markdown filenames syntactically valid hostnames. README.md is a filename in every repository you have ever opened, and it is also a domain somebody can buy. It listed seven registered domains and described them as “pre-positioned attack infrastructure”, reading the real businesses behind them as a “legitimate facade” offering “plausible deniability”.

We are withdrawing that framing. It implied a single coordinated actor, and we did not have the evidence for it.

When we tested the claim against ownership records rather than repeating it, the seven names broke into four unrelated parties. Registration dates span two thousand and six to this year. Three separate hosting ecosystems are involved. One of the names belongs to a Moldovan business that has held it for two decades, which is a company using its own country’s TLD. Another belongs to a live developer service. One operator does hold four of the seven, and that pattern deserves attention, so calling the set “pre-positioned attack infrastructure” described a single coordinated campaign that the evidence does not support.

We state this plainly because the correction changes what a defender should do. If seven domains are a campaign, you block seven domains. If they are four unrelated owners inside a namespace anyone can buy into, blocking domains stops being a strategy.

The number that matters

The February work listed seven names. We have now tested one hundred and two.

Ninety four are registered. That is ninety two per cent. Eighty are delegated, meaning the registry answers for them, and fifty eight resolve to an actual address. Eight were still available on the day we looked, at ordinary .md registration prices, which run to tens of dollars a year rather than anything prohibitive.

Seven was only ever a sample. The correct mental model is that the high value markdown filename namespace is essentially sold out.

The class we did not look for

The February work described repository files: README, LICENSE, CONTRIBUTING. Ordinary things, alarming in an ordinary way.

There is a second class, and it is the reason this follow up exists. AI coding agents read their configuration from files with conventional names. AGENTS.md. CLAUDE.md. PROMPT.md. SKILLS.md. MEMORY.md. INSTRUCTIONS.md. HOOKS.md. MCP.md. We tested around thirty such names. Most are registered, and several remain available.

The uncomfortable detail is timing. Registration dates broadly track the public adoption of each convention. As each agent framework shipped and its configuration filename entered common use, the matching domain tended to follow.

We are careful about what that does and does not prove. It does not prove intent to attack anyone, and we have deliberately not looked at what any of these hosts serve. Our estimate is that deliberate accumulation explains perhaps ten to fifteen per cent of this namespace, and we are not asserting a single operator behind it. What the pattern does establish is that these particular filenames are read by software that acts on their contents, rather than by humans who merely display them. That is why we treat this class as more serious than the repository files we led with in February.

Why we are holding part of this back

During the follow up we confirmed one case where a domain in this namespace published a large volume of developers’ private prompt filenames into public certificate transparency logs, permanently, over a period of months. The developers were never told. The content of those filenames is mostly mundane, and we are not going to inflate it, but certificate transparency logs are append only by design (Laurie, Langley and Kasper, 2013), so nothing published there can be withdrawn.

We are withholding the domain name, the volume figures, and the mechanism detail. Publishing them would let any reader locate the exposed filenames in seconds, and the people harmed are uninvolved developers who cannot remove their own data. The vendor whose tooling established the filename convention has not yet been notified. Naming it first would invert the order that responsible disclosure exists to protect.

That material will be published after notification and a reasonable response window. If nobody responds it will be published anyway, on a fixed date, because our February advisory sat at “pending vendor notification” for six months and nobody was ever told. That is a stall rather than a status, and we are not repeating it.

One part of the finding is safe to state now, because it is the part that helps everybody. The exposure did not require anybody to be attacked. It required a filename convention to collide with a live TLD, and something, somewhere, to treat that filename as a hostname worth resolving. What that something was has not been established. Candidates include link-unfurling bots, security scanners, continuous integration link checkers, and browser address bars. Until it is identified, nobody should assert that any specific vendor’s software performed the lookup.

Why blocklists lose

The instinct, and our own first response, is to write down the bad names and block them. That works exactly as long as the list is complete, and this list can never be complete. Ninety two per cent of the valuable names are already taken, the remainder are for sale to anybody with a card, and new conventions appear faster than advisories do. Every agent framework that ships a configuration filename creates another domain worth buying, and the buyer gets there before the advisory does.

The defect does not sit in Moldova, and it does not sit with the domain owners, most of whom appear to be doing nothing more sinister than holding a domain. It sits in the parsers. It lives in any system that takes bare text and decides, on its own initiative, that SECURITY.md is a hostname worth resolving.

Sinkhole it, in one line

Everything above is diagnosis. Here is remediation, and it is genuinely cheap. Blocking the whole TLD at your resolver covers every device behind it, including the containers and headless tools that never read your policy documents. We run this ourselves.

Pi-hole, which covers a household or an office from one place. The regex is anchored on the label, so it matches md and *.md and never something like somemd.com:

pihole deny --regex '(\.|^)md$'

dnsmasq, on a router or a Pi. Drop this in /etc/dnsmasq.d/block-md-tld.conf and restart:

# .md TLD blackhole. Markdown filenames are valid hostnames because .md is
# Moldova's ccTLD. To permit one host, add a line ABOVE this:
#   server=/example.md/1.1.1.1
address=/md/0.0.0.0
address=/md/::

Unbound, for the same effect:

local-zone: "md." refuse

A single machine, no infrastructure required. This protects one host, and containers on that host bypass it, so treat it as the weakest option. Append to /etc/hosts:

0.0.0.0 readme.md changelog.md license.md contributing.md security.md install.md setup.md
0.0.0.0 claude.md agents.md prompt.md skills.md memory.md instructions.md hooks.md mcp.md
0.0.0.0 config.md credentials.md threatmodel.md todo.md roadmap.md faq.md docs.md api.md

Two caveats, stated honestly. Blocking the TLD blocks legitimate Moldovan sites, so if you have business in Moldova use the allowlist escape hatch shown in the dnsmasq snippet rather than the blanket rule. We checked our own estate before doing this and found no legitimate .md dependency, and you should check yours. Second, a resolver block stops the lookup and does not fix the parser. Anything that ships a literal IP address, or that runs on a machine using a different resolver, walks straight past it. Treat the sinkhole as the net under the trapeze.

The IPv6 line matters more than it looks. A resolver that blocks A records and answers AAAA leaves the whole thing open on modern clients, which prefer IPv6 by default.

If you maintain the software

The question is narrow. When your software encounters the string CLAUDE.md in text it did not author, what does it do next, and did anybody decide that on purpose.

Requiring an explicit scheme before treating anything as a URL fixes it. https://example.md/x may be a link. A bare SECURITY.md never is. Auto-linkers should not infer a TLD from a file extension. Agents should not fetch what they were merely shown.

Method and limits

Registration status comes from registry WHOIS and authoritative DNS on the sixteenth of August twenty twenty six. Certificate data comes from public transparency logs. Ownership clustering is inference from shared addresses, nameservers and registration patterns, and is marked as inference rather than fact.

We did not fetch content from any .md host during this follow up. The February work did, deliberately and inside a sandbox, which is how it observed the differential content delivery it reported. We are not retracting that observation. Our choice not to repeat it was about disclosure hygiene rather than any objection to the earlier method. That is a deliberate limit with a consequence worth carrying: we cannot tell you that any specific domain is hostile, and we do not claim it. What we can tell you is that the namespace is bought, that it trades, that the registry publishes no registrant so none of it is attributable, and that a class of filenames read by autonomous software is now part of it.

References

IANA (2026) Root Zone Database: .md delegation record. Internet Assigned Numbers Authority.

Laurie, B., Langley, A. and Kasper, E. (2013) RFC 6962: Certificate Transparency. Internet Engineering Task Force.

nic.md (2026) WHOIS service, Moldovan registry. Registrant and registrar fields are not published.

FTRCRP (2026) Security Advisory FTRCRP-2026-001-v2: .md TLD Namespace Collision. Internal, 16 August 2026.

AI disclosure

This article predates the formal AI disclosure regime introduced on 19 May 2026. AI tools were used to polish and generate some text in this article. Editorial responsibility: Thomas A. Kleppestø.