An AI skill is a Markdown file your coding agent reads and obeys. GitHub code search currently finds 74,192 SKILL.md files installed under .claude/skills/ in public repos. We pulled a sample of 461 of those repos (plus the official Anthropic, OpenAI, and Trail of Bits catalogs), ran a static capability scan over every skill, and aggregated what they can actually do.
Sample: 392 repos with parseable skills, 17,065 skills (12,280 unique by content hash). Repos ranged from personal dotfiles to projects like Appwrite (56k stars). Aggregate stats only – this post names no repo and no skill.
The numbers
Capability Skills Share Read files 11,780 69.0% Reference network URLs 8,287 48.6% Ship bundled scripts/files 6,970 40.8% Execute shell commands 6,615 38.8% Shell + network + file access in one skill 4,184 24.5% Write files 1,853 10.9% Usecurl or wget
828
4.9%
Declare Bash in allowed-tools frontmatter
690
4.0%
Read sensitive-looking paths (.env, .ssh, .aws, keys)
364
2.1%
Most common shell verbs across skills: grep, npm, git, python, curl, cat, pip, npx, mkdir, bash, jq, uv, rm, node, gh.
Three things that should bother you
1. Capability is implicit, not declared. 38.8% of skills execute shell commands, but only 4.0% declare Bash in their allowed-tools frontmatter. The frontmatter – the only part that looks like a manifest – tells you almost nothing. The capability lives in the prose and the fenced code blocks, which is exactly the part nobody re-reads when a skill gets “a small docs update.”
2. A quarter of skills hold the full toolkit. 24.5% combine shell execution + network access + file access in a single skill. None of that is malicious by itself – a deploy helper legitimately needs all three. But the difference between a deploy helper and an exfiltration chain is only the argument values: which host, which file. A reviewer who approved the skill once will not notice when one of those values changes in a later diff.
3. .env reads are normal – and that’s the problem. 364 skills (2.1%) read paths like .env, .ssh, or .aws credentials files. Spot-checking shows most read their own config (.claude/skills/<name>/.env) – legitimate. But today’s review process gives you no way to distinguish “reads its own .env” from “started reading yours” between two versions of the same skill, because nobody diffs skill behavior – they diff Markdown prose.
What we think follows from this
Skills are dependencies. We learned this lesson with packages: you don’t re-audit node_modules by hand on every update – you pin a lockfile and review the diff. Skills need the same primitive: a committed record of the capability surface you approved (shell verbs, hosts, file paths), and a CI gate that shows the capability delta on every PR and blocks until a human signs off.
That’s what we built skil-lock to do (Apache-2.0 CLI + GitHub Action; the skills.lock spec is CC BY 4.0 and usable without our tool). But the data point stands on its own, whatever tooling you choose: the capability surface of installed skills is large, mostly undeclared, and currently unreviewed.
Methodology + honest caveats
- Sample = first 500 GitHub code-search hits for
filename:SKILL.md path:.claude/skills(461 unique repos, 457 scanned successfully) + 3 official catalogs scanned separately. Code-search ordering is not a uniform random sample of the 74k population. - Static literal extraction only: shell verbs from fenced code blocks + bundled scripts, URLs/paths as written. Runtime-assembled commands (variables,
base64,eval) and natural-language instructions are NOT counted – the true capability surface is strictly larger than these numbers. - Counts are per skill, deduplicated tokens, junk filtered. 12,280 of 17,065 skills are unique by content hash (skills get vendored across repos).
- “Sensitive-looking paths” matches path-like strings only (
.env*,.ssh,.aws,id_rsa/id_ed25519,.netrc,.npmrc,.git-credentials,.gnupg); code fragments are excluded. Reading such a path is often legitimate – the stat measures exposure surface, not malice.
답글 남기기