DevSecOps: Security in the SDLC

Security can no longer be a gate at the end — it has to live in every stage of how software is built. This is DevSecOps: shift-left, automate the checks, make security everyone's job. We walk the secure SDLC stage by stage — threat modeling, pre-commit hooks, SAST/SCA/secret scanning in CI, IaC and container scanning, DAST, and signing/policy/monitoring at runtime. Then the part that makes it real: security gates that block the right findings, and the culture and metrics that keep it alive.

Shift left · automate · gate the right findings

Shift left — security as a checkpoint is dead

For decades, security was a checkpoint at the end — a pentest the week before launch, findings nobody had time to fix. That model is broken: a bug found in design costs a conversation; the same bug found in production costs an incident. DevSecOps is the response — move security earlier and everywhere, automate it into the pipeline, and make it part of how software is built rather than a thing done to it.

🔑 Key idea: The economics drive everything: the cost to fix a flaw rises sharply the later it's found — orders of magnitude from design to production. "Shift left" means catching it where it's cheap. But the modern phrase is "shift everywhere": security checks at design, in the IDE, on commit, in CI, before deploy, and at runtime — each stage catching what the previous missed.

The secure SDLC — security at every stage

Picture the software lifecycle as a pipeline of stages, and bolt a security activity onto each. None alone is sufficient; together they form defence in depth across the whole process.

StageSecurity activityWhat it catches
DesignThreat modeling, security design reviewfind design flaws before any code exists
DevelopSecure coding, IDE plugins, pre-commit hooksstop bugs and secrets at the keyboard
Build / CISAST, SCA, secret scanning, SBOMcatch code & dependency flaws on every push
TestDAST, IaC & container scanningtest the running app and its infrastructure
ReleaseArtifact signing, policy-as-codeonly verified, compliant builds ship
OperateRuntime protection, monitoring, CSPMdetect & feed findings back to the start
🔑 Key idea: This is the spine of DevSecOps: a security activity at every stage, each one automated and fast enough not to slow delivery. The loop is the point — what runtime monitoring finds becomes the next design's threat model. Security stops being a phase and becomes a property of the pipeline.

Design — threat modeling before code

The cheapest bug to fix is one that never gets built. The design stagethreat modeling and security design review — finds whole classes of flaw before a line of code exists.

ActivityHowOutput
Diagram the systemData-flow diagram + trust boundariessee where untrusted data crosses into trusted zones
Enumerate threatsSTRIDE per elementSpoofing, Tampering, Repudiation, Info-disclosure, DoS, Elevation
Write abuse cases"As an attacker, I want to…"the inverse of user stories
Decide mitigationsPer threat: accept / mitigate / design outbecomes the security requirements
A security design review is the same idea applied to a proposed architecture: walk the diagram, ask "what could go wrong at each trust boundary," and catch the missing-authz or SSRF-by-design issues from the Secure Code Review series before they're written. Pair it with our threat-modeling deep-dive.

Develop — secure coding & pre-commit hooks

At the develop stage, the goal is to stop problems at the keyboard: secure-coding standards, security linters in the IDE, and — the highest-leverage automation — pre-commit hooks that refuse to let a secret or obvious flaw be committed at all.

bash
# .pre-commit-config.yaml — runs on every `git commit`, locally
repos:
  - repo: https://github.com/gitleaks/gitleaks
    hooks: [{ id: gitleaks }]            # block committed secrets
  - repo: https://github.com/returntocorp/semgrep
    hooks: [{ id: semgrep, args: ["--config","p/secrets","--error"] }]
  - repo: https://github.com/pre-commit/pre-commit-hooks
    hooks: [{ id: detect-private-key }, { id: check-added-large-files }]
🔑 Key idea: Pre-commit hooks are the earliest automated gate — they run on the developer's machine before the code ever leaves it, so a leaked API key or a flagged pattern is caught in seconds, not in a breach. Pair them with secure-coding guidelines (the checklist from the Secure Code Review series) and IDE security plugins so the feedback is instant and in-context.

CI — SAST, SCA & secret scanning

The heart of DevSecOps is the CI pipeline: on every push and pull request, automatically scan the code (SAST), the dependencies (SCA), and for secrets — and produce a software bill of materials (SBOM).

bash
# .github/workflows/security.yml (sketch) — runs on every PR
jobs:
  appsec:
    steps:
      - uses: actions/checkout@v4
      - run: semgrep ci                       # SAST (diff-aware)
      - run: osv-scanner -r .                  # SCA — vulnerable deps
      - run: gitleaks detect --no-git -v       # secrets
      - run: syft . -o cyclonedx-json > sbom.json   # SBOM
      # gate: fail the build on NEW high-severity findings
🔑 Key idea: This is the SAST tooling from the Secure Code Review series, wired into the pipeline as an automatic, diff-aware gate. Add SCA (most breaches start with a known-vulnerable dependency) and secret scanning, and generate an SBOM so that when the next Log4Shell drops, you can answer "are we affected?" in minutes.

IaC & container scanning

