devsecops
SAST Tools: Static Application Security Testing
Intermediate
14 minutes
October 2026
CloudOpsGuide Team
SAST Tools: Static Application Security Testing
Compare and implement SAST tools — SonarQube, Semgrep, Snyk, and CodeQL — in your CI/CD pipeline.
Table of Contents
- What SAST Does
- Tool Comparison
- Quick Start Guides
- CI/CD Integration
- Triage and Baseline
- Best Practices
What SAST Does
SAST analyzes source code (or compiled binaries) without running it to find:
- SQL injection, XSS, command injection
- Hardcoded credentials and secrets
- Insecure crypto usage
- Buffer overflows (C/C++)
- Framework-specific misconfigurations
It runs fast and early — catch bugs before code review, not in production.
Tool Comparison
| Tool | Type | Languages | Best For | Free Tier |
|---|---|---|---|---|
| SonarQube | Server + scanner | 30+ | Teams wanting dashboards | Community edition |
| Semgrep | CLI rules engine | 30+ | Custom rules, fast CI | Open source |
| CodeQL | GitHub-native | 9 | GitHub repos, deep analysis | Free on public repos |
| Snyk | Cloud SaaS | Many | Dev-first UX, fix advice | Limited free scans |
| Checkmarx | Enterprise SaaS | 35+ | Compliance-heavy orgs | Trial only |
| Bandit | CLI | Python only | Python projects | Open source |
| Gitleaks | CLI secrets | Any text | Secrets detection | Open source |
Quick Start Guides
Semgrep (Fastest to Set Up)
# Install
pip install semgrep
# Scan with community rules
semgrep scan --config auto .
# Scan with specific ruleset
semgrep scan --config p/security-audit .
CI-friendly — one command, JSON output, exit code reflects findings.
SonarQube
# Start local SonarQube
docker run -d -p 9000:9000 sonarqube:community
# Scan with sonar-scanner
sonar-scanner \
-Dsonar.projectKey=my-app \
-Dsonar.sources=. \
-Dsonar.host.url=http://localhost:9000 \
-Dsonar.login=$SONAR_TOKEN
CodeQL (GitHub Native)
# .github/workflows/codeql.yml
name: "CodeQL"
on: [push, pull_request]
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: github/codeql-action/init@v3
with:
languages: javascript-typescript
- uses: github/codeql-action/analyze@v3
Bandit (Python)
pip install bandit
bandit -r . -f json -o bandit-report.json
CI/CD Integration
Jenkins Pipeline
stage('SAST Scan') {
steps {
sh '''
semgrep scan --config auto . \
--json -o semgrep-results.json || true
'''
archiveArtifacts 'semgrep-results.json'
}
}
GitHub Actions
- name: Run Semgrep
uses: semgrep/semgrep-action@v1
with:
config: p/security-audit
generateSarif: true
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: semgrep.sarif
Quality Gate
# Block merges on new critical findings
- name: Check findings
run: |
CRITICAL=$(jq '[.results[] | select(.extra.severity == "ERROR")] | length' report.json)
if [ "$CRITICAL" -gt 0 ]; then
echo "::error::$CRITICAL critical findings"
exit 1
fi
Triage and Baseline
First scan on a legacy codebase will show hundreds of findings. Don't panic:
Step 1: Baseline
# Accept current state, only flag new issues
semgrep scan --config auto --baseline-commit main .
Step 2: Suppress False Positives
# Inline suppression with justification
query = f"SELECT * FROM users WHERE id = {user_id}" # nosemgrep: user input validated upstream
Step 3: Custom Rules
# rules/no-eval.yml — block eval() in your codebase
rules:
- id: no-eval
pattern: eval(...)
message: "eval() is banned in this codebase"
severity: ERROR
languages: [python, javascript]
semgrep scan --config rules/ .
Best Practices
1. Scan Every PR, Not Just Main
on: [push, pull_request] # catch issues before merge
2. Combine SAST with Other Scans
| Layer | Tool Type |
|---|---|
| Code quality + vulns | SAST (Semgrep/SonarQube) |
| Secrets | Gitleaks, TruffleHog |
| Dependencies | Snyk, Dependabot, npm audit |
| Containers | Trivy |
| Runtime | DAST (OWASP ZAP) |
3. Tune Severity, Don't Disable
Disable noisy rules rather than whole scans:
# .semgrepignore
tests/
migrations/
*.min.js
4. Track Metrics Over Time
- Findings per KLOC trending down = healthy
- Mean time to remediate < 30 days
- Zero critical findings older than SLA
5. Developer-Friendly Output
# Human-readable summary, not just JSON
semgrep scan --config auto . --output report.txt
Common Pitfalls
- Scanning everything every commit — scope to changed files with
--baseline-commit - No baseline on legacy code — drowning in old findings kills adoption
- SAST alone — misses runtime issues; pair with DAST and dependency scanning
- Ignoring developer feedback — tune rules quarterly based on false-positive reports
Related Articles
Last Updated: October 2026
Author: CloudOpsGuide Team
Difficulty: Intermediate
Estimated Reading Time: 14 minutes