Skip to main content
ClaudeWave
Skill7k repo starsupdated yesterday

semgrep-rule-variant-creator

This Claude Code skill ports existing Semgrep rules to new target programming languages by analyzing applicability, adapting patterns for each language's syntax and semantics, and generating language-specific rule files with corresponding test cases. Use it when expanding security rule coverage across polyglot codebases or translating vulnerability detection patterns between languages with equivalent constructs.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/trailofbits/skills /tmp/semgrep-rule-variant-creator && cp -r /tmp/semgrep-rule-variant-creator/plugins/semgrep-rule-variant-creator/skills/semgrep-rule-variant-creator ~/.claude/skills/semgrep-rule-variant-creator
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Semgrep Rule Variant Creator

Port an existing Semgrep rule to other languages, one independent test-driven cycle per
language.

For a new rule rather than a port, use `semgrep-rule-creator` — it takes a bug pattern
description where this skill takes a finished rule. That skill is also the reference for
rule-writing fundamentals: taint mode versus pattern matching, why tests come first, and
how to narrow a rule once it passes. Porting applies those same judgments in a new
language, so start there when the rule structure itself is the open question.

## Run it as a workflow

Porting is the same four phases repeated per language, so the orchestration ships as a
dynamic workflow rather than as instructions to re-follow each run:

```
/semgrep-rule-variant-creator:port-rule-to-languages
```

Pass the three required arguments, and `outputDir` unless the working directory is where you
want the variants. One language per entry: `"Go and Java"` ports a single language named after
the phrase, and the script rejects it.

`referencesDir` has to be a resolved absolute path. Resolve it here, because no workflow script
can expand a variable. Try in order, first hit wins — the `-d` is the point, since a bare `ls`
prints the names of the files inside the directory rather than the directory itself and leaves
nothing to copy:

1. **Claude Code** — `ls -d -- "${CLAUDE_PLUGIN_ROOT}/skills/semgrep-rule-variant-creator/references"`
2. **Codex** — the same command with `${CODEX_PLUGIN_ROOT}`, if that variable is set instead
3. **Neither set** — `find ~/.claude ~/.codex . -type d -path '*/semgrep-rule-variant-creator/skills/*/references' -print -quit 2>/dev/null`

Then confirm the directory that printed holds both reference files, with `ls -1 -- "<that path>"`.

Pass the path exactly as printed. If all three come back empty, stop and say so rather than
assembling a path by hand: the script rejects a relative path and an unexpanded token, but a
hand-built absolute path that happens not to exist clears every guard it has, and the run then
reports every language as passed having read no guidance at all.

```json
{
  "rulePath": "<path to the rule being ported>",
  "languages": ["Go", "Java"],
  "referencesDir": "<the absolute path the ls above printed>",
  "outputDir": "<where the variant directories should land>"
}
```

A workflow script cannot expand `{baseDir}` or `${CLAUDE_PLUGIN_ROOT}`, and has no filesystem
access to notice that it did not; an installed plugin does not sit in the user's project
either, so `referencesDir` is the only route by which the references below reach the phase
agents. The script rejects a run that omits it and one that passes a token instead of a path,
rather than porting without them, since a port made without this guidance still reports every
language as passed. `outputDir` is the one optional argument, defaulting to the working
directory, which is rarely what you want inside a repository.

It reads the rule once, then runs each language through the full cycle independently, and
reports which languages passed, which failed validation, which it judged not applicable, which
Semgrep cannot analyze at all, and which it stopped on — a language key it does not recognize,
two entries resolving to one directory, or a refuter that never reported back. A stop names
what to change and will happen again on a re-run, which is what separates it from an agent that
died. The rule travels as a path, not as text: every phase
reads the file, because an agent asked to repeat a rule back verbatim does not — one
HTML-escaped `<` and `>` and broke the `<... ...>` operator for every phase downstream.

If a run is interrupted while the session is still alive — you stopped it, or an agent hit a
terminal error — relaunch it with
`Workflow({scriptPath: "…", resumeFromRunId: "<runId>", args: {…}})`, passing the same
arguments again. Arguments are not saved with a run, so a resume that omits them fails the
pre-flight check above before replaying anything; with them, languages that finished replay
from cache and only the unfinished ones re-run.

