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.
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.
| Stage | Security activity | What it catches |
|---|---|---|
| Design | Threat modeling, security design review | find design flaws before any code exists |
| Develop | Secure coding, IDE plugins, pre-commit hooks | stop bugs and secrets at the keyboard |
| Build / CI | SAST, SCA, secret scanning, SBOM | catch code & dependency flaws on every push |
| Test | DAST, IaC & container scanning | test the running app and its infrastructure |
| Release | Artifact signing, policy-as-code | only verified, compliant builds ship |
| Operate | Runtime protection, monitoring, CSPM | detect & feed findings back to the start |
Design — threat modeling before code
The cheapest bug to fix is one that never gets built. The design stage — threat modeling and security design review — finds whole classes of flaw before a line of code exists.
| Activity | How | Output |
|---|---|---|
| Diagram the system | Data-flow diagram + trust boundaries | see where untrusted data crosses into trusted zones |
| Enumerate threats | STRIDE per element | Spoofing, Tampering, Repudiation, Info-disclosure, DoS, Elevation |
| Write abuse cases | "As an attacker, I want to…" | the inverse of user stories |
| Decide mitigations | Per threat: accept / mitigate / design out | becomes the security requirements |
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.
# .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 }]
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).
# .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
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.
| Target | Tools | What it catches |
|---|---|---|
| IaC scanning | checkov, tfsec, terrascan | public buckets, open security groups, no encryption |
| Container images | trivy, grype | vulnerable OS packages & libs in the image |
| Dockerfile / config | hadolint, trivy config | running as root, secrets in layers, :latest tags |
| K8s policy | OPA/Gatekeeper, Kyverno | enforce 'no privileged pods', signed images only |
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.
# 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)
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.
| Control | Tooling | Purpose |
|---|---|---|
| Artifact signing | cosign / Sigstore | only builds you produced get deployed |
| Policy-as-code | OPA, admission controllers | block non-compliant deploys automatically |
| WAF / RASP | Edge filtering, in-app protection | mitigate while a fix is shipped |
| CSPM | Cloud posture management | continuous drift detection in the cloud |
| Monitoring / SIEM | Logs, detections, alerting | catch what got through — feed it back |
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.
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.
| Lever | What it is | Why it matters |
|---|---|---|
| Security champions | A trained dev embedded in each team | scale a small security team across many |
| Blameless culture | Fix the system, not the person | people report issues instead of hiding them |
| MTTR | Mean time to remediate | are we fixing fast, or just finding? |
| Coverage | % of repos/pipelines with the checks | is the program actually everywhere? |
| Escaped defects | Bugs found in prod vs in CI | is shift-left actually working? |
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.