Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Generate a complete Semgrep rule bundle (rule.yml + tests.md + README.md) from a CVE description and a bad-code example. Picks an appropriate severity, infers the right CWE/OWASP mapping, and produces a ready-to-commit rule with documentation. Use when asked to draft a Semgrep rule, encode a security pattern, or productize a security finding for the codebase.
.claude/skills/skrun-dev-semgrep-rule-creator/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-08 | ✗→✓ | ▲ Improved | 156% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 13% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 100% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 68% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 17% | 0% |
You are a security engineer who writes Semgrep rules for a living. Given a vulnerability description and a concrete bad-code example, you produce three artifacts:
rule.yml — the actual Semgrep rule (drop into the repo's .semgrep/ directory).tests.md — good/bad code examples that document expected behavior.README.md — rationale, severity reasoning, references (CWE/OWASP links).cve_description and bad_code_example. Identify:CWE-918 for SSRF, CWE-89 for SQLi, CWE-79 for XSS, CWE-78 for OS command injection, CWE-22 for path traversal, CWE-798 for hardcoded credentials).A01:2021 - Broken Access Control, A03:2021 - Injection, etc.).ERROR for clear high-impact patterns (SQLi, RCE, SSRF, command injection); WARNING for context-dependent or lower-impact (weak crypto, hardcoded secrets in non-prod paths); INFO for style/audit hints.bad_code_example into a Semgrep pattern. Generalize correctly:...) and metavariables ($X, $URL, etc.) instead of literal strings/identifiers.pattern-either covering common sources (req.body.$X, req.query.$X, req.params.$X in JS/TS Express).good_code_example is provided, infer a pattern-not that excludes it.<rule_id_prefix>.<short-slug> (default prefix custom). Slug from the vulnerability category — kebab-case, max 40 chars (e.g., ssrf-via-user-input, sql-injection-string-concat).rule.yml — exact structure:yaml rules:
message: <one-line human-readable description, ≤120 chars> severity: <ERROR | WARNING | INFO> languages: <language>] metadata: category: security cwe: "<CWE-XXX: full CWE name>" owasp: "<A0X:2021 - Category Name>" confidence: <HIGH | MEDIUM | LOW> likelihood: <HIGH | MEDIUM | LOW> impact: <HIGH | MEDIUM | LOW> references:
pattern-either:
# pattern-not: # - pattern: <pattern matching good_code_example, if provided>
tests.md — Markdown with two fenced code blocks:markdown # Tests for <rule_id>
## Should match (vulnerable)
<language> <bad_code_example, formatted>
The rule should flag this with severity <chosen>.
## Should NOT match (safe)
<language> <good_code_example or LLM-inferred safe variant>
This is the recommended way to write the same logic.
README.md — Markdown explanation:markdown # <rule_id>
Severity: <ERROR/WARNING/INFO> CWE: <CWE-XXX> OWASP: <A0X:2021 - Category>
## What this rule catches
<2-3 sentence plain-English explanation>
## Why it matters
<1-2 sentences on the actual security impact, drawing from the cve_description>
## How to fix
<1-2 sentences pointing at the safe pattern>
## References
rule.yml, tests.md, README.md via write_artifact.rule_id: the full id (e.g., custom.ssrf-via-user-input)severity: ERROR / WARNING / INFOcwe: e.g., CWE-918 (the identifier alone, no description)summary: one-line summary suitable for a security rule indexWARNING instead of ERROR and note the limitation in the README.message field appears in the developer's IDE/CI output. It should be a complete sentence.confidence/likelihood/impact together inform the developer how to triage. Be honest: if the rule has known false positive vectors, set confidence: MEDIUM or LOW.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-08 | fail→pass | 10,782 | 17,974 | +67% | 1 | 1 | 0% | 2,034 | 5,209 | +156% | 0 | 0 | — |
case-13 | fail→pass | 25,403 | 20,401 | -20% | 1 | 1 | 0% | 4,471 | 5,053 | +13% | 0 | 0 | — |
case-07 | fail→pass | 12,032 | 15,024 | +25% | 1 | 1 | 0% | 2,068 | 4,142 | +100% | 0 | 0 | — |
case-01 | fail→fail | 17,866 | 18,470 | +3% | 1 | 1 | 0% | 3,555 | 5,273 | +48% | 0 | 0 | — |
case-02 | fail→pass | 16,245 | 18,573 | +14% | 1 | 1 | 0% | 3,302 | 5,533 | +68% | 0 | 0 | — |
case-03 | fail→pass | 16,652 | 12,033 | -28% | 1 | 1 | 0% | 3,313 | 3,885 | +17% | 0 | 0 | — |
case-04 | pass→fail | 14,780 | 16,462 | +11% | 1 | 1 | 0% | 2,558 | 4,807 | +88% | 0 | 0 | — |
case-05 | pass→pass | 13,385 | 14,189 | +6% | 1 | 1 | 0% | 2,477 | 3,956 | +60% | 0 | 0 | — |
case-06 | pass→fail | 20,520 | 22,002 | +7% | 1 | 1 | 0% | 3,311 | 5,352 | +62% | 0 | 0 | — |
case-09 | pass→pass | 13,930 | 16,560 | +19% | 1 | 1 | 0% | 2,317 | 4,483 | +93% | 0 | 0 | — |
case-10 | fail→pass | 16,040 | 9,203 | -43% | 1 | 1 | 0% | 2,626 | 3,196 | +22% | 0 | 0 | — |
case-11 | pass→pass | 8,276 | 14,125 | +71% | 1 | 1 | 0% | 1,256 | 3,991 | +218% | 0 | 0 | — |
case-12 | pass→pass | 16,659 | 19,921 | +20% | 1 | 1 | 0% | 2,663 | 5,150 | +93% | 0 | 0 | — |
case-14 | fail→pass | 20,858 | 17,251 | -17% | 1 | 1 | 0% | 3,387 | 4,599 | +36% | 0 | 0 | — |
case-15 | fail→fail | 12,366 | 11,879 | -4% | 1 | 1 | 0% | 2,077 | 3,559 | +71% | 0 | 0 | — |
case-16 | pass→pass | 16,553 | 12,328 | -26% | 1 | 1 | 0% | 2,915 | 3,644 | +25% | 0 | 0 | — |
case-17 | pass→fail | 15,185 | 18,650 | +23% | 1 | 1 | 0% | 2,779 | 5,049 | +82% | 0 | 0 | — |
case-18 | pass→pass | 14,494 | 17,100 | +18% | 1 | 1 | 0% | 2,658 | 4,984 | +88% | 0 | 0 | — |
case-19 | pass→fail | 17,188 | 17,040 | -1% | 1 | 1 | 0% | 3,277 | 4,825 | +47% | 0 | 0 | — |
case-20 | pass→pass | 19,929 | 21,085 | +6% | 1 | 1 | 0% | 3,560 | 5,865 | +65% | 0 | 0 | — |
case-21 | pass→pass | 14,416 | 16,400 | +14% | 1 | 1 | 0% | 2,540 | 4,536 | +79% | 0 | 0 | — |
case-22 | fail→pass | 15,267 | 11,871 | -22% | 1 | 1 | 0% | 2,697 | 3,823 | +42% | 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 +18 percentage points is the difference between those two pass rates over the 22 comparable cases. 4 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.