Resume is same-session only, which rules it out for the interruption a long port is most
likely to hit: a session limit ends the session, and runs are stored under that session's own
directory, so the next session cannot reach them. A run id it cannot resolve is not an error
either — the workflow starts from scratch under that id and re-runs every language at full
cost, with nothing saying so. Check the id is still there before counting on a resume:

```
ls -d ~/.claude/projects/*/*/subagents/workflows/*/
```

That is where runs land today rather than a documented interface, so an empty result may mean the
layout moved rather than that the run is gone. The safe reading is the same either way: if you
cannot confirm the id, or the session ended, re-invoke with the same arguments and point
`outputDir` somewhere fresh. The script never deletes a directory, so a language that flipped to
`NOT_APPLICABLE` on the second run leaves the first run's variant behind.

The script is `workflows/port-rule-to-languages.js` at the plugin root. It pins a
reasoning effort per phase — cheap to read the rule, highest for translation and for the
fix-until-green loop — and encodes the phase order, so a rule cannot be written before
the tests that specify it. It also keeps the two decisions that have no oracle out of any
single agent's hands: a `NOT_APPLICABLE` verdict goes to an independent refuter before the
language is dropped, and failed validation is retried up to three times rather than
trusting one agent to iterate until green.

Run the phases by hand when you are porting to a single language and want to stay in the
loop, or when a port is already half-finished and you only need one phase. The workflow is
the only delegation a port needs: one agent to read the rule, and four per language when
the port goes green first try — a refuted verdict adds one, and so does each validation
retry.
agentic-actions-auditorSkill

Audits GitHub Actions workflows for security vulnerabilities in AI agent integrations including Claude Code Action, Gemini CLI, OpenAI Codex, and GitHub AI Inference. Detects attack vectors where attacker-controlled input reaches AI agents running in CI/CD pipelines, including env var intermediary patterns, direct expression injection, dangerous sandbox configurations, and wildcard user allowlists. Use when reviewing workflow files that invoke AI coding agents, auditing CI/CD pipeline security for prompt injection risks, or evaluating agentic action configurations.

ask-questions-if-underspecifiedSkill

Clarify requirements before implementing. Use when serious doubts arise.

audit-context-buildingSkill

Understand a codebase before looking for bugs in it - what each function assumes, what it guarantees, and what it depends on elsewhere. Use when starting an audit, threat model, or architecture review on unfamiliar code, and before any vulnerability-hunting pass.

algorand-vulnerability-scannerSkill

Scans Algorand smart contracts for 11 common vulnerabilities including rekeying attacks, unchecked transaction fees, missing field validations, and access control issues. Use when auditing Algorand projects (TEAL/PyTeal).

audit-prep-assistantSkill

Prepares codebases for security review using Trail of Bits' checklist. Helps set review goals, runs static analysis tools, increases test coverage, removes dead code, ensures accessibility, and generates documentation (flowcharts, user stories, inline comments). Use when preparing your own codebase to be audited by someone else, getting a repository review-ready before an external security review, deciding what to fix before auditors start, or asking what assessors need from a project. For understanding unfamiliar code you are about to audit, use audit-context-building instead.

cairo-vulnerability-scannerSkill

Scans Cairo/StarkNet smart contracts for 6 critical vulnerabilities including felt252 arithmetic overflow, L1-L2 messaging issues, address conversion problems, and signature replay. Use when auditing StarkNet projects.

code-maturity-assessorSkill

Systematic code maturity assessment using Trail of Bits' 9-category framework. Analyzes codebase for arithmetic safety, auditing practices, access controls, complexity, decentralization, documentation, MEV risks, low-level code, and testing, then produces a scorecard with evidence-based ratings and a priority-ordered roadmap. Use when assessing or scoring the maturity of a smart contract or blockchain codebase, producing a maturity scorecard or evaluation, or judging how mature, well-tested, or well-documented such a project is against a rubric.

cosmos-vulnerability-scannerSkill

Scans Cosmos SDK blockchain modules and CosmWasm contracts for consensus-critical vulnerabilities — chain halts, fund loss, state divergence. 25 core + 16 IBC + 10 EVM + 3 CosmWasm patterns. Use when auditing custom x/ modules, reviewing IBC integrations, or assessing pre-launch chain security. Updated for SDK v0.53.x.