SAST: Static Application Security Testing
In plain terms#
Static Application Security Testing (SAST) reads the source code you write and looks for insecure patterns, without running the program. It's the security equivalent of a proofreader who knows the ways code tends to go wrong: building a SQL query by gluing strings together, using a broken hash function, shelling out with unsanitized input.
Where SCA checks the code you reuse, SAST checks the code you author.
Why it matters#
Whole categories of serious bugs are recognizable by shape: SQL injection, command injection, cross-site scripting, path traversal, hardcoded credentials, weak cryptography. Catching them while the code is still in a pull request is dramatically cheaper than after it ships. SAST is a core part of "shift-left" security (more here).
Where it fits#
- Artifact: your source code.
- Stage: in the editor and on every pull request. SAST needs no deployment, so it's a natural continuous-integration (CI) gate on the diff.
How it works#
Early SAST tools were simple pattern matchers (glorified grep). Modern ones parse code into an abstract syntax tree and reason about it, and the best perform taint analysis: tracking whether untrusted input (a request parameter) can flow into a dangerous sink (a database query) without being sanitized. That data-flow awareness is what separates a useful finding from noise.
Popular & reputable tools#
| Tool | Notes |
|---|---|
| Semgrep | OSS, polyglot, fast; rules are readable patterns anyone can write |
| gosec | OSS, Go-specialized; type-aware, deep on Go idioms |
| Bandit | OSS, Python-specific |
| CodeQL | Powerful semantic analysis; free for open source, via GitHub |
| SonarQube, Checkmarx, Snyk Code | Commercial platforms with broad language + policy coverage |
Common pitfalls#
- False positives. SAST's biggest tax. A pattern that looks injectable may be safe in context; too much noise trains people to ignore it. Tuning rules to your codebase matters.
- Language depth varies. A generic polyglot ruleset is shallower than a language-specialized analyzer (e.g. gosec for Go). Best coverage often means the right tool per language.
- It can't see runtime. Logic flaws and configuration issues that only appear when the app runs are DAST territory, not SAST.
sast control runs Semgrep over each component's source and normalizes findings to SARIF. Semgrep is the default because it needs no build step and covers many languages; a Go-specialized scanner (gosec) is planned as an opt-in for deeper Go analysis. See quickstart in the docs.
Keep learning#
- SCA, the same idea for third-party dependencies
- DAST, finding what only appears at runtime
- Shift-left & DevSecOps, why PR-time checks pay off