Testland
Browse all skills & agents

semgrep-rules

Configures and runs Semgrep - pattern-based SAST across 30+ languages with the Semgrep Registry rulesets (`p/owasp-top-ten`, `p/default`, `auto`) plus custom YAML rules; integrates `semgrep ci` for PR-blocking gates with `--baseline-commit` diff-aware scanning, per-finding inline `nosemgrep` suppressions, `--exclude` / `--include` path filters, output formats (`--json` / `--sarif` / `--gitlab-sast` / `--junit-xml`), and severity filter (INFO/WARNING/ERROR). Use when the user runs Semgrep, asks about pattern rules, or needs a low-friction SAST gate without semantic-DB setup.

Install with skills.sh (any agent)

npx skills add testland/qa --skill semgrep-rules
View source

semgrep-rules

Overview

Per semgrep.dev/docs/getting-started/quickstart (opens in new window):

Semgrep is a fast pattern-based static analyzer covering 30+ languages with a registry of community + paid rulesets and straightforward YAML rule authoring. The semgrep ci subcommand adds CI-aware features (baseline-diff, organization policies, metrics).

Per semgrep.dev/docs/cli-reference (opens in new window):

"semgrep scan: Local scans without account requirement; doesn't return failing codes by default.

semgrep ci: Pipeline execution with organization policies, diff-aware scanning, returns failing codes on findings."

When to use

  • The repo has a .semgrep.yml / .semgrep/ directory or wants zero-config registry rulesets.
  • The user needs PR-time SAST without standing up SonarQube or CodeQL infrastructure.
  • A team prefers pattern-DSL rule authoring over semantic-database query languages.

Step 1 - Install

Per sg-quick (opens in new window):

# macOS
brew install semgrep

# Linux/macOS
pipx install semgrep
# or
uv tool install semgrep

# Windows (PowerShell)
pipx install semgrep

# Docker (CI-friendly)
docker pull semgrep/semgrep

Step 2 - First scan

semgrep scan --config auto

Per sg-cli (opens in new window), --config auto "Auto-fetch rules from registry based on project." Specific rulesets:

semgrep scan --config p/owasp-top-ten     # OWASP Top 10
semgrep scan --config p/default            # broad community ruleset
semgrep scan --config p/python p/javascript   # multiple

Step 3 - Custom rule authoring

A minimal Semgrep rule in .semgrep.yml:

rules:
  - id: hardcoded-jwt-secret
    pattern: jwt.sign($PAYLOAD, "...")
    message: Hardcoded JWT secret detected
    languages: [javascript, typescript]
    severity: ERROR
    metadata:
      cwe: "CWE-798: Use of Hard-coded Credentials"

Pattern operators: pattern, pattern-either, pattern-not, metavariable-pattern, pattern-inside. Validate rule syntax:

semgrep validate --config .semgrep.yml

(Per sg-cli (opens in new window) subcommand list.)

Step 4 - CI integration with baseline diff

Per sg-cli (opens in new window): "--baseline-commit=VAL - Show only findings not in specified commit". Diff-aware mode fails only NEW findings on the PR; pre-existing findings are tracked but don't block - critical for legacy adoption.

jobs:
  semgrep:
    runs-on: ubuntu-latest
    container:
      image: semgrep/semgrep
    steps:
      - uses: actions/checkout@v5
      - run: semgrep ci --baseline-ref=main --sarif --output=semgrep.sarif
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with: { sarif_file: semgrep.sarif }

Step 5 - False-positive triage (MANDATORY)

Suppression mechanisms in priority order:

MechanismExampleWhen to use
Per-line nosemgrep comment# nosemgrep: hardcoded-passwordJustified single-line exception
nosemgrep block# nosemgrep: rule-id above a code blockMulti-line exception
paths.exclude in configexclude: ["**/*_pb.go"]Generated files / vendored code
Baseline ref--baseline-commit=main (Step 4)Legacy debt; ratchet
Organization-level rule disableSemgrep AppSec Platform UITeam-wide policy

