Claude Code WebFetch Hardcoded HuggingFace Bare-Hostname Allow-List Bypass — CVE-2026-54316
by InertFluid · 2026-07-05
- Severity
- Medium
- CVE
- CVE-2026-54316 (GHSA-fg94-h982-f3mm)
- Category
- misc
- Affected product
- @anthropic-ai/claude-code (npm package, Claude Code CLI)
- Affected versions
- >= 0.2.54, < 2.1.163 (fixed in 2.1.163)
- Disclosed
- 2026-07-05
- Patch status
- patched
Tags
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-05 |
| Last Updated | 2026-06 |
| Author / Researcher | InertFluid |
| CVE / Advisory | CVE-2026-54316 (GHSA-fg94-h982-f3mm) |
| Category | misc |
| Severity | Medium |
| CVSS Score | Not specified in source |
| Status | PoC |
| Tags | claude-code, webfetch, prompt-injection, exfiltration, huggingface, allow-list-bypass, agentic-ai, docker-lab, cwe-183 |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | @anthropic-ai/claude-code (npm package, Claude Code CLI) |
| Versions Affected | >= 0.2.54, < 2.1.163 (fixed in 2.1.163) |
| Language / Platform | Node.js CLI tool; lab is a Docker container + bash/shell scripts |
| Authentication Required | No (the vulnerable behavior triggers via untrusted content the agent reads, e.g. a poisoned README) |
| Network Access Required | Yes — outbound HTTPS to huggingface.co is the exfiltration channel |
Summary
CVE-2026-54316 (GHSA-fg94-h982-f3mm) is a permission-prompt bypass in Claude Code’s WebFetch tool: versions from 0.2.54 up to (but not including) 2.1.163 hardcoded huggingface.co as a bare, pre-approved hostname, so any path on that domain — including attacker-controlled model repositories — was fetched without ever showing the user a per-domain approval prompt, unlike every other domain. Combined with a classic prompt-injection payload (e.g. a poisoned README the agent reads as “untrusted context”), this becomes a covert, out-of-band exfiltration channel: the agent is steered into encoding secret data character-by-character into HuggingFace resource paths, and since HuggingFace’s server-side download counters increment per fetch, an attacker who owns the target HuggingFace repo can reconstruct the exfiltrated string later from public download metrics — without needing the fetch to ever succeed or return attacker-visible data directly.
Vulnerability Details
Root Cause
Claude Code’s WebFetch tool permission logic (CWE-183, “Permissive List of Allowed Inputs”) maintained a hardcoded allow-list that matched huggingface.co as a bare hostname rather than requiring per-repository/path scoping or normal per-domain prompting. Because HuggingFace hosts arbitrary, attacker-creatable public repositories under that single shared domain, the allow-list effectively pre-approved fetches to attacker-controlled content on a multi-tenant host.
Attack Vector
- An attacker plants prompt-injection instructions in content the agent will ingest as “untrusted” input (e.g. a project README, issue, or data file) — see
payloads/untrusted-readme.mdfor a sanitized example. - The injected instructions direct the agent to read a local secret (e.g. an
.envvalue) and, for each character, issue aWebFetchrequest to a HuggingFace URL path that encodes that character (e.g.https://huggingface.co/<attacker-account>/canary-lab/resolve/main/char_<c>). - Because
huggingface.cowas hardcoded into the pre-approved allow-list, these fetches proceed silently with no permission prompt, unlike a fetch to any other domain (e.g.example.com), which does prompt — this asymmetry is the observable proof of the bug. - The attacker (owner of the target HuggingFace repository) later inspects the repository’s public per-file download/view metrics; the pattern of incremented counters reconstructs the exfiltrated secret character by character.
Impact
Silent, unattended exfiltration of any data the agent has read access to (secrets, source code, credentials) to an attacker-controlled channel, with no visible prompt or user interaction required, defeating the tool’s intended human-in-the-loop approval model for network egress.
Environment / Lab Setup
Target: Docker container pinned to @anthropic-ai/claude-code@2.1.162 (vulnerable)
Attacker: Docker, a Claude subscription for interactive login, and a HuggingFace
account/public repo the researcher owns (for reproducing the exfil channel)
Proof of Concept
PoC Script
See
Dockerfile,.claude/settings.json,fixtures/canary.env,scripts/make_hf_canary_files.sh, andpayloads/untrusted-readme.mdin this folder.
| |
The Dockerfile pins the vulnerable Claude Code release with a strict deny-by-default .claude/settings.json (empty allow/deny lists, so approval is handled purely by the interactive per-domain prompt). Claim 1 demonstrates the prompt-asymmetry directly inside the container. Claim 2 (scripts/make_hf_canary_files.sh + payloads/untrusted-readme.md) reproduces full exfiltration: the researcher pushes generated canary files to their own public HuggingFace repo, plants the injection payload as “untrusted” content for the agent to read, and later reconstructs the dummy canary value (fixtures/canary.env) from that repo’s public download metrics.
Detection & IOCs
Outbound HTTPS requests to huggingface.co/<repo>/resolve/main/<per-character-path>
issued in rapid succession with single-character-varying path segments
WebFetch tool invocations with no corresponding user permission-prompt event in
Claude Code's audit/session logs, for a non-allow-listed-by-the-user domain
Signs of compromise:
- Sequential HuggingFace resource fetches whose path segments spell out recognizable data when decoded.
- Claude Code sessions where
WebFetchreachedhuggingface.cowithout any recorded permission-approval prompt. - Unexplained download-count increments on HuggingFace repos correlating with agent activity timestamps.
Remediation
| Action | Detail |
|---|---|
| Primary fix | Upgrade @anthropic-ai/claude-code to >= 2.1.163, which removes the hardcoded huggingface.co bare-hostname allow-list entry and requires normal per-domain WebFetch approval. |
| Interim mitigation | Explicitly deny huggingface.co (and other multi-tenant hosting domains) in .claude/settings.json permissions until upgraded; avoid running agents with untrusted input over sensitive local secrets/files. |
References
Notes
Mirrored from https://github.com/InertFluid/cve-2026-54316-lab on 2026-07-05. This is a disposable Docker reproduction lab, not a standalone exploit script; running it requires an interactive Claude subscription login inside the container and a HuggingFace account/repo the researcher owns. The “secret” used (fixtures/canary.env) is an explicit dummy value — no real credentials are involved. Filed under “misc” per the archive’s convention for AI/agentic-tool vulnerabilities rather than “web”, since the flaw is in an AI coding agent’s tool-permission model rather than a traditional web application.