SAST and DAST
1 - Overview
1.1 Differences
| Aspect | SAST | DAST |
|---|---|---|
| When | Before execution | Application running |
| What | Source code | Deployed application |
| How | Static analysis | HTTP requests |
| Advantage | Early detection | Real runtime vulns |
| Limitation | False positives | Limited coverage |
1.2 Complementarity
testing_strategy:
sast:
- Injection flaws (SQL, XSS)
- Hardcoded secrets
- Insecure crypto
- Buffer overflows
dast:
- Authentication issues
- Session management
- Configuration errors
- API vulnerabilities
both_needed:
- SAST finds bugs in the code
- DAST validates runtime behavior
- Together = complete coverage
2 - SAST (Static Application Security Testing)
2.1 Popular tools
| Tool | Languages | Type |
|---|---|---|
| SonarQube | 30+ | Commercial/OSS |
| Semgrep | 30+ | OSS |
| CodeQL | 10+ | OSS (GitHub) |
| Bandit | Python | OSS |
| ESLint Security | JavaScript | OSS |
| Checkmarx | 25+ | Commercial |
| Fortify | 25+ | Commercial |
2.2 SonarQube Integration
# .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@master
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
- name: Quality Gate
uses: sonarsource/sonarqube-quality-gate-action@master
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
# sonar-project.properties
sonar.projectKey=my-app
sonar.sources=src
sonar.tests=tests
sonar.javascript.lcov.reportPaths=coverage/lcov.info
# Security rules
sonar.issue.ignore.multicriteria=e1
sonar.issue.ignore.multicriteria.e1.ruleKey=typescript:S1234
sonar.issue.ignore.multicriteria.e1.resourceKey=**/*test*.ts
2.3 Semgrep
# .semgrep.yml
rules:
- id: detect-jwt-none-algorithm
patterns:
- pattern: jwt.decode($TOKEN, algorithms=["none"])
message: "JWT with 'none' algorithm is insecure"
severity: ERROR
metadata:
cwe: "CWE-327"
owasp: "A02:2021"
- id: sql-injection-format-string
patterns:
- pattern-either:
- pattern: |
$QUERY = f"SELECT ... {$VAR} ..."
cursor.execute($QUERY)
- pattern: |
$QUERY = "SELECT ... %s ..." % $VAR
cursor.execute($QUERY)
message: "Potential SQL injection"
severity: ERROR
# GitHub Action
- name: Semgrep
uses: returntocorp/semgrep-action@v1
with:
config: >-
p/security-audit
p/owasp-top-ten
p/cwe-top-25
2.4 CodeQL (GitHub)
# .github/workflows/codeql.yml
name: CodeQL
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 0 * * 0'
jobs:
analyze:
runs-on: ubuntu-latest
permissions:
security-events: write
strategy:
matrix:
language: ['javascript', 'python']
steps:
- uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
queries: security-extended
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
3 - DAST (Dynamic Application Security Testing)
3.1 Tools
| Tool | Type | Features |
|---|---|---|
| OWASP ZAP | OSS | Full scanner |
| Burp Suite | Commercial | Pro features |
| Nuclei | OSS | Template-based |
| Nikto | OSS | Web server scan |
| Arachni | OSS | Full DAST |
3.2 OWASP ZAP
# GitHub Action with ZAP
name: DAST with ZAP
on:
push:
branches: [main]
jobs:
zap_scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Start Application
run: |
docker-compose up -d
sleep 30
- name: ZAP Baseline Scan
uses: zaproxy/action-[email protected]
with:
target: 'http://localhost:8080'
rules_file_name: '.zap/rules.tsv'
cmd_options: '-a'
- name: Upload Report
uses: actions/upload-artifact@v3
with:
name: zap-report
path: report_html.html
# .zap/rules.tsv - Rule configuration
10016 IGNORE (Web Browser XSS Protection Not Enabled)
10017 IGNORE (Cross-Domain JavaScript Source File Inclusion)
10020 WARN (X-Frame-Options Header Not Set)
10021 FAIL (X-Content-Type-Options Header Missing)
10038 FAIL (Content Security Policy Header Not Set)
3.3 ZAP Full Scan
- name: ZAP Full Scan
uses: zaproxy/action-full-[email protected]
with:
target: 'http://localhost:8080'
docker_name: 'owasp/zap2docker-stable'
allow_issue_writing: false
artifact_name: 'zap-full-report'
3.4 Nuclei
# Scan with Nuclei
- name: Nuclei Scan
uses: projectdiscovery/nuclei-action@main
with:
target: https://app.example.com
templates: |
cves/
vulnerabilities/
misconfiguration/
severity: critical,high,medium
output: nuclei-results.txt
4 - IAST (Interactive)
4.1 Concept
IAST = An agent inside the application that observes behavior during tests.
4.2 IAST tools
| Tool | Languages |
|---|---|
| Contrast Security | Java, .NET, Node |
| Seeker | Java, .NET |
| Hdiv | Java, .NET |
5 - Full CI/CD integration
5.1 Complete pipeline
# .gitlab-ci.yml
stages:
- test
- sast
- build
- dast
- deploy
# SAST Stage
sast:
stage: sast
parallel:
matrix:
- SCANNER: [semgrep, sonarqube, gitleaks]
script:
- case $SCANNER in
semgrep) semgrep --config auto --error ;;
sonarqube) sonar-scanner ;;
gitleaks) gitleaks detect --source . ;;
esac
allow_failure: false
# Build
build:
stage: build
script:
- docker build -t $IMAGE .
- trivy image --exit-code 1 --severity HIGH,CRITICAL $IMAGE
needs: [sast]
# DAST Stage
dast:
stage: dast
services:
- name: $IMAGE
alias: app
script:
- zap-baseline.py -t http://app:8080 -r report.html
artifacts:
reports:
dast: gl-dast-report.json
needs: [build]
# Deploy only if all security checks pass
deploy:
stage: deploy
script:
- kubectl apply -f k8s/
needs: [dast]
only:
- main
5.2 Security Gates
# Quality Gates
security_gates:
sast:
critical: 0
high: 0
medium: 10 # Max allowed
dast:
critical: 0
high: 0
container:
critical: 0
high: 5
6 - Managing the results
6.1 Vulnerability triage
| Status | Description | Action |
|---|---|---|
| Confirmed | Real vulnerability | Fix required |
| False Positive | False alert | Mark and ignore |
| Won't Fix | Accepted risk | Document |
| In Progress | Fix underway | Track |
6.2 Remediation SLA
| Severity | SLA | Escalation |
|---|---|---|
| Critical | 24 hours | Immediate |
| High | 7 days | 3 days |
| Medium | 30 days | 15 days |
| Low | 90 days | 60 days |
Summary
In this chapter, we learned:
- The differences between SAST and DAST
- The SAST tools (SonarQube, Semgrep, CodeQL)
- The DAST tools (OWASP ZAP, Nuclei)
- The IAST concept
- Integration into CI/CD pipelines
- Managing the results
Next step
In the next chapter, we will look at Container security.
→ Next chapter: Container security