/skill-audit - Skill Security Scanner
$ARGUMENTS
Scan skill and agent definitions for security risks before installation or after changes.
Usage
/skill-audit # Audit all skills
/skill-audit debug # Audit specific skill
/skill-audit --all --fix # Audit all + auto-fix safe issues
What This Command Does
- Scan SKILL.md frontmatter for permission issues
- Scan scripts/ for dangerous code patterns
- Scan reference/ for hardcoded secrets
- Report findings with severity levels
- Auto-fix safe issues when
--fix is passed
Security Checks
Frontmatter Checks
| Check |
Severity |
Description |
| Overly permissive tools |
WARN |
allowed-tools includes Bash + Write + Edit without justification |
| Missing allowed-tools |
WARN |
No tool restriction = full access |
| Knowledge skill with Bash |
HIGH |
user-invocable: false skills should not need Bash |
| Missing effort field |
INFO |
Best practice to declare effort |
Script Checks (Python)
| Pattern |
Severity |
Description |
eval( / exec( |
HIGH |
Arbitrary code execution |
os.system( |
HIGH |
Shell injection risk |
subprocess.*shell=True |
HIGH |
Shell injection risk |
__import__ |
WARN |
Dynamic imports |
pickle.loads |
HIGH |
Deserialization attack |
open(.*'w') without path validation |
WARN |
Arbitrary file write |
Script Checks (Bash)
| Pattern |
Severity |
Description |
curl.*| bash |
HIGH |
Remote code execution |
curl.*| sh |
HIGH |
Remote code execution |
wget.*| bash |
HIGH |
Remote code execution |
rm -rf / or rm -rf ~ |
HIGH |
Destructive command |
Unquoted $variables in commands |
WARN |
Word splitting / injection |
chmod 777 |
WARN |
Overly permissive |
Secret Detection
| Pattern |
Severity |
Description |
AKIA[0-9A-Z]{16} |
HIGH |
AWS access key |
sk-[a-zA-Z0-9]{20,} |
HIGH |
API key pattern |
password\s*=\s*['"][^'"]+ |
WARN |
Hardcoded password |
token\s*=\s*['"][^'"]+ |
WARN |
Hardcoded token |
-----BEGIN.*PRIVATE KEY |
HIGH |
Private key |
ghp_[a-zA-Z0-9]{36} |
HIGH |
GitHub PAT |
Unicode Safety
Shipped prompt text (skills, agents, rules, personas, mcp-templates) is scanned for invisible/smuggled characters that a human reviewer cannot see. U+200D (ZWJ) is allowlisted so legitimate emoji sequences do not flag.
| Pattern |
Severity |
Description |
Tag block U+E0000–U+E007F |
HIGH |
ASCII smuggling / invisible prompt injection |
| Bidi controls (LRE/RLE/PDF/LRO/RLO, LRI/RLI/FSI/PDI) |
HIGH |
Trojan Source text reordering |
| Zero-width / invisible format chars (ZWSP, ZWNJ, WJ, BOM, soft hyphen, …) |
WARN |
Verify it is intentional |
Output Format
## Skill Audit Report
### Summary
- Skills scanned: N
- HIGH: N | WARN: N | INFO: N
### Findings
#### [HIGH] skill-name/scripts/helper.py:12
Pattern: `eval(user_input)`
Risk: Arbitrary code execution
Fix: Replace with `ast.literal_eval()` or explicit parsing
#### [WARN] skill-name/SKILL.md (frontmatter)
Pattern: Missing `allowed-tools`
Risk: Skill has unrestricted tool access
Fix: Add `allowed-tools: Read, Grep, Glob` (principle of least privilege)
Steps
- Determine scope: single skill (
$ARGUMENTS) or all skills
- For each skill directory in
app/skills/:
a. Read SKILL.md — check frontmatter fields
b. Glob scripts/**/*.py — scan for dangerous Python patterns
c. Glob scripts/**/*.sh — scan for dangerous Bash patterns
d. Grep all files for secret patterns
- Also scan
app/agents/*.md for overly broad tool lists
- Collect findings, sort by severity (HIGH > WARN > INFO)
- If
--fix is passed:
- Add missing
allowed-tools to SKILL.md frontmatter (suggest minimal set)
- Replace
eval( with ast.literal_eval( where safe
- Do NOT auto-fix HIGH severity — only report
- Print audit report
Deterministic Scanner
For CI pipelines or non-interactive use, run the Python scanner directly:
# Human-readable output
python3 scripts/audit_skills.py
# JSON output (for CI parsing)
python3 scripts/audit_skills.py --json
# CI mode: exit 1 on any HIGH finding
python3 scripts/audit_skills.py --ci
The /skill-audit slash command wraps this scanner with Claude's analysis for remediation suggestions.
Rules
- MUST remain read-only by default — file modifications require the explicit
--fix flag
- MUST exit with non-zero status on any HIGH finding so CI pipelines can gate merges
- NEVER auto-fix HIGH-severity findings — only the human owner decides on dangerous code
- NEVER silence findings by adding exceptions in the audit config; either fix the code or document why the pattern is safe in the skill body
- CRITICAL: scan both
app/skills/ and app/agents/ — agents without tool restrictions are the same risk class as skills with broad allowed-tools
- MANDATORY: every finding names a specific fix (replace
eval() with ast.literal_eval(), add missing allowed-tools). A finding without a fix is triage noise.
Gotchas
- Regex-based secret detection catches canonical patterns (
sk-..., ghp_...) but misses custom API key formats used by internal services. Augment the regex list with project-specific patterns before trusting "0 HIGH findings".
--fix on allowed-tools infers minimal tool sets from imports, but skills that shell out via Bash may need tools not visible in the static scan. Review auto-added restrictions before merging.
- Knowledge skills (
user-invocable: false) with Bash access are HIGH because they auto-load and can act without user triggering. Legitimate exceptions (e.g., research-mastery calling smart_query()) should be explicitly whitelisted in the audit config with a comment.
- The scanner flags
eval( even inside docstrings and commented-out code. Context-aware scanning is hard; the alternative is reviewing each HIGH flag manually — the scan errs on the side of false positives.
- CI integration with
--ci exits 1 on any HIGH, which blocks the commit. A sudden pattern match (e.g., a legitimate new use of subprocess.run) can block unrelated PRs. Keep a fast path for pre-approving new patterns.
When NOT to Use
- For general code-quality metrics (complexity, coverage, duplication) — use
/analyze
- For dependency CVE scans — use
/cve-scan
- For HIPAA-specific audits — use
/hipaa-validate
- For live pentesting of a deployed app — delegate to the
security-auditor agent
- When the project has its own security scanner (semgrep, snyk) — prefer it;
/skill-audit is toolkit-specific
1---2name: skill-audit3description: Scans skills/agents for security risks: dangerous patterns, secrets, excessive perms. Triggers: skill audit, security scan, agent audit, dangerous pattern.4---56# /skill-audit - Skill Security Scanner78$ARGUMENTS910Scan skill and agent definitions for security risks before installation or after changes.1112## Usage1314```15/skill-audit # Audit all skills16/skill-audit debug # Audit specific skill17/skill-audit --all --fix # Audit all + auto-fix safe issues18```1920## What This Command Does21221. **Scan SKILL.md frontmatter** for permission issues232. **Scan scripts/** for dangerous code patterns243. **Scan reference/** for hardcoded secrets254. **Report** findings with severity levels265. **Auto-fix** safe issues when `--fix` is passed2728## Security Checks2930### Frontmatter Checks3132| Check | Severity | Description |33|-------|----------|-------------|34| Overly permissive tools | WARN | `allowed-tools` includes Bash + Write + Edit without justification |35| Missing allowed-tools | WARN | No tool restriction = full access |36| Knowledge skill with Bash | HIGH | `user-invocable: false` skills should not need Bash |37| Missing effort field | INFO | Best practice to declare effort |3839### Script Checks (Python)4041| Pattern | Severity | Description |42|---------|----------|-------------|43| `eval(` / `exec(` | HIGH | Arbitrary code execution |44| `os.system(` | HIGH | Shell injection risk |45| `subprocess.*shell=True` | HIGH | Shell injection risk |46| `__import__` | WARN | Dynamic imports |47| `pickle.loads` | HIGH | Deserialization attack |48| `open(.*'w')` without path validation | WARN | Arbitrary file write |4950### Script Checks (Bash)5152| Pattern | Severity | Description |53|---------|----------|-------------|54| `curl.*\| bash` | HIGH | Remote code execution |55| `curl.*\| sh` | HIGH | Remote code execution |56| `wget.*\| bash` | HIGH | Remote code execution |57| `rm -rf /` or `rm -rf ~` | HIGH | Destructive command |58| Unquoted `$variables` in commands | WARN | Word splitting / injection |59| `chmod 777` | WARN | Overly permissive |6061### Secret Detection6263| Pattern | Severity | Description |64|---------|----------|-------------|65| `AKIA[0-9A-Z]{16}` | HIGH | AWS access key |66| `sk-[a-zA-Z0-9]{20,}` | HIGH | API key pattern |67| `password\s*=\s*['"][^'"]+` | WARN | Hardcoded password |68| `token\s*=\s*['"][^'"]+` | WARN | Hardcoded token |69| `-----BEGIN.*PRIVATE KEY` | HIGH | Private key |70| `ghp_[a-zA-Z0-9]{36}` | HIGH | GitHub PAT |7172### Unicode Safety7374Shipped prompt text (skills, agents, rules, personas, mcp-templates) is scanned for invisible/smuggled characters that a human reviewer cannot see. `U+200D` (ZWJ) is allowlisted so legitimate emoji sequences do not flag.7576| Pattern | Severity | Description |77|---------|----------|-------------|78| Tag block `U+E0000–U+E007F` | HIGH | ASCII smuggling / invisible prompt injection |79| Bidi controls (LRE/RLE/PDF/LRO/RLO, LRI/RLI/FSI/PDI) | HIGH | Trojan Source text reordering |80| Zero-width / invisible format chars (ZWSP, ZWNJ, WJ, BOM, soft hyphen, …) | WARN | Verify it is intentional |8182## Output Format8384```markdown85## Skill Audit Report8687### Summary88- Skills scanned: N89- HIGH: N | WARN: N | INFO: N9091### Findings9293#### [HIGH] skill-name/scripts/helper.py:1294Pattern: `eval(user_input)`95Risk: Arbitrary code execution96Fix: Replace with `ast.literal_eval()` or explicit parsing9798#### [WARN] skill-name/SKILL.md (frontmatter)99Pattern: Missing `allowed-tools`100Risk: Skill has unrestricted tool access101Fix: Add `allowed-tools: Read, Grep, Glob` (principle of least privilege)102```103104## Steps1051061. Determine scope: single skill (`$ARGUMENTS`) or all skills1072. For each skill directory in `app/skills/`:108 a. Read `SKILL.md` — check frontmatter fields109 b. Glob `scripts/**/*.py` — scan for dangerous Python patterns110 c. Glob `scripts/**/*.sh` — scan for dangerous Bash patterns111 d. Grep all files for secret patterns1123. Also scan `app/agents/*.md` for overly broad tool lists1134. Collect findings, sort by severity (HIGH > WARN > INFO)1145. If `--fix` is passed:115 - Add missing `allowed-tools` to SKILL.md frontmatter (suggest minimal set)116 - Replace `eval(` with `ast.literal_eval(` where safe117 - Do NOT auto-fix HIGH severity — only report1186. Print audit report119120## Deterministic Scanner121122For CI pipelines or non-interactive use, run the Python scanner directly:123124```bash125# Human-readable output126python3 scripts/audit_skills.py127128# JSON output (for CI parsing)129python3 scripts/audit_skills.py --json130131# CI mode: exit 1 on any HIGH finding132python3 scripts/audit_skills.py --ci133```134135The `/skill-audit` slash command wraps this scanner with Claude's analysis for remediation suggestions.136137## Rules138139- **MUST** remain read-only by default — file modifications require the explicit `--fix` flag140- **MUST** exit with non-zero status on any HIGH finding so CI pipelines can gate merges141- **NEVER** auto-fix HIGH-severity findings — only the human owner decides on dangerous code142- **NEVER** silence findings by adding exceptions in the audit config; either fix the code or document why the pattern is safe in the skill body143- **CRITICAL**: scan both `app/skills/` and `app/agents/` — agents without tool restrictions are the same risk class as skills with broad `allowed-tools`144- **MANDATORY**: every finding names a specific fix (replace `eval()` with `ast.literal_eval()`, add missing `allowed-tools`). A finding without a fix is triage noise.145146## Gotchas147148- Regex-based secret detection catches canonical patterns (`sk-...`, `ghp_...`) but misses custom API key formats used by internal services. Augment the regex list with project-specific patterns before trusting "0 HIGH findings".149- `--fix` on `allowed-tools` infers minimal tool sets from imports, but skills that shell out via Bash may need tools not visible in the static scan. Review auto-added restrictions before merging.150- Knowledge skills (`user-invocable: false`) with Bash access are HIGH because they auto-load and can act without user triggering. Legitimate exceptions (e.g., `research-mastery` calling `smart_query()`) should be explicitly whitelisted in the audit config with a comment.151- The scanner flags `eval(` even inside docstrings and commented-out code. Context-aware scanning is hard; the alternative is reviewing each HIGH flag manually — the scan errs on the side of false positives.152- CI integration with `--ci` exits 1 on any HIGH, which **blocks the commit**. A sudden pattern match (e.g., a legitimate new use of `subprocess.run`) can block unrelated PRs. Keep a fast path for pre-approving new patterns.153154## When NOT to Use155156- For general code-quality metrics (complexity, coverage, duplication) — use `/analyze`157- For dependency CVE scans — use `/cve-scan`158- For HIPAA-specific audits — use `/hipaa-validate`159- For live pentesting of a deployed app — delegate to the `security-auditor` agent160- When the project has its own security scanner (semgrep, snyk) — prefer it; `/skill-audit` is toolkit-specific