Integrates Static Application Security Testing (SAST), Dynamic Application Security Testing (DAST), and Software Composition Analysis (SCA) into CI/CD pipelines using open-source tools. Covers Semgrep for SAST, Trivy for SCA and container scanning, OWASP ZAP for DAST, and Gitleaks for secrets detection. Activates for requests involving DevSecOps pipeline setup, automated security scanning in CI/CD, SAST/DAST/SCA integration, or shift-left security implementation.
Instrucciones de origen · Vista previa de solo lectura
name
implementing-devsecops-security-scanning
description
Integrates Static Application Security Testing (SAST), Dynamic Application Security Testing (DAST), and Software Composition Analysis (SCA) into CI/CD pipelines using open-source tools. Covers Semgrep for SAST, Trivy for SCA and container scanning, OWASP ZAP for DAST, and Gitleaks for secrets detection. Activates for requests involving DevSecOps pipeline setup, automated security scanning in CI/CD, SAST/DAST/SCA integration, or shift-left security implementation.
Setting up automated security scanning in a new or existing CI/CD pipeline
Shifting security left by catching vulnerabilities before code reaches production
Meeting compliance requirements (SOC 2, PCI-DSS, ISO 27001) that mandate automated security testing
Integrating SAST, DAST, and SCA together to achieve comprehensive application security coverage
Establishing security gates that block deployments containing critical or high-severity vulnerabilities
Do not use as a replacement for manual penetration testing. Automated scanning catches common vulnerability patterns but cannot replace human-driven security assessments for business logic flaws and complex attack chains.
Common Misconfigurations & Verification
The most common failure is a scan that runs but never blocks: findings are reported yet the build stays green.
Gate reports but does not fail: Semgrep without --error (or with continue-on-error: true), or Trivy without exit-code: '1', prints findings and exits 0. The security-gate job must inspect needs.*.result and exit 1.
Severity floor hides real bugs:--severity ERROR / severity: 'CRITICAL,HIGH' silently drops MEDIUM secrets and SCA hits. Confirm the threshold matches policy.
DAST against the wrong target:action-baseline pointed at an unauthenticated landing page or a stale build crawls almost nothing. Verify ZAP authenticated and the spidered URL count is non-trivial.
Shallow checkout blinds Gitleaks: without fetch-depth: 0 only the tip commit is scanned, so secrets in history pass.
Branch protection not wired: the gate job exists but is not a required status check, so PRs merge around it.
Verify the gate actually bites: plant a dummy AWS_SECRET_ACCESS_KEY, a cursor.execute(f"...") SQLi pattern, and a pinned known-vulnerable dependency (e.g. lodash@4.17.20), open a PR, and confirm the merge is blocked — not merely annotated. A gate you have never seen fail is not a gate.
Prerequisites
CI/CD platform: GitHub Actions, GitLab CI, Jenkins, or Azure DevOps
Container runtime (Docker) for running scanning tools
A staging environment URL for DAST scanning (DAST cannot test static code)
Repository access with permissions to modify CI/CD workflow files
Tool-specific requirements:
Semgrep: free for open-source rulesets (p/security-audit, p/owasp-top-ten)
Trivy: free, no account required
OWASP ZAP: free, Docker image available
Gitleaks: free, no account required
Workflow
Step 1: Add Secrets Detection with Gitleaks
Secrets detection runs first because leaked credentials are the highest-priority finding. Add to .github/workflows/security.yml:
name:DevSecOpsSecurityPipelineon:push:branches: [main, develop]
pull_request:branches: [main]
jobs:secrets-scan:name:SecretsDetection(Gitleaks)runs-on:ubuntu-lateststeps:-uses:actions/checkout@v4with:fetch-depth:0# Full history for scanning all commits-name:RunGitleaksuses:gitleaks/gitleaks-action@v2env:GITHUB_TOKEN:${{secrets.GITHUB_TOKEN}}
Configure .gitleaks.toml in the repository root for custom rules and allowlists:
For custom rules, create .semgrep/custom-rules.yml:
rules:-id:no-exec-user-inputpatterns:-pattern:exec($INPUT)-pattern-not:exec("...")message:>
User input passed to exec(). This is a command injection vulnerability.
severity:ERRORlanguages: [python]
metadata:cwe:"CWE-78: OS Command Injection"owasp:"A03:2021 - Injection"-id:no-raw-sql-queriespatterns:-pattern:cursor.execute(f"...")-pattern:cursor.execute("..."+...)message:>
SQL query built with string concatenation or f-strings. Use parameterized queries.
severity:ERRORlanguages: [python]
metadata:cwe:"CWE-89: SQL Injection"owasp:"A03:2021 - Injection"
Step 3: Add SCA Scanning with Trivy
Trivy scans dependencies, container images, IaC files, and generates SBOM:
sca-scan:name:SCA&ContainerScan(Trivy)runs-on:ubuntu-lateststeps:-uses:actions/checkout@v4-name:RunTrivyfilesystemscan(dependencies)uses:aquasecurity/trivy-action@0.28.0with:scan-type:'fs'scan-ref:'.'severity:'CRITICAL,HIGH'exit-code:'1'format:'json'output:'trivy-fs-results.json'-name:RunTrivyIaCscan(Terraform,CloudFormation)uses:aquasecurity/trivy-action@0.28.0with:scan-type:'config'scan-ref:'.'severity:'CRITICAL,HIGH'exit-code:'1'format:'json'output:'trivy-iac-results.json'-name:UploadSCAresultsif:always()uses:actions/upload-artifact@v4with:name:trivy-resultspath:trivy-*.jsoncontainer-scan:name:ContainerImageScan(Trivy)runs-on:ubuntu-latestneeds: [sast-scan] # Build image only after SAST passessteps:-uses:actions/checkout@v4-name:BuildDockerimagerun:dockerbuild-tapp:${{github.sha}}.-name:Scancontainerimageuses:aquasecurity/trivy-action@0.28.0with:image-ref:'app:${{ github.sha }}'severity:'CRITICAL,HIGH'exit-code:'1'format:'json'output:'trivy-image-results.json'-name:GenerateSBOMuses:aquasecurity/trivy-action@0.28.0with:image-ref:'app:${{ github.sha }}'format:'cyclonedx'output:'sbom.json'-name:UploadSBOMuses:actions/upload-artifact@v4with:name:sbompath:sbom.json
Step 4: Add DAST Scanning with OWASP ZAP
DAST runs against a deployed staging environment. It is slower than SAST/SCA and should run asynchronously or on a schedule:
dast-scan:name:DAST(OWASPZAP)runs-on:ubuntu-latestneeds: [deploy-staging] # Must run after app is deployed to stagingsteps:-uses:actions/checkout@v4-name:RunZAPBaselineScan(fast,suitableforCI)uses:zaproxy/action-baseline@v0.14.0with:target:${{vars.STAGING_URL}}rules_file_name:'.zap/rules.tsv'cmd_options:'-a -j'# For nightly full scans, use action-full-scan instead:# - name: Run ZAP Full Scan (comprehensive, 30-60 min)# uses: zaproxy/action-full-scan@v0.12.0# with:# target: ${{ vars.STAGING_URL }}
Create .zap/rules.tsv to configure alert thresholds:
10010 IGNORE (Cookie No HttpOnly Flag - acceptable for non-sensitive cookies)
10011 IGNORE (Cookie Without Secure Flag - staging uses HTTP)
90033 WARN (Loosely Scoped Cookie)
10038 FAIL (Content Security Policy Header Not Set)
40012 FAIL (Cross Site Scripting - Reflected)
40014 FAIL (Cross Site Scripting - Persistent)
40018 FAIL (SQL Injection)
90019 FAIL (Server Side Code Injection)
90020 FAIL (Remote OS Command Injection)
Step 5: Aggregate Results and Enforce Security Gates
Create a summary job that aggregates all scan results and enforces pass/fail gates:
security-gate:name:SecurityGateruns-on:ubuntu-latestneeds: [secrets-scan, sast-scan, sca-scan, container-scan]
if:always()steps:-name:Checkscanresultsrun:|
echo "Checking security scan results..."
# Fail the pipeline if any upstream job failedif [[ "${{ needs.secrets-scan.result }}"=="failure" ]];thenecho"BLOCKED: Secrets detected in repository"exit1fiif [[ "${{ needs.sast-scan.result }}"=="failure" ]];thenecho"BLOCKED: SAST found critical/high vulnerabilities"exit1fiif [[ "${{ needs.sca-scan.result }}"=="failure" ]];thenecho"BLOCKED: SCA found critical/high vulnerable dependencies"exit1fiif [[ "${{ needs.container-scan.result }}"=="failure" ]];thenecho"BLOCKED: Container image has critical/high vulnerabilities"exit1fiecho"All security gates passed"
Step 6: Configure Branch Protection Rules
Enforce the security pipeline as a required status check:
GitHub Repository > Settings > Branches > Branch Protection Rules
Branch name pattern: main
Require status checks to pass before merging: Enabled
Required status checks:
- Secrets Detection (Gitleaks)
- SAST (Semgrep)
- SCA & Container Scan (Trivy)
- Security Gate
Require branches to be up to date before merging: Enabled
Step 7: Set Up Developer Feedback Loop
Configure pre-commit hooks so developers catch issues before pushing: