agentscan
The trust layer for AI agent skills.
A deterministic, local security scanner for AI agent skills — plus the Trusted Distribution: a curated, continuously audited package registry.
pip install agentscan-cli
agentscan scan ~/.claude/skills # free, local, deterministic
agentscan activate # Trusted Distribution license
agentscan search # what's available
agentscan install security-engineer # one command, verified
agentscan update # like brew upgrade
The scanner (free, open source, MIT)
Scan any skill, MCP server, or agent config for what it actually does — shell, exfiltration, secrets, supply-chain, obfuscation — before you run it in your agent.
- Facts, not verdicts. Every finding is a checkable fact with
file:line. The scanner never calls anything "malicious" — that verdict is yours. - Deterministic, not ML. Regex, entropy, structure. Same input, same report, every time.
- Zero dependency, zero execution. Pure Python stdlib. Never runs a skill, never calls out, works offline.
$ agentscan scan ~/Downloads/suspicious-skill
agentscan 0.4.0 — /home/you/Downloads/suspicious-skill
scanned 1 artifact(s), 14 finding(s)
ARTIFACT [claude-skill] auto-updater
CRITICAL [exfil] Local secret read piped to network
SKILL.md:41
CRITICAL [secrets] AWS Access Key
SKILL.md:24
...
summary: critical=3 high=2 medium=5 low=2 info=2
note: findings are observed patterns, not verdicts. Review each before acting.
Exit codes: 0 clean · 1 findings at/above threshold · 2 usage error.
What it checks
| Check | Observes |
|---|---|
shell |
bash/sh/python -c/node -e/exec/eval/subprocess invocations |
filesystem |
rm -r/-f, shutil.rmtree, git reset --hard/clean/push --force, chmod 777 |
network |
curl/wget/fetch/requests, URLs, credential-in-URL, IP literals, cleartext http |
secrets |
20+ token formats (AWS, GitHub, Slack, Stripe, OpenAI, Anthropic, JWT, PEM…) |
license |
declared license — recognized vs. unrecognized vs. missing |
supply_chain |
curl|bash pipes, git clone, unpinned pip/npm, script downloads |
prompt_patterns |
high-risk prompt-manipulation phrasing — flagged, never "detected" |
exfil |
credentialed webhooks, env-in-URL, secret-read → network |
obfuscation |
decode-to-execute chains, nested eval/exec, hex escapes |
config_tamper |
remote MCP servers, hook commands, npm lifecycle scripts |
Artifacts detected: claude-skill, mcp-server, cursor-rules,
context-file, github-actions, npm-package, generic.
Usage
python3 -m agentscan <dir> # human report
python3 -m agentscan <dir> --json # machine-readable
python3 -m agentscan <dir> --sarif # SARIF 2.1.0 (GitHub code scanning)
python3 -m agentscan <dir> --severity high # only high+ fails exit code
The Trusted Distribution (paid)
Access to curated, security-reviewed packages. Buy once ($49), receive a
license key, activate, install. No dashboard, no browser login, no accounts —
it's a developer tool.
Buy ($49, Polar checkout)
↓
License key (shown on your Polar purchases page)
↓
pip install agentscan-cli
↓
agentscan activate → Polar /v1/customer-portal/license-keys/validate (direct)
↓
agentscan search → GET /api/packages
↓
agentscan install <package> → GET /api/download/<id> (license-gated) → sha256 → extract → install
↓
agentscan update → like brew upgrade
Architecture
PyPI (agentscan CLI, MIT)
↓
Polar (payment + license keys — source of truth, no users table)
↑ direct validation (public endpoint, no server in the middle)
|
agentscan.baldbee.me (Next.js site + API route handlers)
├── /api/packages public catalog
└── /api/download/[id] license-gated tarball proxy
↓
agentscan-registry (private GitHub repo)
├── packages/ source of truth
├── packages.json generated catalog (sha256 per package)
└── GitHub Releases tarball distribution
↓
~/.agentscan/ license · installed.json · config.json · cache/
~/.claude/skills/<package>/ installed package
The website and API are the same Next.js application. No separate backend, no database, no object storage. Git is the source of truth; GitHub Releases are the CDN. License validation is on-demand against Polar — nothing is stored server-side, no webhooks, no subscriptions.
The Polar organization id is public metadata and is baked into the CLI as a
constant (DEFAULT_POLAR_ORGANIZATION_ID in agentscan/config.py). Users
never configure it — install, activate, done.
Commands
agentscan scan . # scan a directory of agent skills (free)
agentscan activate # prompt for license → verify → store
agentscan logout # remove local license
agentscan whoami # show active license
agentscan search # browse the catalog (package cards)
agentscan install <package> # verified install into Claude Code
agentscan update # upgrade installed packages
agentscan verify # signature · latest · audit · intact
Package names are matched flexibly — any of these work:
agentscan install security-engineer
agentscan install "Security Engineer"
agentscan install Security Engineer
agentscan install security
agentscan install secuirty # typos are suggested, not silent
Add --quiet (or -q) to suppress progress lines for automation; results
and errors still print. Run agentscan --help for examples.
Local state
Everything lives in ~/.agentscan/:
~/.agentscan/
license the activated license (JSON)
installed.json {package-id: version}
config.json api_url override (optional)
cache/ downloaded tarballs
Package format
A package is not just a skill. It may contain agents, skills, slash commands, templates, workflows, and knowledge:
security-engineer/
manifest.json id, title, version, description, license, requires
agents/ optional agent definitions
skills/ SKILL.md files
commands/ optional slash commands
templates/ optional templates
knowledge/ reference material
audit.json latest deterministic scan result
signature.sig placeholder — real signing lands with the Polar milestone
README.md
manifest.json ships one package definition per the catalog shape:
{ "packages": [ { "id": "security-engineer", "title": "Security Engineer",
"version": "1.0.1", "description": "…", "sha256": "…",
"release": "v1.0.1", "asset": "security-engineer-1.0.1.tar.gz" } ] }
Status of the paid layer
- License verification is real.
agentscan activatevalidates the key against Polar's public customer-portal endpoint on demand. No mock, no database, no webhooks. - Downloads are real and license-gated. The CLI sends the license key
as
Authorization: Bearer <key>; the site validates it against Polar before proxying the tarball from the private GitHub registry. Checksums are verified end to end (server-side and CLI-side). signature.sigis a placeholder; cryptographic signing is designed in (agentscan verifyis structured to add it without CLI changes).
The numbers (4,000 skills measured)
We scanned a random sample of 4,000 unique skills across 174 public repos:
| Signal | % of skills |
|---|---|
| No recognizable license | 93.6% |
| Invokes shell / interpreter | 75.3% |
| Supply-chain patterns (curl|bash, unpinned installs) | 23.1% |
| Credential-format strings | 14.7% |
| Destructive filesystem ops | 7.6% |
| Exfiltration sinks | 4.2% |
| Prompt-manipulation phrasing | 3.3% |
| Obfuscation chains | 0.4% |
| Any high/critical finding | 18.0% |
Full methodology: CORPUS-REPORT.md
Development
python3 -m unittest discover -s tests -v # 49 tests
Pure stdlib, Python 3.8+, works offline. To point the CLI at a local server:
export AGENTSCAN_API_URL=http://localhost:3100 # overrides the default API
License
MIT © baldbee
Independent project. Not affiliated with Anthropic, Snyk, or any vendor. Patterns modeled on gitleaks/trufflehog (secrets), OWASP Agentic Top 10, MCPGuard threat taxonomy, and Snyk's ToxicSkills findings.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentscan_cli-0.5.0.tar.gz.
File metadata
- Download URL: agentscan_cli-0.5.0.tar.gz
- Upload date:
- Size: 46.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bdca36bf13669df9f066a8524301f576620121ff7afc35bc1759056696fe008e
|
|
| MD5 |
0bf9b796f49fea87f72d3f6f3d3c4129
|
|
| BLAKE2b-256 |
e0506a80656933259ff17d58c643190cd657106207983275500f4ec76e3e8479
|
File details
Details for the file agentscan_cli-0.5.0-py3-none-any.whl.
File metadata
- Download URL: agentscan_cli-0.5.0-py3-none-any.whl
- Upload date:
- Size: 46.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2331d90700d2589488ec49c157a18c628e59825e8511417dbbcfd845274c1243
|
|
| MD5 |
156272027b0b67206970b42887199113
|
|
| BLAKE2b-256 |
180c338cfbd62077202ccd4b5b4c48c5005c7d23ada8dd15560069b5923e4845
|