Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Run Semgrep static analysis scan on a codebase using parallel subagents. Supports two scan modes — "run all" (full ruleset coverage) and "important only" (high-confidence security vulnerabilities). Automatically detects and uses Semgrep Pro for cross-file taint analysis when available. Use when asked to scan code for vulnerabilities, run a security audit with Semgrep, find bugs, or perform static analysis. Spawns parallel workers for multi-language codebases.
.claude/skills/itamarzand88-semgrep/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | 36% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 67% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 70% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 133% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 104% | 0% |
<!-- source: trailofbits-semgrep — https://raw.githubusercontent.com/trailofbits/skills/main/plugins/static-analysis/skills/semgrep/SKILL.md -->
Run a Semgrep scan with automatic language detection, parallel execution via Task subagents, and merged SARIF output.
--metrics=off — Semgrep sends telemetry by default; --config auto also phones home. Every semgrep command must include --metrics=off to prevent data leakage during security audits.semgrep-rule-creator skillsemgrep-rule-variant-creator skillAll scan results, SARIF files, and temporary data are stored in a single output directory.
OUTPUT_DIR../static_analysis_semgrep_1. If that already exists, increment to _2, _3, etc.In both cases, always create the directory with mkdir -p before writing any files.
bash# Resolve output directory if [ -n "$USER_SPECIFIED_DIR" ]; then OUTPUT_DIR="$USER_SPECIFIED_DIR" else BASE="static_analysis_semgrep" N=1 while [ -e "${BASE}_${N}" ]; do N=$((N + 1)) done OUTPUT_DIR="${BASE}_${N}" fi mkdir -p "$OUTPUT_DIR/raw" "$OUTPUT_DIR/results"
The output directory is resolved once at the start of Step 1 and used throughout all subsequent steps.
$OUTPUT_DIR/
├── rulesets.txt # Approved rulesets (logged after Step 3)
├── raw/ # Per-scan raw output (unfiltered)
│ ├── python-python.json
│ ├── python-python.sarif
│ ├── python-django.json
│ ├── python-django.sarif
│ └── ...
└── results/ # Final merged output
└── results.sarifRequired: Semgrep CLI (semgrep --version). If not installed, see Semgrep installation docs.
Optional: Semgrep Pro — enables cross-file taint tracking, inter-procedural analysis, and additional languages (Apex, C#, Elixir). Check with:
bashsemgrep --pro --validate --config p/default 2>/dev/null && echo "Pro available" || echo "OSS only"
Limitations: OSS mode cannot track data flow across files. Pro mode uses -j 1 for cross-file analysis (slower per ruleset, but parallel rulesets compensate).
Select mode in Step 2 of the workflow. Mode affects both scanner flags and post-processing.
| Mode | Coverage | Findings Reported | |------|----------|-------------------| | Run all | All rulesets, all severity levels | Everything | | Important only | All rulesets, pre- and post-filtered | Security vulns only, medium-high confidence/impact |
Important only applies two filter layers:
--severity MEDIUM --severity HIGH --severity CRITICAL (CLI flag)category=security, confidence∈{MEDIUM,HIGH}, impact∈{MEDIUM,HIGH}See scan-modes.md for metadata criteria and jq filter commands.
┌──────────────────────────────────────────────────────────────────┐
│ MAIN AGENT (this skill) │
│ Step 1: Detect languages + check Pro availability │
│ Step 2: Select scan mode + rulesets (ref: rulesets.md) │
│ Step 3: Present plan + rulesets, get approval [⛔ HARD GATE] │
│ Step 4: Spawn parallel scan Tasks (approved rulesets + mode) │
│ Step 5: Merge results and report │
└──────────────────────────────────────────────────────────────────┘
│ Step 4
▼
┌─────────────────┐
│ Scan Tasks │
│ (parallel) │
├─────────────────┤
│ Python scanner │
│ JS/TS scanner │
│ Go scanner │
│ Docker scanner │
└─────────────────┘Follow the detailed workflow in scan-workflow.md. Summary:
| Step | Action | Gate | Key Reference | |------|--------|------|---------------| | 1 | Resolve output dir, detect languages + Pro availability | — | Use Glob, not Bash | | 2 | Select scan mode + rulesets | — | rulesets.md | | 3 | Present plan, get explicit approval | ⛔ HARD | AskUserQuestion | | 4 | Spawn parallel scan Tasks | — | scanner-task-prompt.md | | 5 | Merge results and report | — | Merge script (below) |
Task enforcement: On invocation, create 5 tasks with blockedBy dependencies (each step blocks the previous). Step 3 is a HARD GATE — mark complete ONLY after user explicitly approves.
Merge command (Step 5):
bashuv run {baseDir}/scripts/merge_sarif.py $OUTPUT_DIR/raw $OUTPUT_DIR/results/results.sarif
| Agent | Tools | Purpose | |-------|-------|---------| | static-analysis:semgrep-scanner | Bash | Executes parallel semgrep scans for a language category |
Use subagent_type: static-analysis:semgrep-scanner in Step 4 when spawning Task subagents.
| Shortcut | Why It's Wrong | |----------|----------------| | "User asked for scan, that's approval" | Original request ≠ plan approval. Present plan, use AskUserQuestion, await explicit "yes" | | "Step 3 task is blocking, just mark complete" | Lying about task status defeats enforcement. Only mark complete after real approval | | "I already know what they want" | Assumptions cause scanning wrong directories/rulesets. Present plan for verification | | "Just use default rulesets" | User must see and approve exact rulesets before scan | | "Add extra rulesets without asking" | Modifying approved list without consent breaks trust | | "Third-party rulesets are optional" | Trail of Bits, 0xdea, Decurity catch vulnerabilities not in official registry — REQUIRED | | "Use --config auto" | Sends metrics; less control over rulesets | | "One Task at a time" | Defeats parallelism; spawn all Tasks together | | "Pro is too slow, skip --pro" | Cross-file analysis catches 250% more true positives; worth the time | | "Semgrep handles GitHub URLs natively" | URL handling fails on repos with non-standard YAML; always clone first | | "Cleanup is optional" | Cloned repos pollute the user's workspace and accumulate across runs | | "Use . or relative path as target" | Subagents need absolute paths to avoid ambiguity | | "Let the user pick an output dir later" | Output directory must be resolved at Step 1, before any files are created |
| File | Content | |------|---------| | rulesets.md | Complete ruleset catalog and selection algorithm | | scan-modes.md | Pre/post-filter criteria and jq commands | | scanner-task-prompt.md | Template for spawning scanner subagents |
| Workflow | Purpose | |----------|---------| | scan-workflow.md | Complete 5-step scan execution process |
$OUTPUT_DIRsemgrep command used --metrics=off$OUTPUT_DIR/rulesets.txt$OUTPUT_DIR/raw/results.sarif exists in $OUTPUT_DIR/results/ and is valid JSONraw/$OUTPUT_DIR/repos/| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 6,888 | 8,018 | +16% | 1 | 1 | 0% | 668 | 3,139 | +370% | 0 | 0 | — |
case-02 | fail→fail | 11,036 | 6,922 | -37% | 1 | 1 | 0% | 1,500 | 2,997 | +100% | 0 | 0 | — |
case-03 | fail→fail | 7,649 | 7,151 | -7% | 1 | 1 | 0% | 900 | 3,113 | +246% | 0 | 0 | — |
case-04 | pass→pass | 2,983 | 3,033 | +2% | 1 | 1 | 0% | 606 | 3,023 | +399% | 0 | 0 | — |
case-05 | fail→pass | 15,167 | 7,644 | -50% | 1 | 1 | 0% | 2,952 | 4,001 | +36% | 0 | 0 | — |
case-06 | pass→pass | 6,307 | 2,885 | -54% | 1 | 1 | 0% | 1,281 | 2,916 | +128% | 0 | 0 | — |
case-07 | fail→fail | 17,654 | 7,128 | -60% | 1 | 1 | 0% | 2,995 | 3,704 | +24% | 0 | 0 | — |
case-08 | fail→pass | 9,889 | 2,837 | -71% | 1 | 1 | 0% | 1,715 | 2,857 | +67% | 0 | 0 | — |
case-09 | fail→pass | 10,751 | 4,854 | -55% | 1 | 1 | 0% | 1,999 | 3,403 | +70% | 0 | 0 | — |
case-10 | fail→pass | 7,558 | 2,927 | -61% | 1 | 1 | 0% | 1,231 | 2,867 | +133% | 0 | 0 | — |
case-11 | fail→pass | 7,001 | 2,044 | -71% | 1 | 1 | 0% | 1,366 | 2,786 | +104% | 0 | 0 | — |
case-12 | pass→fail | 7,275 | 2,198 | -70% | 1 | 1 | 0% | 1,212 | 2,659 | +119% | 0 | 0 | — |
case-13 | pass→pass | 10,580 | 2,786 | -74% | 1 | 1 | 0% | 1,791 | 2,753 | +54% | 0 | 0 | — |
case-14 | fail→pass | 10,611 | 1,374 | -87% | 1 | 1 | 0% | 1,844 | 2,542 | +38% | 0 | 0 | — |
case-15 | pass→pass | 10,164 | 3,987 | -61% | 1 | 1 | 0% | 1,673 | 3,045 | +82% | 0 | 0 | — |
case-16 | fail→pass | 11,147 | 1,273 | -89% | 1 | 1 | 0% | 1,835 | 2,564 | +40% | 0 | 0 | — |
case-17 | pass→pass | 6,063 | 2,182 | -64% | 1 | 1 | 0% | 1,005 | 2,694 | +168% | 0 | 0 | — |
case-18 | fail→pass | 2,707 | 2,111 | -22% | 1 | 1 | 0% | 459 | 2,706 | +490% | 0 | 0 | — |
case-19 | pass→pass | 8,937 | 7,921 | -11% | 1 | 1 | 0% | 645 | 3,017 | +368% | 0 | 0 | — |
case-20 | fail→fail | 13,542 | 24,262 | +79% | 1 | 1 | 0% | 2,648 | 7,137 | +170% | 0 | 0 | — |
case-21 | fail→fail | 7,912 | 7,033 | -11% | 1 | 1 | 0% | 859 | 3,079 | +258% | 0 | 0 | — |
case-22 | fail→fail | 14,405 | 12,068 | -16% | 1 | 1 | 0% | 2,569 | 4,459 | +74% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +32 percentage points is the difference between those two pass rates over the 22 comparable cases. 2 cases got worse with the skill loaded, and they are included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.