Skip to main content

SAST and DAST


1 - Overview

1.1 Differences

AspectSASTDAST
WhenBefore executionApplication running
WhatSource codeDeployed application
HowStatic analysisHTTP requests
AdvantageEarly detectionReal runtime vulns
LimitationFalse positivesLimited 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)

ToolLanguagesType
SonarQube30+Commercial/OSS
Semgrep30+OSS
CodeQL10+OSS (GitHub)
BanditPythonOSS
ESLint SecurityJavaScriptOSS
Checkmarx25+Commercial
Fortify25+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

ToolTypeFeatures
OWASP ZAPOSSFull scanner
Burp SuiteCommercialPro features
NucleiOSSTemplate-based
NiktoOSSWeb server scan
ArachniOSSFull 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

ToolLanguages
Contrast SecurityJava, .NET, Node
SeekerJava, .NET
HdivJava, .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

StatusDescriptionAction
ConfirmedReal vulnerabilityFix required
False PositiveFalse alertMark and ignore
Won't FixAccepted riskDocument
In ProgressFix underwayTrack

6.2 Remediation SLA

SeveritySLAEscalation
Critical24 hoursImmediate
High7 days3 days
Medium30 days15 days
Low90 days60 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


← Back to table of contents