semgrep scan: Run SAST Rules Locally and in CI
semgrep scan runs rules against your code and exits 1 when findings are reported, 0 when clean, and 2 on a fatal error.
semgrep scan is the workhorse command. Point it at a rule pack with --config and it lints every supported language without compiling the project.
What it does
semgrep scan loads rules (a registry pack, a local YAML, or "auto"), matches them against the code, and prints findings. Exit 0 means no findings, 1 means findings were reported (with --error), and 2 means a fatal/parse error. Without --error, findings alone do not change the exit code in some modes, so set it explicitly.
Common usage
semgrep scan --config p/ci --error
# multiple packs
semgrep scan --config p/security-audit --config p/secrets --error
# only high-severity findings
semgrep scan --config auto --severity ERROR --errorOptions
| Flag | What it does |
|---|---|
| --config <src> | Rule source: p/ci, p/security-audit, auto, or a file/dir |
| --error | Exit non-zero (1) when findings are present |
| --severity <level> | Filter to INFO, WARNING, or ERROR findings |
| --json / --sarif | Machine-readable output |
| --exclude <glob> | Skip matching paths |
| --metrics off | Disable anonymous metrics upload |
| --max-target-bytes <n> | Skip files larger than n bytes |
In CI
Add --error so findings fail the job; without it the exit code can stay 0 and the gate does nothing. Use --metrics off on a locked-down runner with no egress, and a specific pack like p/ci rather than auto for reproducible results (auto picks rules based on the project, which can drift).
Common errors in CI
"Scan failed to start: invalid configuration" means a bad --config path or pack name. Exit 2 with "Syntax error" is a parse failure on a source file, not a security finding; exclude generated files. "METRICS: ... connection error" on an air-gapped runner is fixed with --metrics off. A green build despite findings usually means --error was omitted.