skill-shield
Static-analysis security scoreboard for public AI agent skills. Find the risky behavior in a SKILL.md before an agent loads it.
In February 2026 security researchers identified 341 malicious skills in the ClawHub marketplace — a coordinated supply chain attack that shipped infostealer payloads inside agent skills. Skill frameworks are now the fastest-growing GitHub category (mattpocock/skills +1,618 stars in a single week; the agentic-skills category gained 120K stars in 90 days). mcp-trust already covers MCP servers. Nothing does this for Skills.
skill-shield scans every public SKILL.md from a curated list of skill repositories, runs deterministic regex-based static analysis on each one, and produces a 0-100 risk score with a categorized finding list.
What it scores
| Category | Patterns |
|---|---|
| Execution | curl \| bash, eval(), subprocess.run, download_exec, reverse-shell signatures |
| Secrets | Reads KEY/TOKEN/SECRET from env, touches ~/.ssh ~/.aws ~/.kube, loads .env files |
| Network | fetch / axios / requests, suspicious TLDs, URL shorteners, raw IPs |
| Obfuscation | Long base64 literals, hex-escape blobs |
| Permissions | "allowedTools": "*", --dangerously-skip-permissions |
| Filesystem | Writes outside scratch dirs |
Each match contributes a fixed weight (capped at 3 matches per pattern) and the total is clamped to 0-100. Categories: safe 0-20, low 21-40, moderate 41-60, high 61-80, critical 81-100.
Data sources (all real, all public)
- GitHub
git/trees/:branch?recursive=1— enumerate everySKILL.mdin each seed repository (no auth required;GITHUB_TOKENoptional for 5000 req/h limit). raw.githubusercontent.com/<owner>/<repo>/<branch>/<path>— fetch the actual file content.- Crawl cadence: every 6 hours (
0 /6). - User-submitted URLs queued and processed every 5 minutes.
The seed list lives in fetchers/known_repos.js. Currently includes Anthropic, mattpocock, Cloudflare Agents, ModelContextProtocol, Mastra, Block Goose, VoltAgent, Continue, CrewAI, LangGraph, Pydantic-AI, AG2, and the OpenAI agents SDK.
No mocks, no seed data, no Math.random(). If GitHub returns 404 the row is left stale and never fabricated.
Endpoints
All endpoints are public (no auth, by design) and mounted under BASE_PATH=/skill-shield:
| Method | Path | What |
|---|---|---|
| GET | / | Single-page dashboard |
| GET | /health | JSON health probe |
| GET | /api/skills | Sortable, filterable, paginated list |
| GET | /api/skills/:id | Skill detail + findings + history |
| GET | /api/skills/:id/urls | URLs extracted from the SKILL.md, suspicious-classified |
| GET | /api/movers | Biggest weekly risk-score swings |
| GET | /api/stats | Counters + pattern catalog |
| GET | /api/sources | Seed repositories + last fetch metadata |
| POST | /api/submit | Queue a github.com/.../SKILL.md URL for scanning |
| GET | /api/submit/:id | Submission status |
| GET | /badge.svg?repo=owner/repo&path=... | Shields-style SVG badge |
Stack
- Node.js 20+, Express, helmet, compression
- better-sqlite3 (WAL mode)
- node-cron
- Vanilla JS SPA, dark theme, English labels
- No frameworks, no build step
Run locally
npm install
PORT=4820 BASE_PATH=/skill-shield node server.js
# open http://localhost:4820/skill-shield/
First crawl kicks off 5 seconds after boot. Watch the logs for [crawl] done in Ns — N skills.
Deploy
DEPLOY_MANIFEST.json is wired for the RNDLAB orchestrator:
echo '{"product":"skill-shield",...}' >> .openclaw/cowork-deploy-bridge/queue.jsonl
The Mac watcher picks it up within 30 seconds, runs rsync + systemd + nginx, and adds the showcase tile.
License
MIT