SAST: What is Static Code Analysis
SAST (Static Application Security Testing) is an analysis technique that examines source code without executing it, looking for patterns that indicate security vulnerabilities. Unlike dynamic testing that requires a running application, SAST operates directly on the code, allowing problems to be identified in the earliest stages of development.
SAST analyzes code looking for vulnerabilities such as SQL injection, cross-site scripting (XSS), buffer overflow, hardcoded credentials, insecure deserialization, and many others. SAST tools build a model of the code (AST - Abstract Syntax Tree) and apply security rules to identify problematic patterns.
In this article, we will explore the main SAST tools, their integration into CI/CD pipelines, and strategies for managing one of the most common problems: false positives.
What You'll Learn
- How SAST works and the difference with DAST and IAST
- Configuring SonarQube, Semgrep, and CodeQL in the CI/CD pipeline
- Writing custom rules for Semgrep
- Managing false positives and prioritizing findings
- Integrating SAST in the IDE for immediate feedback
- Quality Gates and blocking thresholds for deployment
SAST vs DAST vs IAST: The Differences
To choose the right tools, it's essential to understand the differences between the three main security testing approaches:
Security Testing Approaches Comparison
| Feature | SAST | DAST | IAST |
|---|---|---|---|
| Analysis | Source code (white-box) | Running application (black-box) | Runtime with agent (grey-box) |
| When | During development, in CI | In staging/pre-production | During functional tests |
| Coverage | All code, even unreachable | Only HTTP-reachable parts | Code executed during tests |
| False Positives | Medium-high | Low | Very low |
| Speed | Fast (minutes) | Slow (hours) | Depends on tests |
The optimal approach is to use all three complementarily: SAST for quick feedback during development, DAST to validate runtime security, and IAST for precise correlation during testing.
SonarQube: Complete Code Quality Analysis
SonarQube is the most widely used SAST platform, used by over 400,000 organizations. Beyond security, it analyzes code quality, code smells, duplications, and test coverage. The Community edition is open source and covers 30+ programming languages.
Setup with Docker Compose
The quickest way to start SonarQube locally or in a staging environment is through Docker Compose:
# docker-compose.sonarqube.yml
version: "3.8"
services:
sonarqube:
image: sonarqube:lts-community
container_name: sonarqube
ports:
- "9000:9000"
environment:
- SONAR_JDBC_URL=jdbc:postgresql://db:5432/sonarqube
- SONAR_JDBC_USERNAME=sonar
- SONAR_JDBC_PASSWORD=sonar_password
volumes:
- sonarqube_data:/opt/sonarqube/data
- sonarqube_logs:/opt/sonarqube/logs
- sonarqube_extensions:/opt/sonarqube/extensions
depends_on:
- db
db:
image: postgres:15
container_name: sonarqube-db
environment:
- POSTGRES_USER=sonar
- POSTGRES_PASSWORD=sonar_password
- POSTGRES_DB=sonarqube
volumes:
- postgresql_data:/var/lib/postgresql/data
volumes:
sonarqube_data:
sonarqube_logs:
sonarqube_extensions:
postgresql_data:
Integration in GitHub Actions
Integrating SonarQube in the CI/CD pipeline with GitHub Actions allows automatic analysis on every push or pull request:
# .github/workflows/sonarqube.yml
name: SonarQube Analysis
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
sonarqube:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: SonarQube Scan
uses: SonarSource/sonarqube-scan-action@v3
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
- name: SonarQube Quality Gate
uses: SonarSource/sonarqube-quality-gate-action@v1
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
Semgrep: Lightweight and Customizable Static Analysis
Semgrep is an open source SAST tool created by Return Security (now Semgrep Inc.) that stands out for its simplicity in creating custom rules. Unlike SonarQube which requires a server, Semgrep can be run as a simple command-line tool.
Semgrep's power lies in its pattern matching language that allows writing security rules intuitively, almost like writing the code you want to find.
Writing Custom Semgrep Rules
Here is an example of a Semgrep rule to detect SQL injection in Python applications:
# .semgrep/sql-injection.yml
rules:
- id: python-sql-injection
patterns:
- pattern: |
cursor.execute($QUERY)
- pattern-not: |
cursor.execute($QUERY, $PARAMS)
- metavariable-pattern:
metavariable: $QUERY
patterns:
- pattern: |
f"..."
message: >
Possible SQL injection: the SQL query uses f-string
instead of prepared parameters. Use cursor.execute(query, params)
with %s placeholders to prevent injection.
severity: ERROR
languages: [python]
metadata:
cwe:
- "CWE-89: Improper Neutralization of Special Elements"
owasp:
- "A03:2021 - Injection"
confidence: HIGH
CI/CD Integration
Semgrep integrates easily into any CI/CD pipeline. Here is the configuration for GitHub Actions:
# .github/workflows/semgrep.yml
name: Semgrep Security Scan
on:
push:
branches: [main]
pull_request:
jobs:
semgrep:
runs-on: ubuntu-latest
container:
image: semgrep/semgrep
steps:
- uses: actions/checkout@v4
- name: Run Semgrep
run: |
semgrep scan \
--config auto \
--config .semgrep/ \
--sarif --output semgrep-results.sarif \
--error \
--severity ERROR
- name: Upload SARIF
if: always()
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: semgrep-results.sarif
CodeQL: GitHub's Semantic Analysis
CodeQL is the analysis engine developed by GitHub that treats code as queryable data. Unlike Semgrep which uses pattern matching, CodeQL builds a relational database of the code and allows writing complex queries to find vulnerabilities.
CodeQL excels at taint tracking analysis: the ability to follow data flow from user input (source) to sensitive operations (sink), verifying whether data is sanitized along the path.
CodeQL: Key Advantages
- Free for public repositories on GitHub
- Deep semantic analysis with taint tracking
- Extensive rule community maintained by GitHub Security Lab
- Native integration with GitHub Advanced Security
- Support for custom queries in the QL language
Managing False Positives
One of the major problems with SAST tools is the false positive rate: alerts that flag vulnerabilities that don't actually exist. A false positive rate that's too high erodes team trust in the tools and leads to alert fatigue, where developers start ignoring all alerts.
Strategies to Reduce False Positives
- Rule tuning: disable rules not relevant to the application context
- Targeted exclusions: exclude generated files, tests, vendor code
- Baseline: establish a baseline and focus only on new findings
- Prioritization: focus first on CRITICAL and HIGH severity
- Suppression comments: mark false positives with documented comments
# Example of suppression in Python code
import hashlib
# This MD5 usage is for checksum, not security
# nosemgrep: python-weak-hashing
file_hash = hashlib.md5(file_content).hexdigest() # noqa: S303
# Example of SonarQube suppression
password = get_env("DB_PASSWORD") # NOSONAR - password from env var, not hardcoded
Quality Gates: When to Block Deployment
A Quality Gate defines the minimum quality and security thresholds that code must meet to be released. It's the mechanism that transforms SAST from an informational tool to a blocking gate in the pipeline.
Recommended Quality Gate
| Metric | Threshold | Action |
|---|---|---|
| CRITICAL Vulnerabilities | 0 | Block deploy |
| HIGH Vulnerabilities | 0 (new code) | Block deploy |
| MEDIUM Vulnerabilities | Max 5 (new code) | Warning, review required |
| Security Hotspots | 100% reviewed | Block if not reviewed |
| Code Coverage | Min 80% (new code) | Warning |
SAST in the IDE: Immediate Feedback
The most effective shift-left is bringing SAST analysis directly into the developer's IDE. This allows identifying and fixing vulnerabilities while writing code, even before committing.
- SonarLint: plugin for IntelliJ, VS Code, Eclipse. Connected to SonarQube to synchronize rules
- Semgrep VS Code Extension: highlights findings directly in the editor
- GitHub Copilot: suggests contextual security fixes
IDE integration reduces the feedback loop from minutes (CI/CD) to seconds, drastically increasing the likelihood that the developer fixes the issue immediately.
SAST Best Practices
After implementing SAST in several enterprise projects, here are the best practices we recommend:
- Start in non-blocking mode: for the first 2-4 sprints, SAST generates reports only without blocking deploys. This allows the team to familiarize with the tools
- Establish a baseline: record the number of existing findings and focus on progressive reduction
- Focus on new code: apply strict thresholds only to new code, to avoid blocking the team on legacy technical debt
- Custom rules for context: create Semgrep/CodeQL rules specific to application patterns
- Weekly finding review: dedicate 1-2 weekly hours to SAST finding triage with the Security Champion
- Metrics and trends: track MTTR, false positive rate, and vulnerability density over time
Conclusions
SAST is the first line of defense in the DevSecOps paradigm. Identifying vulnerabilities in source code before it's executed saves time, money, and risk. The key to success is balancing coverage and usability: too many rules generate alert fatigue, too few let critical vulnerabilities through.
In the next article, we'll explore DAST (Dynamic Application Security Testing), the natural complement to SAST that analyzes running applications to find runtime vulnerabilities like XSS, CSRF, and misconfiguration.
Related deep dive: 01 - Introduzione a DevSecOps - Shift-Left e Sicurezza nel Ciclo di Sviluppo.
Related deep dive: 03 - DAST - Test Dinamico e Penetration Testing Automatico.
Frequently asked questions
What is the main difference between Static Application Security Testing (SAST) and dynamic testing?
Unlike dynamic testing, which requires a running application, SAST examines source code without executing it to identify security vulnerabilities.
How does SonarQube analyze code beyond just security?
It analyzes code quality, detects code smells, identifies duplications, and measures test coverage in addition to its security analysis capabilities.
What is unique about Semgrep's approach to writing custom rules for static analysis?
Its pattern matching language allows writing security rules intuitively, almost like writing the code you want to find.
Why is it essential to balance coverage and usability when implementing SAST in a development pipeline?
Too many rules can generate alert fatigue, while too few may let critical vulnerabilities through.
Related deep dive: Rate Limiting Multi-Bucket: Perché un Solo Numero per Tutta l'API è un Errore.
Commenti
Caricamento commenti...
Sign in to comment