Technology

Security Automation: Vulnerability Scanning in CI/CD

Catch vulnerabilities before production. SAST, DAST, dependency scanning, and container scanning.

All articles
TechnologyNexaEx TeamJanuary 15, 2026 8 min read
Security Automation: Vulnerability Scanning in CI/CD

Security After Deployment Fails

Security that happens after code ships is too late. By then, the vulnerability is live. Users are at risk.

Modern security is automated, continuous, and happens during development. Scan every commit. Fail builds that have high-severity vulnerabilities. Security is a developer responsibility, not an afterthought.

The Security Scanning Stack

SAST (Static Application Security Testing): Analyze source code for vulnerabilities.

  • Runs on code, no compilation needed.
  • Fast (minutes).
  • High false positive rate.
  • Catches: SQL injection, XSS, hardcoded secrets, weak crypto.

DAST (Dynamic Application Security Testing): Test running application by attacking it.

  • Runs after deployment.
  • Slow (15-30 minutes).
  • Tests real behavior (more accurate).
  • Catches: misconfigurations, broken authentication, business logic flaws.

Dependency scanning: Check third-party libraries for known vulnerabilities.

  • Runs on package manifests (package.json, requirements.txt, pom.xml).
  • Very fast (<1 minute).
  • High value (dependencies are large attack surface).
  • Catches: outdated packages with known CVEs.

Container scanning: Check Docker images for vulnerabilities.

  • Scans layers for malicious content and CVEs.
  • Fast (seconds).
  • Essential for container-based infrastructure.
  • Catches: vulnerable base images, malware.

SAST Tools

Semgrep (open-source):

  • Lightweight, fast, accurate.
  • Works with 15+ languages.
  • Integrates easily into CI/CD.
  • Best for startups.
# Run on every commit
semgrep --config=p/security-audit src/
# Fails if high-severity issues found

SonarQube:

  • More comprehensive than Semgrep.
  • Expensive ($2k+/year).
  • Better for enterprises.

Snyk, GitHub Advanced Security:

  • Managed SaaS.
  • Easy integration with GitHub/GitLab.
  • Paid services.

Dependency Scanning

npm audit (Node.js):

npm audit  # Find vulnerabilities
npm audit fix  # Auto-fix

pip audit (Python):

pip install pip-audit
pip-audit  # Find vulnerabilities in requirements

Safety (Python):

pip install safety
safety check

OWASP Dependency-Check:

dependency-check --scan .

Integrate into CI/CD:

# GitHub Actions
- name: Audit dependencies
  run: npm audit --audit-level=high
  # Fail if high-severity vulnerabilities

Container Scanning

Trivy:

  • Fast, accurate, open-source.
  • Scans Docker images, Kubernetes manifests, any files.
  • Integrates with CI/CD.
trivy image myapp:latest
# Outputs CVEs and severity

Snyk Container:

  • Managed scanning.
  • Better UX, paid.

Anchore:

  • Open-source or managed.
  • Deep analysis of image layers.

Fail builds if critical CVEs found:

- name: Scan image
  run: |
    trivy image myapp:latest
    # Fails if critical CVEs found

DAST and Penetration Testing

DAST requires a running application. Run after staging deployment.

OWASP ZAP (open-source):

docker run -v $(pwd):/zap/wrk owasp/zap2docker-stable   zap-baseline.py -t https://staging.myapp.com/

Reports vulnerabilities in running app.

Real penetration testing: For production applications, hire professional pen testers annually. Automated DAST catches low-hanging fruit; professionals find business logic flaws and nuanced attacks.

CI/CD Security Pipeline

Ideal security automation:

# .github/workflows/security.yml
name: Security Scan

on: [pull_request]

jobs:
  sast:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: SAST scan
        run: semgrep --config=p/security-audit src/

  dependencies:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Npm audit
        run: npm audit --audit-level=high
      - name: OWASP dependency check
        run: dependency-check --scan .

  secrets:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Detect secrets
        uses: trufflesecurity/trufflehog@main

  container:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Build image
        run: docker build -t myapp:${{ github.sha }} .
      - name: Scan image
        run: trivy image myapp:${{ github.sha }}

On every PR:

  1. SAST scans source code
  2. Dependency check scans packages
  3. Secret detection prevents credential leaks
  4. Container scanning checks Docker image

If any check fails, PR is blocked. Fix issues before merging.

False Positives and Alert Fatigue

Security scanning generates false positives. ("This is SQL injection! Actually, it's a log message.") Too many false positives cause developers to ignore alerts.

Manage false positives:

  • Use strict SAST rules (reduce noise)
  • Suppress known false positives with comments
# nosemgrep: sql-injection
# The user input is validated and parameterized above
query = f"SELECT * FROM users WHERE id = {user_id}"
  • Fail the build only on high-severity issues
  • Allow warnings and medium issues, but don't block

Policies and Compliance

Document security policies:

  • No hardcoded secrets
  • All dependencies must be pinned to specific versions
  • High-severity vulnerabilities must be fixed within 48 hours
  • Medium-severity within 1 week
  • All Docker images must be scanned before production

Enforce policies in CI/CD automatically.

Security Checklist

  • SAST (Semgrep or SonarQube) in CI/CD
  • Dependency scanning (npm audit, OWASP DC)
  • Secret scanning (TruffleHog or GitHub Secret Scanning)
  • Container scanning (Trivy)
  • Secrets management (no hardcoded credentials)
  • DAST for critical services (after staging deploy)
  • Annual penetration testing for production
  • Documented security policies
  • Security training for team
  • Incident response plan

Frequently asked questions

Should we scan every commit or just on release?

Every commit, in CI/CD. The earlier you catch vulnerabilities, the cheaper they are to fix. Scanning only at release means vulnerabilities reach production. Scan on every PR.

How do we handle unavoidable vulnerabilities (e.g., library with unpatched CVE)?

Document the risk. If the CVE doesn't affect your code path, document why it's safe. Mitigate with compensating controls (WAF rules, network isolation). Replace the library ASAP. Never ignore.

What's the difference between SAST and DAST?

SAST analyzes code without running it (fast, catches code flaws). DAST tests running application (slow, catches runtime issues and misconfigurations). Use both. SAST for speed, DAST for depth.

Let's build your next idea

One conversation to scope the work, meet the team, and get a proposal — usually within two business days.