Skip to main content
Career Paths
Concepts
Security Scanning
The Simplified Tech

Role-based learning paths to help you master cloud engineering with clarity and confidence.

Product

  • Career Paths
  • Interview Prep
  • Scenarios
  • AI Features
  • Cloud Comparison
  • Resume Builder
  • Pricing

Community

  • Join Discord

Account

  • Dashboard
  • Credits
  • Updates
  • Sign in
  • Sign up
  • Contact Support

Stay updated

Get the latest learning tips and updates. No spam, ever.

Terms of ServicePrivacy Policy

© 2026 TheSimplifiedTech. All rights reserved.

BackBack
Interactive Explainer

Security in CI/CD: SAST, SCA, and Secret Scanning

How to embed automated security scanning — static analysis, dependency checking, container scanning, and secret detection — directly into your CI/CD pipeline so vulnerabilities are caught before they reach production.

🎯Key Takeaways
Four scanning pillars: SAST (code), SCA (dependencies), Container scanning (OS packages), Secret scanning (leaked credentials).
SAST finds vulnerable code patterns — SQL injection, XSS, insecure crypto — without running the application.
SCA scans your dependency graph against CVE databases — the Log4Shell response validated SCA as mandatory.
Container scanning checks base image OS packages in addition to language packages — run after every docker build.
Secret scanning must run both as a pre-commit hook (fast feedback) and in CI (non-bypassable enforcement).
Parallelise all scanners — security gates that slow CI by >20% get disabled by frustrated teams.
SARIF format allows all scanner results to flow into GitHub Advanced Security or GitLab Vulnerability Reports for centralised tracking.
Pin third-party CI actions to commit SHAs — the Codecov breach showed that mutable CI scripts are a supply chain attack vector.

Security in CI/CD: SAST, SCA, and Secret Scanning

How to embed automated security scanning — static analysis, dependency checking, container scanning, and secret detection — directly into your CI/CD pipeline so vulnerabilities are caught before they reach production.

~10 min read
Be the first to complete!
Why this matters

Manual code reviews miss security bugs, vulnerable dependencies ship unnoticed, and secrets get committed to Git — all because security checks happen too late (or not at all) in the development cycle.

Without this knowledge

Vulnerabilities are discovered in production, often by attackers. Remediating a flaw found in production costs 6–30× more than catching it during development, and the business impact (breach, downtime, compliance failure) can be catastrophic.

With this knowledge

Every pull request and every build automatically runs SAST, dependency scanning, container scanning, and secret detection. Security issues are flagged as PR comments or build failures — developers fix them before merging, treating security exactly like any other quality gate.

What you'll learn
  • Four scanning pillars: SAST (code), SCA (dependencies), Container scanning (OS packages), Secret scanning (leaked credentials).
  • SAST finds vulnerable code patterns — SQL injection, XSS, insecure crypto — without running the application.
  • SCA scans your dependency graph against CVE databases — the Log4Shell response validated SCA as mandatory.
  • Container scanning checks base image OS packages in addition to language packages — run after every docker build.
  • Secret scanning must run both as a pre-commit hook (fast feedback) and in CI (non-bypassable enforcement).
  • Parallelise all scanners — security gates that slow CI by >20% get disabled by frustrated teams.
  • SARIF format allows all scanner results to flow into GitHub Advanced Security or GitLab Vulnerability Reports for centralised tracking.
  • Pin third-party CI actions to commit SHAs — the Codecov breach showed that mutable CI scripts are a supply chain attack vector.

Lesson outline

The Four Pillars of Pipeline Security Scanning

A complete security scanning strategy in CI/CD covers four distinct categories. Each catches a different class of vulnerability.

PillarWhat It FindsWhen It RunsExample Tools
SAST (Static Application Security Testing)Vulnerable code patterns — SQL injection, XSS, hardcoded passwords, insecure functionsOn every PR / commitSemgrep, Snyk Code, CodeQL, Checkmarx, Bandit (Python), ESLint-security
SCA (Software Composition Analysis)Known CVEs in open-source dependenciesOn every PR / dependency updateSnyk, Dependabot, OWASP Dependency-Check, Renovate with security checks
Container / Image ScanningCVEs in base OS packages and installed libraries inside container imagesAfter docker buildTrivy, Snyk Container, Grype, AWS ECR scanning, Clair
Secret ScanningAPI keys, tokens, passwords accidentally committed to GitPre-commit hook + every PRgitleaks, truffleHog, GitHub Secret Scanning, GitLab Secret Detection

