惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Stack Overflow Blog
Stack Overflow Blog
Y
Y Combinator Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
M
MIT News - Artificial intelligence
GbyAI
GbyAI
A
About on SuperTechFans
T
The Blog of Author Tim Ferriss
雷峰网
雷峰网
Blog — PlanetScale
Blog — PlanetScale
J
Java Code Geeks
IT之家
IT之家
Microsoft Azure Blog
Microsoft Azure Blog
V
V2EX
爱范儿
爱范儿
N
Netflix TechBlog - Medium
U
Unit 42
博客园 - 三生石上(FineUI控件)
WordPress大学
WordPress大学
博客园 - 叶小钗
G
Google Developers Blog
Jina AI
Jina AI
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
腾讯CDC

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
DevSecOps in Practice: Tools That Actually Catch Vulnerab...
Hariharan · 2026-04-26 · via DEV Community

Hariharan

If you've followed along from Part 1, we have built five separate scanning
workflows. This final part replaces them with a single unified pipeline —
one YAML file, one run, everything in the right order.

The pipeline structure
The five individual workflow files are deleted and replaced with one:
.github/workflows/devsecops-pipeline.yml

name: DevSecOps Pipeline

on:
  push:
    branches: ["**"]
  pull_request:
    branches: ["**"]

jobs:

  secret-scan:
    name: Secret Scanning - Gitleaks
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Run Gitleaks
        uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  sast:
    name: SAST - Bandit
    runs-on: ubuntu-latest
    needs: secret-scan
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      - name: Install Bandit
        run: pip install bandit
      - name: Run Bandit
        run: bandit -r app.py --severity-level high -f json -o bandit-report.json
      - name: Upload Report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: bandit-report
          path: bandit-report.json

  sca:
    name: SCA - pip-audit
    runs-on: ubuntu-latest
    needs: secret-scan
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      - name: Install pip-audit
        run: pip install pip-audit
      - name: Run pip-audit
        run: pip-audit -r requirements.txt -f json -o pip-audit-report.json
      - name: Upload Report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: pip-audit-report
          path: pip-audit-report.json

  iac:
    name: IaC - Checkov
    runs-on: ubuntu-latest
    needs: secret-scan
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      - name: Install Checkov
        run: pip install checkov
      - name: Run Checkov
        run: checkov -d terraform/ -o json > checkov-report.json
      - name: Upload Report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: checkov-report
          path: checkov-report.json

  container-scan:
    name: Container Scan - Trivy
    runs-on: ubuntu-latest
    needs: [sast, sca, iac]
    steps:
      - uses: actions/checkout@v4
      - name: Build Docker image
        run: docker build -t devsecops-demo:${{ github.sha }} .
      - name: Run Trivy
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: devsecops-demo:${{ github.sha }}
          format: json
          output: trivy-report.json
          severity: CRITICAL,HIGH
          exit-code: 1
      - name: Upload Report
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: trivy-report
          path: trivy-report.json

Enter fullscreen mode Exit fullscreen mode

The logic is deliberate:

  1. Secret scanning runs first. If credentials are found in the code, nothing else runs. There's no value in scanning code that's already compromised.
  2. SAST, SCA, and IaC run in parallel after secrets pass. These are independent checks — no reason to run them sequentially. Running in parallel keeps the pipeline fast.
  3. Container scanning runs last. It only runs if the three parallel scans all pass. If the code has known vulnerabilities, there's no point building and scanning the image.

What the pipeline run looks like

Secret Scanning passed — no leaks detected. SAST, SCA, and IaC all failed
because the demo app is deliberately broken. Container Scan was skipped.
That skipped Trivy stage is worth explaining. It's not a failure — it's the pipeline working correctly. GitHub Actions skips a job when its dependencies fail. Trivy needed Bandit, pip-audit, and Checkov to all pass before it would run. They didn't, so it didn't. There's no point scanning a container image built from code you already know is vulnerable.
In a real project where the code is clean, all five stages would run and the pipeline would either pass completely or fail at Trivy if the image has CVEs.

What this pipeline catches
Across the five parts of this series, the pipeline found:

  1. Secrets — AWS access keys hardcoded in app.py, caught before commit and at push time
  2. Code vulnerabilities — SQL injection, eval() on user input, debug=True in Flask, all flagged by Bandit
  3. Vulnerable dependencies — 37 known CVEs across 6 packages in requirements.txt, caught by pip-audit
  4. Infrastructure misconfigurations — 18 failed Checkov checks including a public S3 bucket, unencrypted EBS, and no IMDSv2 enforcement
  5. Container CVEs — 1,747 vulnerabilities in the Docker image, 185 of them CRITICAL, caught by Trivy

None of this required a security expert. Each tool is open source, free,
and wired into a standard GitHub Actions workflow.

What this pipeline doesn't catch

  1. DAST — Dynamic Application Security Testing scans a running application for vulnerabilities. Nothing here does that. Tools like OWASP ZAP fill this gap.
  2. Runtime security — once the container is running in production, nothing here monitors it. Tools like Falco watch for suspicious behaviour at runtime.
  3. Secrets in git history — Gitleaks scans current files and recent commits. A secret committed years ago and deleted may still be in history.
  4. Logic flaws — no static analysis tool catches business logic vulnerabilities. Those require manual review.

The repo
Everything built across this series is at
https://github.com/pkkht/devsecops-demo — the vulnerable Flask app, the Terraform, the Dockerfile, and all the GitHub Actions workflows.
Clone it, run the pipeline, break things deliberately, and see what gets caught.