PoC Archive PoC Archive
Medium CVE-2026-54316 (GHSA-fg94-h982-f3mm) patched

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

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-06
Author / ResearcherInertFluid
CVE / AdvisoryCVE-2026-54316 (GHSA-fg94-h982-f3mm)
Categorymisc
SeverityMedium
CVSS ScoreNot specified in source
StatusPoC
Tagsclaude-code, webfetch, prompt-injection, exfiltration, huggingface, allow-list-bypass, agentic-ai, docker-lab, cwe-183
RelatedN/A

Affected Target

FieldValue
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 / PlatformNode.js CLI tool; lab is a Docker container + bash/shell scripts
Authentication RequiredNo (the vulnerable behavior triggers via untrusted content the agent reads, e.g. a poisoned README)
Network Access RequiredYes — 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

  1. 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.md for a sanitized example.
  2. The injected instructions direct the agent to read a local secret (e.g. an .env value) and, for each character, issue a WebFetch request to a HuggingFace URL path that encodes that character (e.g. https://huggingface.co/<attacker-account>/canary-lab/resolve/main/char_<c>).
  3. Because huggingface.co was 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.
  4. 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, and payloads/untrusted-readme.md in this folder.

1
2
docker build -t cve-2026-54316-lab .
docker run --rm -it cve-2026-54316-lab

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 WebFetch reached huggingface.co without any recorded permission-approval prompt.
  • Unexplained download-count increments on HuggingFace repos correlating with agent activity timestamps.

Remediation

ActionDetail
Primary fixUpgrade @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 mitigationExplicitly 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.