L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Données et recherche · SKILL.md

sast-tooling

sast-tooling

Use when running Static Application Security Testing (SAST) on a codebase — wraps bandit (Python), semgrep (multi-language, OSS rule packs), eslint-security (JavaScript/TypeScript), and CodeQL (GitHub-hosted, license-gated for private repos). Standardises on SARIF 2.1.0 output, feeds the G_SECURE gate in _meta/gates.py, integrates with forge Step 1 advisory…

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentation de la Skill

GitHub

name: sast-tooling description: Use when running Static Application Security Testing (SAST) on a codebase — wraps bandit (Python), semgrep (multi-language, OSS rule packs), eslint-security (JavaScript/TypeScript), and CodeQL (GitHub-hosted, license-gated for private repos). Standardises on SARIF 2.1.0 output, feeds the G_SECURE gate in _meta/gates.py, integrates with forge Step 1 advisory, alf sweeps, and pre-commit/CI workflows. Trigger on - SAST, static analysis, bandit, semgrep, CodeQL, eslint-security, SARIF, security linting, code-injection scan, "scan code for vulnerabilities", "find security bugs", "OWASP scan".

SAST Tooling

Overview

Static Application Security Testing (SAST) — find security defects in source code without running it. SAST catches the LOW-MEDIUM hygiene defects (verify=False, eval(user_input), hardcoded password= strings, unsafe deserialisation, weak cryptography) that secret-scanning and dep-currency-check don't cover. Per the S038 alf sweep verdict, this skill closes the "no SAST runner" gap (finding F-H2).

The runner choices in 2026, with Gemini freshness-probe corroboration (2026-05-22):

