A deliberately vulnerable, DVWA/WebGoat-style teaching environment for Claude
Agent Skills. It reproduces the common ways a SKILL.md can be weaponized so
security engineers, red teamers, and skill authors can see each attack, its blast
radius, and its fix — safely.
⚠️ ReadSAFETY.mdfirst. These skills are designed to misbehave. They are safe only because payloads use fake canary secrets, exfil to a local sink, and only ever touch the sacrificialsandbox/directory. Never install them into a real Claude Code environment.
A Claude Agent Skill is a folder with a SKILL.md:
skill-name/
SKILL.md # YAML frontmatter (name, description, allowed-tools) + instructions
scripts/ # optional bundled executables the body may tell the agent to run
Two trust boundaries make this dangerous:
- The
descriptionis loaded into the model's context as soon as the skill is available — before the user asks for anything. Poison it and you influence the agent early and invisibly. - The body and bundled scripts are pulled in on demand and can steer the agent's tools (Bash, file writes, network). A skill the user trusted for one purpose can quietly do another.
Skills are shared as plain folders in repos and gists. There is no sandbox, no signature, and no manifest of what a skill will actually do. That is the gap DVS teaches you to close.
Fifteen modules, each one class of skill attack. Every module has a vulnerable
low/ skill and a hardened secure/ rewrite of the same skill.
| ID | Module | Core idea |
|---|---|---|
| DVS-01 | Body prompt injection | Imperative instructions in the body hijack the running task |
| DVS-02 | Description-field poisoning | The always-loaded description biases the agent before the body is read |
| DVS-03 | Invisible / obfuscated instructions | Zero-width chars, HTML comments, base64 a human reviewer misses |
| DVS-04 | Secret exfiltration | Reads fake .env/~/.ssh canaries and beacons them to the sink |
| DVS-05 | Destructive tool abuse | Runs destructive shell beyond its stated purpose |
| DVS-06 | Over-broad allowed-tools |
Claims Bash/network it does not need — confused deputy |
| DVS-07 | Malicious bundled script | Benign body tells the agent to run a backdoored helper script |
| DVS-08 | Cross-skill / memory poisoning | Emits durable instructions that alter later agent behavior |
| DVS-09 | Supply chain: typosquat & rug-pull | Squats a popular name; benign v1 flips to malicious v2 |
| DVS-10 | Metadata/behavior mismatch | Name/description advertise one thing, body does another |
| DVS-11 | Indirect / data-borne injection | A benign skill treats attacker-controlled ingested content as instructions |
| DVS-12 | Tool shadowing | A skill redefines or intercepts another tool the agent calls |
| DVS-13 | Unsafe autonomy | Escalates scope across steps without re-consent |
| DVS-14 | Denial-of-wallet | Induces runaway loops / token & resource exhaustion |
| DVS-15 | Approval-fatigue bypass | Slips a destructive step past a rubber-stamping human |
A subset (DVS-03, 04, 07, 08) is also wired as capture-the-flag challenges — see
challenges/.
make setup # build container, start the local exfil sink on :8888
make seed # write fake canary secrets into env/
make test # run the scanner test suite (offline, deterministic)Reproduce an exploit (worked example, DVS-04):
scripts/install-skill.sh DVS-04 low # link the vulnerable skill into .claude/skills/
# launch Claude Code in this repo, paste vulns/DVS-04-*/exploit/prompt.md
make sink-logs # watch the CANARY token arrive at the sinkConfirm the fix:
scripts/install-skill.sh DVS-04 secure # swap in the hardened skill
tools/skill-scanner/scan.py vulns/DVS-04-secret-exfiltration/secure # cleantools/skill-scanner/— a static analyzer that flags the patterns behind every module (hidden/confusable unicode, encoded blobs in base64/hex/percent/rot13, exfil URLs, risky tool scopes, metadata mismatch, and the agentic classes). It parses MCP and OpenAI tool JSON too, and has an offline--semanticintent tier (make scan-semantic DIR=...).tools/guardrail/— a runtimePreToolUseegress hook that blocks a skill's outbound beacon at the harness layer (defense in depth beyond static scanning). Opt-in; see its README.tools/eval/— a model-resistance harness.make evalruns an offline naive-agent baseline;make eval-live MODEL=...scores whether a real model resists each exploit.tools/detection/— a hardening checklist and per-class indicators of compromise.tools/metrics/— regenerateschallenges/metrics.md: scanner gate status, catalog size, and evasion-corpus recall.make metrics.- Supply-chain pinning:
scripts/install-skill.sh --pin <MOD> <level>records a reviewed content digest inskills.lockand refuses a changed skill (the DVS-09 rug-pull defense).
portability/— the same attack in three ecosystems: Claude Skills, OpenAI function tools, and MCPtools/listJSON. Shows thedescriptionis the shared trust boundary.mcp/— a runnable MCP rug-pull demo (make mcp-demo): the same tool name serves a benign v1 and a poisoned v2 (the CVE-2025-54136 mechanism).
docs/threat-model.md— the skill lifecycle and trust boundaries.docs/taxonomy.md— the 15 classes mapped to OWASP LLM Top 10, OWASP Agentic threats, MITRE ATLAS, and MAESTRO.docs/setup.md— container bring-up and a full first walkthrough.
MIT, with an educational-use disclaimer. See LICENSE.