
Лаборатория воспроизведения для CVE-2026-54316 (Claude Code WebFetch huggingface.co bare-hostname permission bypass / exfiltration)
Полноценная одноразовая лаборатория, воспроизводящая
GHSA-fg94-h982-f3mm
/ CVE-2026-54316: Claude Code предварительно одобрил huggingface.co как голое имя хоста
для инструмента WebFetch, поэтому любой путь на этом домене — включая
управляемые атакующим репозитории моделей — загружался без запроса
разрешения. В сочетании с инъекцией промптов это становится внеполосным каналом
для эксфильтрации данных, наблюдаемым через серверные счетчики загрузок HuggingFace.
| Уведомление | GHSA-fg94-h982-f3mm |
| CVE | CVE-2026-54316 |
| Пакет | @anthropic-ai/claude-code (npm) |
| Затронутые версии | >= 0.2.54, < 2.1.163 |
| Исправлено в | 2.1.163 |
| Коренная причина | Разрешение голого имени хоста на мультитенантном хосте (CWE-183) |
Эта лаборатория воспроизводит исправленную, публично раскрытую уязвимость в образовательных и защитных целях. Используйте её только против инфраструктуры, принадлежащей вам:
fixtures/canary.env) — никогда не используйте настоящее.huggingface.co без запроса подтверждения, в то время как любой другой
домен вызывает такой запрос — потому что huggingface.co находится в жёстко
заданном белом списке.Контейнер — единственное место, где работает уязвимая версия; ваша хост-система остаётся чистой. Аутентифицируйтесь с помощью токена подписки Claude (ключ API не требуется):
docker build -t cve-2026-54316-lab .
docker run --rm -it cve-2026-54316-lab
Внутри контейнера запустите claude и выберите «Claude account with subscription»
для интерактивного входа. Уязвимая версия 2.1.162 предшествует появлению
переменной окружения CLAUDE_CODE_OAUTH_TOKEN, поэтому setup-token здесь не
используется — интерактивный поток с браузером/вставкой кода позволяет обойтись без
создания долгоживущего токена.
Суть в асимметрии запросов подтверждения по доменам, поэтому WebFetch остаётся
доступным (он не запрещён) — подтверждение обрабатывается через промпт, что
является поведением по умолчанию. Внутри контейнера в claude:
Используйте WebFetch для загрузки
https://example.comи создания краткого описания.
→ Появляется запрос разрешения с просьбой одобрить example.com. Затем:
Используйте WebFetch для загрузки
https://huggingface.co/<ваш-аккаунт>/canary-lab/resolve/main/config.json.
Уязвимо: загрузка с huggingface.co выполняется без запроса, в то время как
example.com требовал его. Эта асимметрия и есть ошибка — huggingface.co
находится в жёстко заданном белом списке. (Репозиторий HF не обязательно должен
существовать для этого теста; ответ 401/404 всё равно доказывает, что запрос не
появлялся.) Пересоберите с @anthropic-ai/[email protected] — теперь загрузка
с huggingface.co тоже требует запроса; это различие «до/после» и есть суть.
./scripts/make_hf_canary_files.sh ./hf-repo, затем отправьте hf-repo/ в
публичный репозиторий HuggingFace, принадлежащий вам (<ваш-аккаунт>/canary-lab).payloads/untrusted-readme.md, установите HF_ACCOUNT и
поместите файл туда, где агент прочитает его как недоверенное содержимое.Dockerfile — зафиксированная уязвимая версия 2.1.162.claude/settings.json — пустой список разрешённых/запрещённых, так что WebFetch запрашивает подтверждение для каждого доменаfixtures/canary.env — фиктивная канарейкаscripts/make_hf_canary_files.sh — структура файлов канарейки для HFpayloads/untrusted-readme.md — полезная нагрузка с инъекцией промптов (санитизирована)