Justification template (mandatory in code):

# nosemgrep: hardcoded-password
# Reason: Test fixture; password never reaches production runtime
# Reviewer: alice@example.com (2026-05-15)
# Expires: 2026-12-15
TEST_PASSWORD = "test-only-password-do-not-deploy"

Per sg-cli (opens in new window) severity filter for triage workflow:

semgrep scan --severity ERROR --json   # only critical findings

Cadence: every quarter, audit nosemgrep suppressions for staleness. Expired ones removed; persistent ones reviewed for escalation.

Step 6 - CLI reference (formats, flags, exit codes)

Gate on exit 0 = clean, 1 = findings, 2 = fatal error. The full output-format flags, performance-tuning flags, and complete exit-code table are in references/cli-reference.md.

Anti-patterns

Anti-patternWhy it failsFix
--config=auto everywhereRulesets drift; no ownershipPin specific rulesets (Step 2)
nosemgrep without justificationBecomes invisible debtRequired justification template (Step 5)
No baseline refEvery legacy finding blocks; team disables--baseline-commit=main (Step 4)
semgrep scan in CIDoesn't return failing exit code by defaultUse semgrep ci (Step 1 quote)
Mix --severity ERROR with --baseline-commit poorlyCan mask real new findingsSeverity filter at output stage, not scan stage

Limitations

  • Pattern matching can miss cross-file taint flows; for those, pair with codeql-queries.
  • Registry rulesets evolve; pin specific versions for production.
  • Semgrep AppSec Platform features (org policies, supply-chain scanning) are paid; the OSS engine covers the patterns above.

References

  • sg-quick (opens in new window) - install, quickstart
  • sg-cli (opens in new window) - full CLI reference, exit codes, all flags
  • semgrep.dev/docs/writing-rules/rule-syntax - custom rules
  • semgrep.dev/docs/semgrep-ci/overview - CI integration
  • sonarqube-rules, codeql-queries, bandit-python, gosec-go - sister scanners

Semgrep CLI reference

Full flag, output-format, and exit-code detail for semgrep-rules. The SKILL.md spine keeps the common commands; this file holds the exhaustive tables. All entries per semgrep.dev/docs/cli-reference (opens in new window).

Output formats

FlagPurpose
--jsonSemgrep JSON format (for multi-scanner triage)
--sarifSARIF format (GitHub Code Scanning upload)
--gitlab-sastGitLab SAST format (GitLab Security Dashboard)
--junit-xmlJUnit XML (test reporters)
--textDefault human-readable
--output VALWrite to file or URL

Performance flags

semgrep scan -j 8 --timeout 10 --max-target-bytes 5000000
  • -j VALUE - Parallelism degree (default: 3)
  • --timeout=DOUBLE - Per-rule per-file timeout in seconds (default: 5.0)
  • --max-target-bytes=VALUE - Skip files exceeding size (default: 1000000)

Exit codes

CodeMeaning
0Success, no issues
1Issues detected (with --error flag)
2Fatal error
3Invalid syntax in scanned language
4Invalid pattern in rule
5Invalid YAML configuration
7Invalid rule in configuration
8Unsupported language specified
13Invalid API key

The spine gates on 0 (pass) / 1 (findings) / 2 (fatal); the rest signal config or rule authoring errors.

Related skills

bandit-python

Configures and runs Bandit - Python-only SAST covering 60+ rule IDs across 7 categories (B1xx-B7xx: misc, app, crypto, imports, injections, XSS); `bandit -r .` scan, `--severity-level` + `--confidence-level` filtering, `# nosec`/`# nosec B404` per-line and per-rule suppression, `pyproject.toml [tool.bandit]` config. Use for a focused, low-overhead Python SAST in pre-commit / CI. Python-only: for Go use gosec-go, for cross-language pattern SAST use semgrep-rules; to merge Bandit findings with other scanners into one gate use multi-tool-finding-triage - not this for non-Python code.