ToolLanguagesMaintenanceSpeedFalse positivesUse case
banditPython onlyActive (v1.9.4 Feb 2026, py3.10+ required)FastLow-mediumPython-specific; CI gate; pre-commit
semgrepMulti-language (Python/JS/TS/Java/Go/Ruby/PHP/C/+more)Active (v1.x, no breaking v2.0 — Agentic IDE hooks added 2025-26)FastMedium (configurable per ruleset)The de-facto multi-language SAST; default choice for polyglot repos
eslint-securityJavaScript / TypeScriptActive (eslint-plugin-security)FastMediumJS/TS-specific; runs as ESLint plugin; CI gate
CodeQLMany (C/C++/C#/Go/Java/JS/Python/Ruby/Swift)Active (GitHub)Slower (compile-then-analyze)Low (deep dataflow)Best for high-stakes / open-source; license-gated for private repos since Apr 2025

Companion skills:

  • python-auth-security — what the findings SHOULD look like (no eval, parameterised SQL, etc.)
  • secret-scanning — sister skill for secrets (gitleaks/trufflehog)
  • dep-currency-check — sister skill for dependency CVEs (orthogonal to source-level SAST)
  • llm-security — sister skill for LLM-specific defects
  • _meta/gates.py (G_SECURE) — the gate this skill feeds

1. Tool selection — when to use which

ScenarioTool
Pure-Python projectbandit (cheap, Python-specific) + optional semgrep --config p/python for broader coverage
JS/TS projecteslint-security in eslint config + optional semgrep --config p/javascript
Polyglot repo (Python + JS + Go + ...)semgrep with bundled or custom rulesets — single runner, single SARIF output
Public repo on GitHubCodeQL via Actions (free for public repos) + semgrep for fast iteration
Private repo on GitHub with GHAS Code SecurityCodeQL + semgrep
Private repo without GHAS budgetsemgrep + tool-specific (bandit / eslint-security) — CodeQL is $30/committer/month standalone since Apr 2025
Air-gapped / offline environmentbandit + semgrep (both offline-capable with bundled rulesets)
Quick-iteration developer-loop scansemgrep autofix (--autofix) for the small set of safe-auto-fix rules
Highest-confidence deep dataflow analysisCodeQL

The default 2026 setup for a polyglot CI gate: semgrep + bandit (Python) + eslint-security (JS/TS), each emitting SARIF, aggregated by G_SECURE. CodeQL adds the dataflow tier when budget / license permits.


2. Install Commands

RHEL 9 / AlmaLinux 9 / Rocky 9

# bandit
pip install --user bandit
bandit --version  # expects 1.9.x

# semgrep
pip install --user semgrep
semgrep --version  # expects 1.16x.x

# eslint-security (Node.js project)
npm install --save-dev eslint eslint-plugin-security

# CodeQL CLI (standalone — for use outside GHAS)
# Download from: https://github.com/github/codeql-cli-binaries/releases
# Place under ~/.local/bin/codeql

Debian 12 / Ubuntu 24.04

# Same pip / npm commands as RHEL
pip install --user bandit semgrep
# eslint-security per project

Windows 11

# Via pip (Python tools)
py -m pip install --user bandit semgrep
# Or scoop/chocolatey:
scoop install semgrep

Verify via env-adoption (S038 Batch A added these to the inventory):

jq '.tools | {bandit, semgrep, "pip-audit", "osv-scanner"}' ~/.claude/state/inventory.json

3. SARIF as the canonical output

SARIF 2.1.0 is the multi-tool standard. Every wrapper this skill describes emits SARIF, and G_SECURE consumes SARIF. This means findings from bandit / semgrep / eslint-security / CodeQL aggregate uniformly into one report, ingestable by GitHub Advanced Security, VS Code, JetBrains, Sonarqube, and most enterprise dashboards.

# bandit → SARIF
bandit -r src/ -f sarif -o /tmp/bandit.sarif

# semgrep → SARIF
semgrep --config auto --sarif --output /tmp/semgrep.sarif

# eslint-security → SARIF
npx eslint --format @microsoft/eslint-formatter-sarif --output-file /tmp/eslint.sarif src/

# CodeQL → SARIF (via Action; CLI: codeql database analyze --format=sarif-latest)

G_SECURE aggregates by reading SARIF and applying the configured severity threshold.


4. Canonical CI integration

4.1 GitHub Actions (.github/workflows/sast.yml)

name: sast
on: [pull_request, push]
jobs:
  semgrep:
    runs-on: ubuntu-latest
    permissions: { security-events: write }
    steps:
      - uses: actions/checkout@v4
      - uses: returntocorp/semgrep-action@v1
        with:
          config: >-
            p/python p/javascript p/typescript p/security-audit p/secrets
            p/r2c-security-audit p/owasp-top-ten
          generateSarif: true
      - uses: github/codeql-action/upload-sarif@v3
        with: { sarif_file: semgrep.sarif }

  bandit:
    runs-on: ubuntu-latest
    if: contains(github.event.repository.topics, 'python') # gate on python repos
    permissions: { security-events: write }
    steps:
      - uses: actions/checkout@v4
      - run: pip install bandit
      - run: bandit -r . -ll -f sarif -o bandit.sarif || true
      - uses: github/codeql-action/upload-sarif@v3
        with: { sarif_file: bandit.sarif }

  codeql:
    # Optional — CodeQL for deeper dataflow
    runs-on: ubuntu-latest
    permissions: { security-events: write }
    strategy:
      matrix: { language: [python, javascript] }
    steps:
      - uses: actions/checkout@v4
      - uses: github/codeql-action/init@v3
        with: { languages: ${{ matrix.language }} }
      - uses: github/codeql-action/analyze@v3

4.2 Pre-commit hook (POSIX)

# .git/hooks/pre-commit (extract)
if command -v semgrep >/dev/null 2>&1; then
  semgrep --config auto --error --quiet --skip-unknown-extensions $(git diff --cached --name-only) \
    || { echo "[semgrep] BLOCKING — review findings"; exit 1; }
fi

4.3 The G_SECURE gate (S038 Batch E)

python3 ~/.claude/skills/_meta/gates.py G_SECURE /path/to/project \
  --sast-mode advisory                # never blocks; reports
python3 ~/.claude/skills/_meta/gates.py G_SECURE /path/to/project \
  --sast-mode strict \
  --severity high                     # blocks on high+critical
python3 ~/.claude/skills/_meta/gates.py G_SECURE /path/to/project \
  --sast-mode strict \
  --severity critical \
  --runner semgrep                    # explicit runner choice

Exit codes mirror the family:

  • 0 = pass (no findings at/above severity, OR advisory mode)
  • 2 = fail (strict mode AND findings at/above severity)
  • 3 = environmental error (no SAST runner available)

5. Per-runner notes

5.1 bandit (Python)

  • Confidence levels: HIGH / MEDIUM / LOW. Default rules-loaded at all levels. -ll = medium-or-higher severity + medium-or-higher confidence. Recommended CI baseline.
  • -ll filter is the most-cited 2026 baseline by the OpenSSF Python WG (the LOW-confidence rules produce too many FPs).
  • Common-rule cheat-sheet:
    • B101 — assert outside tests (False in production)
    • B105/106/107 — hardcoded password strings/funcargs/defaults
    • B301 — pickle deserialisation (HIGH severity)
    • B324 — weak hash (md5/sha1)
    • B501 — verify=False in requests
    • B602/603/605/607 — subprocess shell-injection variants
    • B608 — SQL string concat
    • B701 — Jinja2 autoescape disabled
  • Inline suppress: # nosec: <rule-id> — justification
  • Project config: bandit.yaml or pyproject.toml [tool.bandit]

5.2 semgrep (multi-language)

  • Free-tier rulesets: p/security-audit, p/owasp-top-ten, p/secrets, language-specific p/python / p/javascript / etc. The 2026 build has Agentic IDE hooks (Claude Code / Windsurf integration).
  • Autofix: semgrep --autofix for the small subset of rules marked fix: in the YAML. Safe-by-default — only applies fixes that don't change semantics.
  • Custom rules: YAML under .semgrep/. Pattern-based matching with metavariables; far more flexible than bandit.
  • Inline suppress: // nosemgrep: <rule-id> (or language-comment variant)
  • Project config: .semgrep.yml or --config <path>

5.3 eslint-security (JS/TS)

  • eslint-plugin-security provides a focused security-only ruleset; add to your eslint config:
    {"extends": ["plugin:security/recommended"], "plugins": ["security"]}
    
  • Coverage is narrower than semgrep for JS — they're complementary, not redundant.
  • Key rules: detect-eval-with-expression, detect-non-literal-fs-filename, detect-non-literal-regexp, detect-unsafe-regex, detect-object-injection.

5.4 CodeQL

  • GHAS Code Security add-on standalone: $30/committer/month (since Apr 2025 — Gemini freshness probe).
  • Open-source / public repos: free via GitHub Actions.
  • Strengths: deep dataflow analysis catches taint flows that pattern-matchers miss.
  • Slow (compile-then-analyse) — use for nightly / pre-release scans, not every PR.
  • Output: SARIF, ingestable by GHAS or third parties.

6. Security Hardening (the rules for THIS skill's usage)

  1. Layer SAST + secrets + deps + LLM-security — each tool catches different things; none is sufficient alone.
  2. Run advisory first, baseline existing findings, then go strict.
  3. Document every suppression — # nosec: B608 — reason not bare # nosec.
  4. CI gates use SARIF — feed into GitHub Advanced Security / Sonarqube / enterprise dashboards.
  5. CI runs at least one SAST runner (semgrep is the cheapest baseline).
  6. Pin SAST runner versions — semgrep's rule packs change, bandit's rule list updates; record the version in CI logs (bandit --version / semgrep --version).
  7. Keep SAST runner versions current via dep-currency-check — semgrep ships new rule packs continuously.
  8. Don't --autofix blindly in CI — review the diff. Auto-fixed code can change semantics for edge cases the fix-rule didn't anticipate.
  9. Custom rules are project-specific — file under .semgrep/ in the repo, code-review additions.
  10. alf sweep includes SAST runner currency — sees bandit/semgrep/gitleaks versions in the inventory and flags if the project's pinned version drifts.

7. Anti-patterns

Anti-patternWhy it failsCorrect approach
Run bandit with default confidence (LOW) in CI gate from day oneFP storm; team learns to --no-verifyUse bandit -ll; tune over time
One tool onlyEach catches different thingsLayer at least 2 of {semgrep, bandit, eslint-security}
# nosec without justificationPermanent exception with no traceable reasonRequired format: # nosec: <id> — reason
Auto-fix in CI without reviewRule-based fixes can break edge-case semantics--autofix only locally, then code-review the diff
Skip SAST because dep-currency-check + secret-scanning are runningSister skills cover different threats; SAST adds source-level findingsRun all three (G_SECRETS_SCAN + G_DEP_CURRENCY + G_SECURE)
Treat SAST FPs as bugs in the SAST toolTriaging FPs is the work; modern SAST is by-design over-reportingTriage, suppress with reason, OR tune the ruleset
Run CodeQL on every PRSlow; eats GHAS minutes; better for nightlysemgrep / bandit on PR, CodeQL nightly
Custom rules in a single project's .semgrep/ without sharing backReinvents the wheel across projectsMaintain shared org-level rule packs

8. Selection Cheatsheet

  • Polyglot CI gate, fast → semgrep --config auto with --severity ERROR --error
  • Python project + needs deep dataflow → bandit + CodeQL (Python)
  • JS/TS in mixed repo → semgrep p/javascript + eslint-security inside ESLint
  • Just want quick "is this code obviously bad" check locally → semgrep --config p/security-audit --autofix (local only)
  • Need SARIF aggregated to GitHub Advanced Security → upload via github/codeql-action/upload-sarif@v3
  • Need G_SECURE for bob WP-completion gate → python3 ~/.claude/skills/_meta/gates.py G_SECURE --sast-mode strict
  • Need an advisory pass for forge Step 1 → --sast-mode advisory

9. Gotchas

GotchaDetail
semgrep --config auto requires metrics: on (default) to authenticateFor air-gapped, use --config p/<ruleset> with explicit packs
bandit can't analyse code that doesn't parseIf your code uses syntax newer than the bandit-supporting Python (1.9.4 → py 3.14), bandit will fail; pin a compatible Python
eslint-plugin-security needs eslint flat-config in modern repos.eslintrc.json legacy format still works, but new repos default to eslint.config.js
CodeQL pricing changed Apr 2025Public repos free; private repos require GHAS Code Security add-on at $30/committer/month
SARIF schema versions can clashAll four runners standardise on 2.1.0 as of 2026; older outputs may need conversion
semgrep autofix on == → === (JS) is safe-mostly but rarely "what the developer wanted"Review every autofix
Custom rule false-positives in semgrep need careful pattern designUse pattern-not and metavariable-regex to scope tightly
bandit B105 flags password = "changeme" even in test fixturesSuppress with # nosec: B105 — test fixture, not a real credential

10. Update triggers (alf scans these)

  • bandit major version bump (currently 1.9.x as of 2026-05)
  • semgrep major version bump (still on 1.x, but 2.0 would be material)
  • semgrep rule pack additions for new attack patterns
  • ESLint flat-config completion (deprecation of .eslintrc.* formats)
  • New OWASP Top 10 edition (rules need re-mapping)
  • CodeQL pricing / availability change
  • New SARIF version (currently 2.1.0)
  • Annual review on 2027-05-24

11. See Also

NeedSkill
Dependency CVE check (orthogonal to SAST)dep-currency-check
Secrets in code (orthogonal to SAST)secret-scanning
LLM-specific defects (prompt injection, etc.)llm-security
Python web-app auth patternspython-auth-security
The G_SECURE gate this feeds~/.claude/skills/_meta/gates.py
Pre-commit hook patterns (POSIX + Windows hardened PS1)dep-currency-check (precedent)
Bootstrap hook offerinstaller/bootstrap-environment.py
Skills enregistrées