agentic-actions-audito…
Audits GitHub Actions workflows for security vulnerabilities in AI agent integrations including Claude Code Action, Gemini CLI,…
Creates language variants of existing Semgrep rules. Use when porting a Semgrep rule to specified target languages. Takes an existing rule and target languages as input, produces independent rule+test directories for each language.
Claude Code
$ npx -y skills add trailofbits/skills --skill semgrep-rule-variant-creator --agent claude-code
Codex
$ npx skills add trailofbits/skills --skill semgrep-rule-variant-creator -a codex -y
Cursor
$ npx skills add trailofbits/skills --skill semgrep-rule-variant-creator -a cursor -y
Gemini CLI
$ npx skills add trailofbits/skills --skill semgrep-rule-variant-creator -a gemini-cli -y
GitHub Copilot
$ npx skills add trailofbits/skills --skill semgrep-rule-variant-creator -a github-copilot -y
OpenCode
$ npx skills add trailofbits/skills --skill semgrep-rule-variant-creator -a opencode -y
Windsurf
$ npx skills add trailofbits/skills --skill semgrep-rule-variant-creator -a windsurf -y
name: semgrep-rule-variant-creator description: Creates language variants of existing Semgrep rules. Use when porting a Semgrep rule to specified target languages. Takes an existing rule and target languages as input, produces independent rule+test directories for each language. allowed-tools: Bash Read Write Edit Glob Grep WebFetch Workflow
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.
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** — resolve `{baseDir}/references` from the directory containing this loaded SKILL.md and print its absolute path with `ls -d -- "<resolved path>"`. Do not search caches or the target project for another copy.
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.
{
"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 re
Trail of Bits skills and plugins for AI-assisted security analysis, testing, and development. Install this marketplace in Claude Code or Codex, or import it into your ChatGPT workspace marketplace.
Audits GitHub Actions workflows for security vulnerabilities in AI agent integrations including Claude Code Action, Gemini CLI,…
Understand a codebase before looking for bugs in it - what each function assumes, what it guarantees, and what it depends on…
Scans Algorand smart contracts for 11 common vulnerabilities including rekeying attacks, unchecked transaction fees, missing…
Prepares codebases for security review using Trail of Bits' checklist. Helps set review goals, runs static analysis tools,…
Scans Cairo/StarkNet smart contracts for 6 critical vulnerabilities including felt252 arithmetic overflow, L1-L2 messaging…
Systematic code maturity assessment using Trail of Bits' 9-category framework. Analyzes codebase for arithmetic safety, auditing…
Use for authorized security assessment of REST, GraphQL, WebSocket, or SOAP APIs, including discovery, authentication,…
Extract and decrypt Windows DPAPI-protected secrets (Credential Manager, browser logins/cookies, Wi-Fi credentials, KeePass keys)…
Clean and finalize authorized natural-language text intended for readers by auditing suspicious invisible Unicode and rewriting…