codeql-queries

Configures and runs GitHub CodeQL - semantic-database SAST with queries written in the CodeQL declarative query language; supports `codeql database create` (per-language) + `codeql database analyze` with --format=sarif; ships query packs (`codeql/javascript-queries`, `codeql/python-queries`, `codeql/java-queries`, `codeql/go-queries`, etc.); integrates with GitHub Code Scanning via SARIF upload; suppression via inline comment + sarif-filter + Security-tab dismissal. Use when the team uses GitHub-hosted repos and needs deep semantic SAST beyond pattern matching (cross-file taint flows, dataflow analysis).

eslint-security-rules

Configures and runs `eslint-plugin-security` (14 detect-* rules covering injection, path traversal, ReDoS, unsafe buffers, and bidi trojan-source) plus `eslint-plugin-no-unsanitized` (DOM XSS via `innerHTML`, `outerHTML`, `document.write`, `insertAdjacentHTML`) as the JS/TS first-party SAST layer; covers flat config setup, per-rule suppression with justification templates, SARIF output via `@microsoft/eslint-formatter-sarif` for GitHub Code Scanning upload, and CI gating on ESLint exit code 1. Use when the project is JS or TS and needs an in-process security lint pass without a separate SAST server.

gosec-go

Configures and runs gosec - Go-only SAST covering 40+ rule IDs (G101 hardcoded creds, G104 unhandled errors, G304 path traversal, G401 weak crypto, G601 memory aliasing) via Go AST + SSA taint tracking; `gosec ./...` scan, `#nosec G404 -- justification` suppression, `--fmt sarif|json|junit-xml|html`, golangci-lint integration. Use for a focused Go SAST wired into golangci-lint / CI. Go-only: for Python use bandit-python, for cross-language pattern SAST use semgrep-rules; to merge gosec findings with other scanners into one gate use multi-tool-finding-triage - not this for non-Go code.

multi-tool-finding-triage

Merges two or more security scanner reports into one gate. Use when you need a single BLOCK or PASS decision from multiple scanners instead of reading N separate reports. Normalizes each report into one common finding format (a canonical `Finding`), deduplicates on a per-domain key while recording which scanners agree (`caught_by` consensus), validates a waiver (finding-suppression) file, rejecting any missing `expires:` / `approved_by:` / `reason:` or expired, enriches CVE findings with EPSS (exploit-probability) and CISA KEV (known-exploited catalog), then applies a `fail_on` severity threshold to emit BLOCK or PASS plus a bucketed pull-request comment. Works across static (SAST), dynamic (DAST), secret, dependency (SCA), container, and IaC scanners. To run a single scanner instead use semgrep-rules, codeql-queries, bandit-python, or gosec-go; this runs after them to merge output - the cross-scanner gate, not a single-scanner wrapper.

pmd-apex-rules

Runs PMD's built-in Apex security ruleset (`category/apex/security.xml`) against Salesforce Apex source to detect injection, privilege-escalation, cryptographic, and XSS vulnerabilities; configures custom rulesets for regulated-industry Apex codebases; emits SARIF for GitHub Code Scanning upload; integrates `pmd check` as a PR-blocking CI gate. Use when the codebase contains Salesforce Apex and the team needs SAST coverage for ApexSOQLInjection, ApexCRUDViolation, ApexSharingViolations, or the full 10-rule security category.

sonarqube-rules

Configures and runs SonarQube / SonarCloud - multi-language SAST + Quality Gate platform with built-in Sonar Way rule profiles + custom rule plugins; integrates `sonar-scanner` with `sonar-project.properties` config; supports Quality Gate definitions including new-code-period blocking, branch + PR analysis, and per-issue suppression via `// NOSONAR` comment or `@SuppressWarnings("squid:RULE_ID")` annotation. Use when the user runs SonarQube Community / Developer / Enterprise edition or SonarCloud, or needs a multi-language SAST + code-quality platform with persistent issue tracking.