Modern apps ship as infrastructure-as-code and container images — and those are attack surface too. A public S3 bucket or a root-running container with a vulnerable base image is a finding the same as a SQLi. Scan them in the same pipeline.

TargetToolsWhat it catches
IaC scanningcheckov, tfsec, terrascanpublic buckets, open security groups, no encryption
Container imagestrivy, grypevulnerable OS packages & libs in the image
Dockerfile / confighadolint, trivy configrunning as root, secrets in layers, :latest tags
K8s policyOPA/Gatekeeper, Kyvernoenforce 'no privileged pods', signed images only
🔑 Key idea: "Security as code" extends to the infrastructure. checkov on your Terraform catches the misconfigured bucket before it's deployed; trivy on your image catches the vulnerable base before it's pushed; an admission controller refuses to run anything non-compliant. Cloud misconfiguration is one of the most common breach causes — and one of the most automatable to prevent.

Test — DAST against the running app

SAST reads the code; DAST (Dynamic Application Security Testing) attacks the running app from the outside, like a scanner-driven pentest. It catches things static analysis can't — runtime config, auth flows, and issues that only appear when the whole system is assembled.

python
# DAST against a deployed staging build, in the pipeline:
zap-baseline.py -t https://staging.app.example -r zap.html   # OWASP ZAP
nuclei -u https://staging.app.example -severity high,critical # templated checks
# API: import the OpenAPI spec and fuzz each endpoint (ZAP / schemathesis)
DAST is slower and noisier than SAST and needs a running target, so it usually runs against a staging deploy (nightly or pre-release) rather than on every commit. The two are complementary: SAST finds the vulnerable code path, DAST confirms it's actually reachable and exploitable in the deployed system. IAST instruments the running app to combine both.

Release & operate — trust and detect

At release and in operation, the controls shift from finding bugs to ensuring only trusted things run and detecting attacks against what's live.

ControlToolingPurpose
Artifact signingcosign / Sigstoreonly builds you produced get deployed
Policy-as-codeOPA, admission controllersblock non-compliant deploys automatically
WAF / RASPEdge filtering, in-app protectionmitigate while a fix is shipped
CSPMCloud posture managementcontinuous drift detection in the cloud
Monitoring / SIEMLogs, detections, alertingcatch what got through — feed it back
🔑 Key idea: Runtime is the last line and the feedback source. Signing and policy-as-code ensure provenance; a WAF buys time while you patch; CSPM catches the bucket someone made public after deploy; and monitoring closes the loop — every real incident becomes an input to the next threat model. Security as a cycle, not a line.

Security gates — block the right things

All this scanning is noise unless something acts on it. Security gates decide what blocks the pipeline and what only warns — and getting that balance right is the difference between a program people respect and one they bypass.

🔑 Key idea: Two rules keep gates survivable. Be diff-aware: block on new findings, not the legacy backlog (baseline the existing mountain). Be risk-based: a new critical or a leaked secret blocks the merge; a low-severity style issue annotates and tracks. A gate that fails the build for everything gets disabled within a week; a gate that blocks only the genuinely dangerous, with a clear path to fix, becomes trusted infrastructure.
The fastest way to kill a DevSecOps program is a wall of false positives that breaks every build. Tune ruthlessly, baseline aggressively, and make the gate's verdict obviously correct — developer trust is the scarcest resource and the hardest to rebuild.

Culture & metrics — making it stick

DevSecOps is as much culture as tooling. The "Sec" in the middle means security is everyone's job, not a separate team's veto — and you steer it with metrics, not vibes.

LeverWhat it isWhy it matters
Security championsA trained dev embedded in each teamscale a small security team across many
Blameless cultureFix the system, not the personpeople report issues instead of hiding them
MTTRMean time to remediateare we fixing fast, or just finding?
Coverage% of repos/pipelines with the checksis the program actually everywhere?
Escaped defectsBugs found in prod vs in CIis shift-left actually working?
🔑 Key idea: Tools find bugs; culture decides whether they get fixed. Security champions embed expertise in every team so security scales without a bottleneck; a blameless stance keeps people reporting; and a few honest metrics — MTTR, coverage, escaped defects — tell you whether the program is working or just generating dashboards. Measure remediation, not just detection.

Closing — security as a property of the pipeline

DevSecOps is one idea applied relentlessly: security at every stage, automated, owned by everyone, with gates that block the dangerous and a culture that fixes what's found. Design catches the architecture flaws, pre-commit and CI catch the code and dependency bugs, IaC/container scanning catches the infrastructure, DAST catches the runtime, and signing/policy/monitoring keep production honest — each stage a net under the last.

But a pipeline that finds and even fixes bugs still leaves one question unanswered: did the fix actually work? A finding marked "remediated" in a ticket is not the same as a vulnerability proven gone. Closing that gap — retesting and verification — is what turns a stream of findings into measurable risk reduction, and it's where the lifecycle completes.

Next — Vulnerability Management: Retesting & Verification. The remediation lifecycle, how to prove a fix holds (not just that a ticket was closed), regression and bypass checks, risk acceptance, and the metrics that show risk actually going down.

Reactions

Related Articles