Research
HalluSquatting: detecting an inference-time trust-chain failure
Published 2026-07-30
In July 2026, researchers from Tel Aviv University, the Technion, and Intuit described an attack they call HalluSquatting. The idea is uncomfortable and simple: language models invent resource names, they invent the same names repeatedly, and an attacker can register those names in advance. The paper reports hallucination rates of up to 85% for repository-cloning prompts and up to 100% for skill-installation prompts, with a demonstrated path from a hallucinated name to remote code execution. Those numbers are the authors'; we have not independently reproduced them.
The attack is theirs. This writeup is about the other half of the problem: once you accept that models will name resources that do not exist, what can a defender actually detect by reading code - and, just as importantly, what can they not honestly claim to have detected?
What follows is the detection method VibeAudit ships for this class: a trust-chain model, four finding classes with an explicit evidence requirement each, and a claim contract that keeps every result inside what static analysis genuinely proves.
Slopsquatting stops at the manifest. This does not.
Dependency slopsquatting is already a known shape: a model suggests a package name, the name lands in a manifest or an install command, and a scanner can compare that literal string against a registry. The name is a fact sitting in a file. You can look it up.
HalluSquatting crosses a boundary that no manifest records. Model output becomes a resource locator, the retrieved content becomes agent context, and that context can become a tool invocation. Each hop is an ordinary feature working as designed. There is no misspelled string to diff, because at scan time the identifier does not exist yet - it is produced at inference, on a machine you do not control, in a session you cannot see.
That is why the detectable artifact is not a name. It is the shape of the pipeline that will carry whatever name the model produces:
model or planner
-> unverified or ambiguously resolved resource identifier
-> repository / package / skill fetch
-> untrusted README / project rule / SKILL.md
-> agent tool invocation
-> data egress or terminal handoverFour things static analysis can honestly see
Each class below pairs a required piece of static evidence with the narrowest claim that evidence supports. The second half matters more than the first: a detector that cannot say what it failed to prove is a detector that will eventually lie to someone.
Resource Trust Fall - a model- or planner-derived identifier reaches repository, skill, package, or resource retrieval with no visible preceding search or provenance control. The claim is that the application contains an unsafe retrieval boundary. It does not prove that any model hallucinated any particular identifier.
Repository Promptware Chain - instruction-override or AI-targeted content tied to urgent tool use and context egress, or a repository instruction file that routes the agent to a shipped helper with a supported payload shape. The claim is that the repository contains a promptware-compatible instruction path. A correlated instruction-to-helper chain is materially stronger evidence than either file alone.
Skill Resolution Trap - lossy generic-word removal during name normalization, automatic installation of a similarity search's top result, material divergence between display name and install slug, explicit skill promptware, or a SKILL.md-to-helper payload chain. The claim is that skill resolution creates a HalluSquatting-compatible ambiguity or execution path. The paper's skill-installation scenario is the one that reached a 100% hallucination rate, which makes this the class worth wiring first.
HalluSquatting-Compatible Poisoned Payload - an executable that combines sensitive-data discovery with network or browser egress, or that contains a terminal-handover primitive, with no scanned instruction file reaching it. The claim is that the payload could serve as an execution stage. Static evidence alone says nothing about how the resource was selected.
A prompt is not a security boundary
This is the single most load-bearing conclusion in the whole method, and it is the one most likely to be got wrong in a code review.
Search-before-fetch is a genuine control: resolve the name against a registry or search API first, then retrieve only what the search returned. It is only durable when the fetch or install tool itself refuses to run without a preceding search result. A system prompt that asks the model to search first is not a boundary, because the same model that hallucinates the name is the component being asked to police itself. It can skip the step, or narrate having taken it. Under adversarial pressure it will.
So the detector treats an enforced boundary and a requested one as different findings. If the check lives in the tool, that is a control. If the check lives in the instructions, the retrieval boundary is still unsafe - and the code will often look responsible while being exactly as exposed.
Record the defenses, not just the defects
A scanner that only emits problems produces a distorted picture of a codebase that is doing the right thing. This detector records five defenses as positive controls rather than findings: a repository, skill, package, registry, or web search that occurs before the fetch; an exact canonical resource or slug match; a trusted owner or publisher allowlist; signature, digest, integrity, or provenance verification; and explicit user confirmation when resolution is ambiguous.
Controls are reported alongside findings so a reviewer can see which boundaries already hold. A file that fetches a model-named resource behind an exact-match check and a publisher allowlist is not the same risk as one that concatenates model output into a clone command, and the output should not flatten that difference.
One chain, not two findings
When a README, project rule, or SKILL.md reaches a helper script with a supported payload shape, there is a temptation to report two issues: a suspicious instruction file and a suspicious script. That inflates the count and buries the actual story.
Instead the detector retains both underlying facts but emits a single causal chain finding, and suppresses the standalone payload finding for any helper already covered by a chain. The correlation is the evidence. A helper that discovers credentials and posts them somewhere is ambiguous on its own - plenty of legitimate deployment tooling looks like that. The same helper, reachable from an instruction file that tells an agent to run it before answering and not to mention it, is a different claim entirely.
What this cannot tell you
Every finding in this class is labeled static_suspicious, and the label is load-bearing. The detector does not infer that a specific model hallucinated a resource name, that an observed owner registered a resource maliciously, that a repository or skill is globally malicious or globally clean, that a payload ever executed, that data left any machine, or that files it did not scan were checked.
The bounds are equally explicit. It recognizes supported direct references and payload shapes; it is not a malware engine, a marketplace reputation service, an interprocedural analyzer, or a dynamic prompt-injection test. Encoding changes, indirect loaders, unsupported languages, generated paths, and novel payload shapes evade it. Benign administrative and security-testing code legitimately matches some standalone payload shapes, which is why findings preserve paths, line numbers, and confidence for human review rather than auto-escalating.
The evidence contract is redaction-first. Exported facts are limited to paths, line numbers, detector kinds, finding classes, abstract signal categories, chain stages, hashes and body fingerprints, and counts. Raw source, snippets, prompt text, commands, resource identifiers, owner values, and endpoints are never exported - and the free and paid artifacts carry the same redacted evidence, because an evidence contract that weakens when someone pays is not a contract.
If your app fetches resources the model named
For a suspected promptware or payload chain: do not open the resource in an agent, IDE workspace, CI job, or package lifecycle hook. Quarantine and inspect instruction files and helpers outside the agentic environment. Verify the canonical owner, the immutable commit or artifact digest, and the expected distribution channel. If a helper did run, rotate every credential that was reachable from that environment - developer, CI, cloud, npm, GitHub, and application. Then rebuild from a trusted source and add a fail-closed retrieval boundary before re-enabling agent tools.
For an application you are building: make the fetch or install API itself require a preceding search result, an exact canonical match, verified provenance, and confirmation when resolution is ambiguous. Treat every retrieved instruction as untrusted data and keep it isolated from privileged tool policy. Run any necessary inspection with no credentials, no ambient host filesystem access, and no unrestricted egress.
The general principle: the component that produces the name must never be the component that vouches for it.
Questions people ask
- Is HalluSquatting VibeAudit's research?
- No. The attack was published by Spira, Cohen, Feldman, Bitton, Wool, and Nassi (arXiv 2607.07433), and the affected vendors were notified before that paper appeared. What is ours is the detection method described here: the trust-chain model, the four finding classes, the positive-control set, and the static-evidence claim contract.
- How is this different from the slopsquatting checks I already run?
- Slopsquatting checks compare a package name that already exists in a manifest or install command against a registry. HalluSquatting detection looks for an unsafe retrieval boundary, because the dangerous identifier is generated at inference time and never appears in your repository at all.
- Does a clean HalluSquatting result mean my agent is safe from this attack?
- No. A clean result means no supported signal was found in the files that were scanned. Encoding changes, indirect loaders, unsupported languages, and generated paths can evade the detector, and private or omitted files are never treated as checked. Unscanned scope stays Security Unverified.
- Does asking the model to search before fetching count as a control?
- No, and this is the most common mistake. A control has to be enforced by the fetch or install tool. If the requirement lives in a prompt, the component being asked to verify the name is the same component that produced it, so the detector still reports the retrieval boundary as unsafe.
- What does the scan send off my machine?
- For the local deep scan, file contents stay local. Exported evidence is limited to paths, line numbers, detector kinds, finding classes, abstract signal categories, chain stages, hashes, fingerprints, and counts. Raw source, prompt text, commands, resource identifiers, and endpoints are not exported.
Check your launch, not your luck.
The free Thorough Scan runs against your live URL - severity counts and categories in about a minute, no code upload, no card.