Shift left — catch bugs where they are cheapest to fix

A CVE caught by a pre-commit hook costs 5 minutes to fix. The same CVE found in production during a pen test costs days of emergency patching, possible downtime, and potential breach notification obligations. Run scanners as early in the pipeline as possible.

SAST: Finding Vulnerable Code Before It Ships

SAST tools analyse source code (or compiled bytecode) without running the application. They look for patterns that commonly lead to security vulnerabilities.

What SAST catches

  • Injection flaws — SQL injection, command injection, LDAP injection — unsanitised input passed to interpreters
  • XSS (Cross-Site Scripting) — User input rendered unescaped in HTML templates
  • Insecure cryptography — MD5/SHA1 for passwords, ECB mode, hardcoded IVs
  • Path traversal — User-controlled file paths used in open() calls
  • Insecure deserialization — Untrusted data passed to pickle.loads(), ObjectInputStream
  • Hardcoded credentials — password = "abc123" or api_key = "sk-..." in code
  • Missing input validation — Integer overflow, format string bugs, buffer reads

SAST has high false positive rates — tune your rules

Out-of-the-box SAST can flag hundreds of issues, many of which are false positives. Start with a curated rule set (e.g. Semgrep's OWASP Top 10 rules), suppress known false positives with inline comments + a review process, and add custom rules for your specific framework and threat model. Noisy scanners get ignored.


  Developer pushes code
         │
         ▼
  ┌─────────────────────────────────────────────────────────┐
  │              CI Pipeline (on every PR)                  │
  │                                                         │
  │  ① SAST        ② SCA           ③ Secret Scan           │
  │  Semgrep       Snyk/OWASP      gitleaks                 │
  │  CodeQL        Dependency-     (also pre-commit)        │
  │  Bandit        Check                                    │
  │     │               │               │                   │
  │     └───────┬────────┘               │                   │
  │             ▼                        │                   │
  │     ┌──────────────┐                 │                   │
  │     │  Build +     │◄────────────────┘                   │
  │     │  docker build│                                     │
  │     └──────┬───────┘                                     │
  │            ▼                                             │
  │  ④ Container Scan                                        │
  │  Trivy / Grype                                          │
  │     │                                                    │
  │     ▼                                                    │
  │  Results → PR comments / build failure / SARIF upload   │
  └─────────────────────────────────────────────────────────┘
         │
         ▼ (if all pass)
  Merge → Deploy

Four scanning layers run in parallel where possible. Container scanning runs after the image is built.

sast-semgrep.yml
1# Semgrep SAST — GitHub Actions
2name: SAST Scan
3
4on: [pull_request]
5
6jobs:
7 semgrep:
8 name: SAST with Semgrep
9 runs-on: ubuntu-latest
10 container:
11 image: semgrep/semgrep
12 steps:
13 - uses: actions/checkout@v4
14
15 - name: Run Semgrep
p/owasp-top-ten = curated rules for OWASP Top 10
16 run: |
17 semgrep scan --config p/owasp-top-ten --config p/secrets --config p/python --sarif --output semgrep-results.sarif --error # Fail build on findings
18
19 - name: Upload SARIF to GitHub Security tab
20 uses: github/codeql-action/upload-sarif@v3
--error causes non-zero exit (build fails) on any finding
21 if: always() # Upload even if scan found issues
22 with:
23 sarif_file: semgrep-results.sarif
SARIF = industry standard format for security findings
24 category: semgrep

SCA: Dependency Scanning and CVE Detection

Modern applications use hundreds of open-source packages. Software Composition Analysis (SCA) scans your dependency graph against known CVE databases (NVD, OSV, GitHub Advisory Database) to find vulnerable versions.

The Log4Shell lesson: one dependency, global impact

CVE-2021-44228 (Log4Shell) affected Log4j — a logging library used by millions of Java applications, often as a transitive dependency (a dependency of a dependency). SCA tools discovered which applications used Log4j 2.0–2.14.1 within minutes. Without SCA, teams spent days manually auditing package.json, pom.xml, and build files.

SCA in practice

  • Dependabot (GitHub) — Automatically opens PRs to update vulnerable dependencies. Free, zero config for public repos. Integrates with GitHub Security Advisories.
  • Snyk — Deep dependency graph analysis, fix PR automation, container scanning, IaC scanning. Best commercial option with a generous free tier.
  • OWASP Dependency-Check — Open-source, runs against NVD. Good for air-gapped environments. Higher false positives than Snyk.
  • Renovate — Dependency update automation with security-first mode — auto-merges patch updates that fix CVEs.

Set severity thresholds — not all CVEs block deploys

Configure your SCA tool to: FAIL the build on Critical/High CVEs with a fix available, WARN on Medium CVEs or High CVEs with no fix, IGNORE Low CVEs in pipeline (track separately). Blocking on every Low CVE creates noise and alert fatigue.

trivy-container-scan.yml
1# Trivy — container image scanning + SCA in one tool
2# Trivy scans both OS packages (apk/apt/rpm) and language packages (pip/npm/go)
3name: Container Security Scan
4
5on:
6 push:
7 branches: [main]
8 pull_request:
9
10jobs:
11 trivy-scan:
12 runs-on: ubuntu-latest
13 steps:
14 - uses: actions/checkout@v4
15
16 - name: Build image
17 run: docker build -t myapp:${{ github.sha }} .
18
19 - name: Run Trivy container scan
20 uses: aquasecurity/trivy-action@master
21 with:
22 image-ref: myapp:${{ github.sha }}
23 format: sarif
severity: CRITICAL,HIGH — avoid alert fatigue from Low/Medium
24 output: trivy-results.sarif
25 severity: CRITICAL,HIGH # Only report C/H
ignore-unfixed: skip CVEs where no patch exists yet
26 exit-code: '1' # Fail on findings
27 ignore-unfixed: true # Ignore CVEs with no patch yet
28
29 - name: Upload Trivy results
30 uses: github/codeql-action/upload-sarif@v3
31 if: always()
32 with:
33 sarif_file: trivy-results.sarif
34 category: trivy-container
fs scan also catches Python/Node/Go vulnerable packages
35
36 # Also scan filesystem (SCA for Python/Node/Go deps)
37 - name: Run Trivy filesystem scan
38 uses: aquasecurity/trivy-action@master
39 with:
40 scan-type: fs
41 scan-ref: .
42 format: table
43 severity: CRITICAL,HIGH
44 exit-code: '1'

Secret Scanning: Catching Leaked Credentials

Secret scanners look for high-entropy strings and known credential patterns in your codebase and commit history. They catch AWS keys, GitHub tokens, Stripe secrets, JWT secrets, and more.

Layered secret scanning strategy

→

01

Pre-commit hook (gitleaks / git-secrets) — blocks commits containing secrets on the developer's machine before they ever leave

→

02

CI pipeline scan (gitleaks in GitHub Actions / GitLab Secret Detection) — catches anything that slipped past the pre-commit hook

→

03

GitHub / GitLab native secret scanning — platform-level scanning that also covers historical commits and notifies you of newly added patterns

04

Periodic full-history scan (truffleHog --entropy) — finds secrets buried in old commits from before scanning was in place

1

Pre-commit hook (gitleaks / git-secrets) — blocks commits containing secrets on the developer's machine before they ever leave

2

CI pipeline scan (gitleaks in GitHub Actions / GitLab Secret Detection) — catches anything that slipped past the pre-commit hook

3

GitHub / GitLab native secret scanning — platform-level scanning that also covers historical commits and notifies you of newly added patterns

4

Periodic full-history scan (truffleHog --entropy) — finds secrets buried in old commits from before scanning was in place

Pre-commit hooks can be bypassed with --no-verify

Developers can skip pre-commit hooks with git commit --no-verify. This is why CI pipeline scanning is the non-bypassable safety net. Pre-commit hooks are the fast developer feedback loop; CI scanning is the enforcement gate.

ToolTypeCoverageBest For
gitleaksOpen sourceGit history, staged files, CIPre-commit hooks, CI pipeline
truffleHogOpen sourceFull Git history, entropy analysisHistorical audit of existing repos
GitHub Secret ScanningPlatform nativeAll commits, PRs, issues (for GitHub token patterns)GitHub-hosted repos — zero config
GitLab Secret DetectionPlatform nativeCommits in MR pipelineGitLab CI/CD — built into Ultimate tier
Semgrep (p/secrets)Open source + SaaSSource code patternsCombined SAST + secret scan in one run
gitleaks-setup.yaml
1# gitleaks pre-commit hook + CI enforcement
2# Step 1: Install gitleaks pre-commit hook (developer machine)
3# .pre-commit-config.yaml
4repos:
5 - repo: https://github.com/gitleaks/gitleaks
6 rev: v8.18.2
7 hooks:
8 - id: gitleaks
Pre-commit hook blocks commits with secrets on dev machine
9 # gitleaks will scan staged files before each commit
10 # If a secret is found, the commit is blocked with the finding
11
12# Step 2: CI enforcement (GitHub Actions)
13name: Secret Scanning
14
15on: [push, pull_request]
16
17jobs:
18 gitleaks:
19 runs-on: ubuntu-latest
20 steps:
21 - uses: actions/checkout@v4
22 with:
23 fetch-depth: 0 # Full history — scan all commits in the PR
fetch-depth: 0 ensures full PR history is scanned, not just HEAD
24
25 - uses: gitleaks/gitleaks-action@v2
26 env:
27 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28 # GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} # For org-level scan
29
30# Step 3: Historical audit (run once on existing repos)
31# docker run --rm -v $(pwd):/repo zricethezav/gitleaks \
32# detect --source /repo --report-format sarif \
Historical audit — run this once on all existing repos
33# --report-path gitleaks-report.sarif
34
35# gitleaks.toml — custom rules (optional)
36# [rules]
37# [[rules.rules]]
38# description = "Internal API key pattern"
39# regex = 'MYCO-[A-Z0-9]{32}'
40# tags = ["key", "myco"]

Integrating Scanning into Your Pipeline Without Slowing It Down

Security scanning that doubles build time gets disabled. Parallelise, cache, and threshold-tune to keep the feedback loop fast.

Performance and ergonomics best practices

  • Parallelise SAST, SCA, and secret scanning — Run all three simultaneously as separate CI jobs. No job should wait for another.
  • Cache dependency graphs — SCA tools rebuild the dependency graph on every run. Cache node_modules, .m2, pip caches between runs.
  • Fail fast on secrets — Secret scans are fast (seconds) — run them first or in parallel. A leaked secret is always a build blocker.
  • Use incremental scanning — Semgrep and most SAST tools support scanning only changed files in a PR rather than the full codebase.
  • Establish a suppression process — False positives need a legitimate suppression path (inline comment + reviewer approval) — otherwise developers bypass the scanner entirely.
  • SARIF for all findings — All modern scanners support SARIF output. Upload to GitHub Advanced Security / GitLab Vulnerability Reports for centralised tracking.

The golden rule: security gates must not slow CI by more than 20%

A pipeline that took 5 minutes and now takes 20 minutes due to security scanning will be disabled or bypassed. Target total additional time of under 2–3 minutes through parallelisation and incremental scanning. Fast, accurate, actionable is the goal.

How this might come up in interviews

Pipeline security scanning appears in DevSecOps engineer interviews, senior backend/platform roles, and any role where you own CI/CD. Expect scenario questions about triaging scanner findings and balancing security with developer velocity.

Common questions:

  • What is the difference between SAST and DAST?
  • How would you add security scanning to an existing CI/CD pipeline without disrupting the team?
  • A Trivy scan shows your base image has 47 CVEs. How do you triage and respond?
  • What happened in the Log4Shell incident and how does SCA help prevent similar scenarios?
  • How do you prevent secret sprawl in a large engineering organisation?

Strong answer: Mentions parallelisation for speed, SARIF for centralised reporting, severity thresholds to avoid alert fatigue, and the importance of the pre-commit hook layer for secrets.

Red flags: Thinking SAST is the only security scanner needed, not knowing what SCA stands for, or believing container scanning is covered by language-level dependency scanning.

Quick check · Security in CI/CD: SAST, SCA, and Secret Scanning

1 / 4

You run Trivy on your Docker image and it reports a Critical CVE in libssl. What should you do first?

Key takeaways

  • Four scanning pillars: SAST (code), SCA (dependencies), Container scanning (OS packages), Secret scanning (leaked credentials).
  • SAST finds vulnerable code patterns — SQL injection, XSS, insecure crypto — without running the application.
  • SCA scans your dependency graph against CVE databases — the Log4Shell response validated SCA as mandatory.
  • Container scanning checks base image OS packages in addition to language packages — run after every docker build.
  • Secret scanning must run both as a pre-commit hook (fast feedback) and in CI (non-bypassable enforcement).
  • Parallelise all scanners — security gates that slow CI by >20% get disabled by frustrated teams.
  • SARIF format allows all scanner results to flow into GitHub Advanced Security or GitLab Vulnerability Reports for centralised tracking.
  • Pin third-party CI actions to commit SHAs — the Codecov breach showed that mutable CI scripts are a supply chain attack vector.
Before you move on: can you answer these?

Your Trivy scan reports 47 CVEs in your Node.js Docker image. What is your triage approach?

First, filter by severity — focus on Critical and High with a fix available (ignore-unfixed flag). Second, separate OS-level CVEs (in the base image — fix by updating to a newer base image or using distroless/Alpine) from application dependency CVEs (fix by updating package.json). Third, check if the vulnerable code path is actually reachable in your application — some CVEs in libraries your code never calls have no real impact. Prioritise: Critical CVEs with exploits in the wild → Critical CVEs with fix available → High CVEs. Create tickets for Medium/Low with no urgency.

What is the difference between SAST and DAST, and when would you use each in a pipeline?

SAST (Static) analyses source code without running the application — catches code-level bugs (injection, insecure functions, hardcoded secrets) early in the pipeline, fast. DAST (Dynamic) runs against a live application by sending HTTP requests and observing responses — catches runtime issues (authentication bypasses, misconfigured headers, server-side logic bugs) that require the app to be running. Use SAST on every PR (fast, no infrastructure needed). Use DAST in a staging environment after deploy (slower, requires a running app). SAST catches what you wrote; DAST catches how it behaves.

A developer argues that security scanning is slowing down their pipeline too much. How do you respond?

Acknowledge the concern — slow pipelines do get disabled. Then diagnose: (1) Are scans running sequentially instead of in parallel? (2) Is the dependency cache being rebuilt every run? (3) Are we scanning the full repo on every commit instead of just changed files? Fix the implementation first. If scanning genuinely cannot be fast enough, apply incremental scanning (changed files only for SAST), run expensive scans only on merge to main (not on every PR commit), and use asynchronous scanning (non-blocking) with a separate PR check for slower deep scans. Never remove scanning — adjust the implementation.

From the books

The DevSecOps Handbook (Gene Kim / John Willis, IT Revolution)

Part IV: The Third Way — Continual Learning and Experimentation

Covers integrating security into the Three Ways of DevOps — flow, feedback, and continuous learning. Chapter on security scanning pipelines is directly applicable.

Alice and Bob Learn Application Security (Tanya Jain, Wiley)

Practical application security guide covering SAST, DAST, threat modelling, and secure code review. One of the most accessible security books for developers.

🧠Mental Model

💡 Analogy

Airport security — multiple checkpoints, each catching different threats

⚡ Core Idea

No single scanner catches everything. SAST finds vulnerable code patterns. SCA finds vulnerable libraries. Container scanning finds vulnerable OS packages. Secret scanning finds leaked credentials. You need all four, layered, running automatically on every code change.

🎯 Why It Matters

The cost and blast radius of a security vulnerability grow exponentially the later they are found. A SQL injection bug found by SAST in a PR review is a 30-minute fix. The same bug found in production after a breach is a regulatory investigation, customer notification, and months of remediation.

Ready to see how this works in the cloud?

Switch to Career Paths for structured paths (e.g. Developer, DevOps) and provider-specific lessons.

View role-based paths

Sign in to track your progress and mark lessons complete.

Discussion

Questions? Discuss in the community or start a thread below.

Join Discord

In-app Q&A

Sign in to start or join a thread.