Kedro Security Review
kedro-org/kedro
Run a Kedro security scan on the full codebase or just a pull request.
Parses and processes SARIF files from static analysis tools like CodeQL, Semgrep, or other scanners.
$ npx skills add trailofbits/skills --skill sarif-parsing -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install trailofbits/skills sarif-parsing --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/trailofbits/skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/static-analysis/skills/sarif-parsing .claude/skills/sarif-parsing && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "sarif-parsing" agent skill from https://github.com/trailofbits/skills/tree/main/plugins/static-analysis/skills/sarif-parsing into .claude/skills/sarif-parsing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sarif-parsing", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/trailofbits/skills/tree/main/plugins/static-analysis/skills/sarif-parsingType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add trailofbits/skills --skill sarif-parsing -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install trailofbits/skills sarif-parsing --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/trailofbits/skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/static-analysis/skills/sarif-parsing .agents/skills/sarif-parsing && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "sarif-parsing" agent skill from https://github.com/trailofbits/skills/tree/main/plugins/static-analysis/skills/sarif-parsing into .agents/skills/sarif-parsing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sarif-parsing", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add trailofbits/skills --skill sarif-parsing -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install trailofbits/skills sarif-parsing --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/trailofbits/skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/static-analysis/skills/sarif-parsing .cursor/skills/sarif-parsing && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "sarif-parsing" agent skill from https://github.com/trailofbits/skills/tree/main/plugins/static-analysis/skills/sarif-parsing into .cursor/skills/sarif-parsing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sarif-parsing", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/trailofbits/skills.git --path plugins/static-analysis/skills/sarif-parsing--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add trailofbits/skills --skill sarif-parsing -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install trailofbits/skills sarif-parsing --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/trailofbits/skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/static-analysis/skills/sarif-parsing .gemini/skills/sarif-parsing && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "sarif-parsing" agent skill from https://github.com/trailofbits/skills/tree/main/plugins/static-analysis/skills/sarif-parsing into .gemini/skills/sarif-parsing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sarif-parsing", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install trailofbits/skills sarif-parsingInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add trailofbits/skills --skill sarif-parsing -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/trailofbits/skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/static-analysis/skills/sarif-parsing .github/skills/sarif-parsing && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "sarif-parsing" agent skill from https://github.com/trailofbits/skills/tree/main/plugins/static-analysis/skills/sarif-parsing into .github/skills/sarif-parsing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sarif-parsing", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add trailofbits/skills --skill sarif-parsing -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install trailofbits/skills sarif-parsing --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/trailofbits/skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/static-analysis/skills/sarif-parsing .opencode/skills/sarif-parsing && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "sarif-parsing" agent skill from https://github.com/trailofbits/skills/tree/main/plugins/static-analysis/skills/sarif-parsing into .opencode/skills/sarif-parsing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "sarif-parsing", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
sarif-parsingParses and processes SARIF files from static analysis tools like CodeQL, Semgrep, or other scanners.
Sarif Parsing is an agent skill from trailofbits/skills, published by the product's own GitHub organization. Parses and processes SARIF files from static analysis tools like CodeQL, Semgrep, or other scanners. Triggers on "parse sarif", "read scan results", "aggregate findings", "deduplicate alerts", or "process sarif output". Handles filtering, deduplication, format conversion, and CI/CD integration of SARIF data. Does NOT run scans — use the Semgrep or CodeQL skills for that.
Its SKILL.md is about 4.4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 11 other files, including assets (for example `agents/openai.yaml`, `resources/jq-queries.md` and `resources/sarif_helpers.py`).
It sits in Security, covering Static analysis and SAST. It works with Semgrep and Python. The repository describes itself as: Trail of Bits Claude Code skills for security research, vulnerability detection, and audit workflows. The licence is CC-BY-SA-4.0.
5 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 82fe822. It shows what the files ask for, not the result of running them.
Pre-approves these tools, so the agent can use them without asking each time:
BashReadGlobGrepFrom allowed-tools in the SKILL.md frontmatter.
Ships script files (Python), which the agent can run.
Shell commands in SKILL.md call:
jquvnpmbrewaptgoFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
json.schemastore.orgAlso links to:
github.comdocs.oasis-open.orgdocs.github.comsarifweb.azurewebsites.netFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Sarif Parsing loads about 4.4k tokens when it runs. Until then it costs about 97 tokens; SKILL.md has 894 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
allowed-tools: Bash, Read, Glob, GrepAutomated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from trailofbits/skills at commit 82fe822, republished under its CC-BY-SA-4.0 licence (© trailofbits). 894 words, ~4,439 tokens.
.claude/skills/sarif-parsing/SKILL.md (or your agent's skills folder). This skill also uses 7 other files; get the full folder from GitHub.You are a SARIF parsing expert. Your role is to help users effectively read, analyze, and process SARIF files from static analysis tools.
Use this skill when:
Do NOT use this skill for:
SARIF 2.1.0 is the current OASIS standard. Every SARIF file has this hierarchical structure:
sarifLog
├── version: "2.1.0"
├── $schema: (optional, enables IDE validation)
└── runs[] (array of analysis runs)
├── tool
│ ├── driver
│ │ ├── name (required)
│ │ ├── version
│ │ └── rules[] (rule definitions)
│ └── extensions[] (plugins)
├── results[] (findings)
│ ├── ruleId
│ ├── ruleIndex (index into tool.driver.rules[])
│ ├── level (OPTIONAL, inherited from the rule when absent)
│ ├── message.text
│ ├── locations[]
│ │ └── physicalLocation
│ │ ├── artifactLocation.uri
│ │ └── region (startLine, startColumn, etc.)
│ ├── fingerprints{}
│ └── partialFingerprints{}
└── artifacts[] (scanned files metadata)result.level is optional. CodeQL omits it on every result and records severity on the
rule as defaultConfiguration.level, which the result inherits. Read result.level
directly and a CodeQL run scores as clean however many errors it found, which is how a
severity gate ends up exiting 0 on a failing repo.
Resolve severity in this order (SARIF 2.1.0 section 3.27.10):
kind other than "fail" (a pass/notApplicable record), so "none"result.level, when presentdefaultConfiguration.level, joining ruleIndex into
runs[].tool.driver.rules[], or matching ruleId against rules[].id when the tool
omits ruleIndex"warning", the SARIF defaultEvery severity query in this skill starts from that resolution. In jq it is the
LEVEL_FN definition in {baseDir}/resources/jq-queries.md;
in Python it is resolve_level(result, run) in
{baseDir}/resources/sarif_helpers.py.
Without stable fingerprints, you can't track findings across runs:
Tools report different paths (/path/to/project/ vs /github/workspace/), so path-based matching fails. Fingerprints hash the content (code snippet, rule ID, relative location) to create stable identifiers regardless of environment.
| Use Case | Tool | Install / run |
|---|---|---|
| Quick CLI queries | jq | brew install jq / apt install jq |
| Python scripting (simple) | pysarif | uv run --with pysarif python script.py |
| Python scripting (advanced) | sarif-tools | uv run --with sarif-tools python script.py |
| .NET applications | SARIF SDK | NuGet package |
| JavaScript/Node.js | sarif-js | npm package |
| Go applications | garif | go get github.com/chavacava/garif |
| Validation | SARIF Validator | sarifweb.azurewebsites.net |
For rapid exploration and one-off queries:
# Pretty print the file
jq '.' results.sarif
# Count total findings
jq '[.runs[].results[]] | length' results.sarif
# List all rule IDs triggered
jq '[.runs[].results[].ruleId] | unique' results.sarif
# Severity resolution, needed by every query below that filters on level.
# See resources/jq-queries.md for the annotated version.
LEVEL_FN='
def rule($run):
. as $r
| ($run.tool.driver.rules // []) as $rules
| (if ($r.ruleIndex | type) == "number" and $r.ruleIndex >= 0
then $rules[$r.ruleIndex] else null end)
// first($rules[] | select(.id == $r.ruleId))
// null;
def level($run):
. as $r
| if ($r.kind // "fail") != "fail" then "none"
else ($r.level // rule($run).defaultConfiguration.level // "warning") end;
'
# Extract errors only
jq "$LEVEL_FN"'.runs[] as $run | $run.results[] | select(level($run) == "error")' results.sarif
# Get findings with file locations
jq '.runs[].results[] | {
rule: .ruleId,
message: .message.text,
file: .locations[0].physicalLocation.artifactLocation.uri,
line: .locations[0].physicalLocation.region.startLine
}' results.sarif
# Filter by severity and get count per rule
jq "$LEVEL_FN"'[.runs[] as $run | $run.results[] | select(level($run) == "error")] | group_by(.ruleId) | map({rule: .[0].ruleId, count: length})' results.sarif
# Extract findings for a specific file
jq --arg file "src/auth.py" '.runs[].results[] | select(.locations[].physicalLocation.artifactLocation.uri | contains($file))' results.sarifFor programmatic access with full object model:
from pysarif import load_from_file, save_to_file
# Load SARIF file
sarif = load_from_file("results.sarif")
# Iterate through runs and results
for run in sarif.runs:
tool_name = run.tool.driver.name
print(f"Tool: {tool_name}")
for result in run.results:
# pysarif fills a missing result.level with "warning", so .level here is NOT the
# rule-inherited severity: a CodeQL error (no level on the result, severity on the
# rule) reads as "warning". Gate severity with Strategy 1's level() or with
# resolve_level() in resources/sarif_helpers.py, which resolve it from the rule.
print(f" {result.rule_id}: {result.message.text}")
if result.locations:
loc = result.locations[0].physical_location
if loc and loc.artifact_location:
print(f" File: {loc.artifact_location.uri}")
if loc.region:
print(f" Line: {loc.region.start_line}")
# Save modified SARIF
save_to_file(sarif, "modified.sarif")For aggregation, reporting, and CI/CD integration:
from sarif import loader
# Load single file
sarif_data = loader.load_sarif_file("results.sarif")
# Or load multiple files
sarif_set = loader.load_sarif_files(["tool1.sarif", "tool2.sarif"])
# Get summary report
report = sarif_data.get_report()
# Get histogram by severity
errors = report.get_issue_type_histogram_for_severity("error")
warnings = report.get_issue_type_histogram_for_severity("warning")
# Filter by severity. sarif-tools hands back raw result dicts, and a result's level may
# live on its rule, so resolve it against the run instead of reading r["level"].
from sarif_helpers import extract_findings, filter_by_level, load_sarif
high_severity = filter_by_level(extract_findings(load_sarif("results.sarif")), "error")sarif-tools CLI commands:
# Summary of findings
sarif summary results.sarif
# List all results with details
sarif ls results.sarif
# Get results by severity
sarif ls --level error results.sarif
# Diff two SARIF files (find new/fixed issues)
sarif diff baseline.sarif current.sarif
# Convert to other formats
sarif csv results.sarif > results.csv
sarif html results.sarif > report.htmlWhen combining results from multiple tools:
import json
from sarif_helpers import deduplicate, extract_findings
def aggregate_sarif_files(sarif_paths: list[str]) -> dict:
"""Combine multiple SARIF files into one."""
aggregated = {
"version": "2.1.0",
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"runs": []
}
for path in sarif_paths:
with open(path) as f:
sarif = json.load(f)
aggregated["runs"].extend(sarif.get("runs", []))
return aggregated
unique = deduplicate(extract_findings(aggregate_sarif_files(["tool1.sarif", "tool2.sarif"])))deduplicate() prefers whatever fingerprints or partialFingerprints the tool supplied
and falls back to hashing rule ID, the whole normalized path, line, and message. Keep the
directory in that key: the same rule at the same line in auth/login.py and
admin/login.py is two findings, and a basename-only key throws one of them away.
resources/sarif_helpers.py covers this with the standard library alone.
extract_findings() returns Finding objects whose severity is already resolved, and
filter_by_level(), sort_by_severity(), deduplicate() and diff_findings() consume
those:
from sarif_helpers import extract_findings, filter_by_level, load_sarif, sort_by_severity
findings = sort_by_severity(extract_findings(load_sarif("results.sarif")))
for f in filter_by_level(findings, "error"):
print(f"{f.file_path}:{f.start_line} [{f.level}] {f.rule_id}: {f.message}")Writing your own extractor, severity is the part that goes wrong silently:
def resolve_level(result: dict, run: dict) -> str:
"""Severity of a result: its own level, else its rule's default, else "warning"."""
if result.get("kind", "fail") != "fail":
return "none"
if result.get("level"):
return result["level"]
rules = run.get("tool", {}).get("driver", {}).get("rules", [])
index = result.get("ruleIndex")
rule = rules[index] if isinstance(index, int) and 0 <= index < len(rules) else next(
(r for r in rules if r.get("id") == result.get("ruleId")), {}
)
return rule.get("defaultConfiguration", {}).get("level") or "warning"Results carry ruleIndex on some tools and only ruleId on others, so a resolver that
joins one way alone silently returns the default for every result the other kind of tool
produces.
Different tools report paths differently (absolute, relative, URI-encoded), so
file:///src/a%20b.py and src/a b.py can be the same file. Strip the file:// scheme,
percent-decode, resolve against a base path, and normalize separators before comparing or
hashing anything: normalize_path() in resources/sarif_helpers.py does all four.
Fingerprints may not match if:
Solution: Use multiple fingerprint strategies:
def compute_stable_fingerprint(result: dict, file_content: str = None) -> str:
"""Compute environment-independent fingerprint."""
import hashlib
components = [
result.get("ruleId", ""),
result.get("message", {}).get("text", "")[:100], # First 100 chars
]
# Add code snippet if available
if file_content and result.get("locations"):
region = result["locations"][0].get("physicalLocation", {}).get("region", {})
if region.get("startLine"):
lines = file_content.split("\n")
line_idx = region["startLine"] - 1
if 0 <= line_idx < len(lines):
# Normalize whitespace
components.append(lines[line_idx].strip())
return hashlib.sha256("".join(components).encode()).hexdigest()[:16]SARIF allows many optional fields. Always use defensive access:
def safe_get_location(result: dict) -> tuple[str, int]:
"""Safely extract file and line from result."""
try:
loc = result.get("locations", [{}])[0]
phys = loc.get("physicalLocation", {})
file_path = phys.get("artifactLocation", {}).get("uri", "unknown")
line = phys.get("region", {}).get("startLine", 0)
return file_path, line
except (IndexError, KeyError, TypeError):
return "unknown", 0For very large SARIF files (100MB+):
import ijson # run via: uv run --with ijson
def stream_results(sarif_path: str):
"""Stream results without loading entire file."""
with open(sarif_path, "rb") as f:
# Stream through results arrays
for result in ijson.items(f, "runs.item.results.item"):
yield resultValidate before processing to catch malformed files:
# Using ajv-cli
npm install -g ajv-cli
ajv validate -s sarif-schema-2.1.0.json -d results.sarif
# Using Python jsonschema
uv run --with jsonschema python your_script.py # e.g. the function belowfrom jsonschema import validate, ValidationError
import json
def validate_sarif(sarif_path: str, schema_path: str) -> bool:
"""Validate SARIF file against schema."""
with open(sarif_path) as f:
sarif = json.load(f)
with open(schema_path) as f:
schema = json.load(f)
try:
validate(sarif, schema)
return True
except ValidationError as e:
print(f"Validation error: {e.message}")
return False- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
- name: Check for high severity
run: |
# select(.level == "error") counts zero on CodeQL output, which records severity on
# the rule instead. Resolve the level or the gate passes on a repo full of errors.
HIGH_COUNT=$(jq '
def rule($run):
. as $r
| ($run.tool.driver.rules // []) as $rules
| (if ($r.ruleIndex | type) == "number" and $r.ruleIndex >= 0
then $rules[$r.ruleIndex] else null end)
// first($rules[] | select(.id == $r.ruleId))
// null;
def level($run):
. as $r
| if ($r.kind // "fail") != "fail" then "none"
else ($r.level // rule($run).defaultConfiguration.level // "warning") end;
[.runs[] as $run | $run.results[] | select(level($run) == "error")] | length
' results.sarif)
if [ "$HIGH_COUNT" -gt 0 ]; then
echo "Found $HIGH_COUNT high severity issues"
exit 1
fifrom sarif import loader
def check_for_regressions(baseline: str, current: str) -> int:
"""Return count of new issues not in baseline."""
baseline_data = loader.load_sarif_file(baseline)
current_data = loader.load_sarif_file(current)
baseline_fps = {get_fingerprint(r) for r in baseline_data.get_results()}
new_issues = [r for r in current_data.get_results()
if get_fingerprint(r) not in baseline_fps]
return len(new_issues)result.level: it is optional, and CodeQL always omits itFor ready-to-use query templates, see {baseDir}/resources/jq-queries.md:
LEVEL_FN - the severity resolution every filtering query starts fromFor Python utilities, see {baseDir}/resources/sarif_helpers.py:
resolve_level() - Severity from the result or the rule it inherits fromnormalize_path() - Handle tool-specific path formatscompute_fingerprint() - Rule, normalized path, line, and messagededuplicate() - Remove duplicates across runsTwo SARIF fixtures live in {baseDir}/resources/fixtures, one with severity on the rules only and one with severity on the results. Each contains exactly one error, so a gate can be checked against a known answer before it is trusted.
© trailofbits, CC-BY-SA-4.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 7 other files (assets) in plugins/static-analysis/skills/sarif-parsing of trailofbits/skills.
Open the folder on GitHubat commit 82fe822
We found 3 copies of this SKILL.md (exact, near-identical or edited) in other folders, from 3 other GitHub owners. This page covers the copy in trailofbits/skills, which our catalogue first saw on October 7, 2026.
Sarif Parsing next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Sarif Parsing this skilltrailofbits/skills | 7.4k | 3 repos | ~4.4k | Automated safety check: Notes | CC-BY-SA-4.0 | |
| Kedro Security Reviewkedro-org/kedro | 11k | — | ~3.3k | Automated safety check: Pass | Custom licence | |
| Detection Breadthdeonmenezes/mantishack | 504 | — | ~510 | Automated safety check: Pass | Apache-2.0 | |
| Sast Scanningsickn33/agentic-awesome-skills | 47k | 1 repos | ~2.4k | Automated safety check: Pass | MIT | |
| Sast ScanningBagelHole/DevOps-Security-Agent-Skills | 1.1k | — | ~2.2k | Automated safety check: Pass | MIT | |
| Clawsec ScannerLeoYeAI/openclaw-master-skills | 2.2k | — | ~4.1k | Automated safety check: Pass | MIT |
kedro-org/kedro
Run a Kedro security scan on the full codebase or just a pull request.
deonmenezes/mantishack
When and how to reach for the companion detectors -- bandit (Python SAST) and trivy (deps + secrets + IaC misconfig) -- alongside the core semgrep/CodeQL/osv/trufflehog toolchain
sickn33/agentic-awesome-skills
Perform static application security testing with tools like Semgrep, CodeQL, and SonarQube.
BagelHole/DevOps-Security-Agent-Skills
Perform static application security testing with tools like Semgrep, CodeQL, and SonarQube.
LeoYeAI/openclaw-master-skills
Automated vulnerability scanner for agent platforms. An agent skill from LeoYeAI/openclaw-master-skills.
seb1n/awesome-ai-agent-skills
Analyze source code for security vulnerabilities using static analysis tools, custom rules, and CI-integrated scanning pipelines.
trailofbits/skills
Scans a codebase for vulnerabilities with CodeQL's data flow and taint tracking in run-all or important-only modes, including data extensions for project-specific sources and sinks.
trailofbits/skills
Generates Mermaid diagrams from Trailmark code graphs, including call graphs, class hierarchies, module dependency maps, complexity heatmaps and attack surface data flows.
trailofbits/skills
Compares Trailmark code graphs at two snapshots, such as commits, tags or directories, to surface attack paths, blast radius and taint changes that text diffs miss.
trailofbits/skills
Draws a 12 Houses tarot spread to break ties when a request is vague or casually delegated, then reads the cards to pick the next step.
trailofbits/skills
Detects languages, proposes rulesets for approval, then runs the approved Semgrep scan across a codebase and merges the output into one SARIF file.
trailofbits/skills
Searches and extracts data from Burp Suite project files on the command line: regex searches over responses, audit findings, proxy history and site map data.
Categories
Parses and processes SARIF files from static analysis tools like CodeQL, Semgrep, or other scanners. Sarif Parsing is an agent skill from trailofbits/skills, published by the product's own GitHub organization. Parses and processes SARIF files from static analysis tools like CodeQL, Semgrep, or other scanners.
Sarif Parsing fits situations like: read scan results; aggregate findings; deduplicate alerts; process sarif output.
Run `npx skills add trailofbits/skills --skill sarif-parsing -a claude-code`. Or copy the skill folder (plugins/static-analysis/skills/sarif-parsing in trailofbits/skills) into .claude/skills/sarif-parsing in your project. Claude Code loads it when a task matches its description.
Run `npx skills add trailofbits/skills --skill sarif-parsing -a codex`. Or copy the skill folder (plugins/static-analysis/skills/sarif-parsing in trailofbits/skills) into .agents/skills/sarif-parsing in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add trailofbits/skills --skill sarif-parsing -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/sarif-parsing, .gemini/skills/sarif-parsing, .github/skills/sarif-parsing and .opencode/skills/sarif-parsing in your project.
Going by SKILL.md and its folder, Sarif Parsing needs Python for the scripts in its folder and the command-line tools its instructions call (jq, uv, npm, brew, apt and go). Our summary lists: Python 3; Node.js. Its frontmatter pre-approves these tools: Bash, Read, Glob, Grep.
SKILL.md names 5 domains. In commands or code: json.schemastore.org; the agent is likely to contact it when it follows the instructions. As links in the text: github.com, docs.oasis-open.org, docs.github.com and sarifweb.azurewebsites.net. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
Sarif Parsing is published under the CC-BY-SA-4.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.4k tokens (SKILL.md is roughly 18k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Sarif Parsing: Kedro Security Review (kedro-org/kedro, 11k stars), Detection Breadth (deonmenezes/mantishack, 504 stars), Sast Scanning (sickn33/agentic-awesome-skills, 47k stars) and Sast Scanning (BagelHole/DevOps-Security-Agent-Skills, 1.1k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
trailofbits (a GitHub organization, an official publisher) maintains it in trailofbits/skills, which has 7,440 GitHub stars. The repository holds 79 skills in this directory. The repository was last updated on October 7, 2026.
Source: trailofbits/skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.