Skip to main content
Back to Insights
Security

Shifting Left on Security: A Practical DevSecOps Checklist

Infraxiom5 min readMarch 17, 2026

Security tooling is cheap; building a culture where engineers care about security outputs is not. Here's the checklist we use when embedding security into a new CI/CD pipeline.

The tooling isn't the hard part

"Shift left" — the idea that security checks should happen earlier in the development lifecycle, ideally before code ever reaches production — has been mainstream advice for years. The tooling to implement it is cheap, widely available, and well-documented.

The hard part is making the output of that tooling matter to the engineers who build and ship the code. A security scan that produces 2,000 findings gets ignored. A pipeline gate that blocks every deploy eventually gets bypassed. Neither of those is security; they're theatre.

This checklist reflects what we actually implement when we embed security into a CI/CD pipeline — and more importantly, why each item is there.

Pre-commit: catch the cheap stuff early

Secret scanning. The number one source of credential leaks is developers accidentally committing API keys, tokens, or passwords to Git. `git-secrets`, `gitleaks`, or Infisical's CLI can run as a pre-commit hook and block the commit before it reaches the remote. This is a five-minute setup with a high return.

IaC scanning. If your team writes Terraform, Bicep, or CloudFormation, run `tfsec`, `checkov`, or `terrascan` against infrastructure changes before they're applied. Misconfigurations — open security groups, public S3 buckets, unencrypted storage — are far cheaper to catch in a PR than after deployment.

Neither of these requires changing your pipeline. They run on the developer's machine. Make them part of the project's standard setup.

In the CI pipeline: automatic, not advisory

SAST (Static Application Security Testing). Tools like Semgrep, Bandit (Python), or CodeQL scan your source code for known vulnerability patterns — SQL injection, insecure deserialization, hardcoded credentials in code (as opposed to config). Run these on every PR. The key is to configure a baseline and only alert on new issues introduced by the current change — otherwise you're surfacing a backlog of historical issues on every PR, which leads to alert fatigue.

Container image scanning. If you're building Docker images, scan them before they're pushed to your registry. `Trivy` is the tool we use most — it's fast, accurate, and integrates cleanly with GitHub Actions, GitLab CI, and Jenkins. Fail the build on critical or high CVEs in your own code layers; treat base image CVEs as warnings until your base image upgrade cycle handles them.

Dependency auditing. `npm audit`, `pip-audit`, `bundler-audit` — most language ecosystems have a native tool for checking your dependencies against known vulnerability databases. This belongs in every pipeline and takes seconds to run.

The failure mode here is setting all of these to "warn only" so they don't block anything. Pick your threshold and hold to it. Our default: block on critical, warn on high, ignore informational.

At deployment: environment-aware checks

DAST (Dynamic Application Security Testing). Tools like OWASP ZAP or Nuclei run against a running application — they test it the way an attacker would, by sending malicious inputs and observing responses. Run these against your staging environment after deployment, before promotion to production. DAST finds things SAST misses: runtime configuration issues, exposed admin interfaces, improper redirects.

Infrastructure compliance scanning. After infrastructure changes are applied, verify the resulting state matches your compliance baseline. `aws-config`, Azure Policy, and GCP Security Command Center can all be queried programmatically. Include a compliance check in your deploy pipeline so a misconfigured resource doesn't stay misconfigured for long.

The cultural piece

Tools run in pipelines, but security decisions are made by humans. A few things that make the tooling actually work:

Keep findings actionable. A finding should tell an engineer what the problem is, what the risk is, and what to do about it. Tools that report "HIGH: CVE-2024-XXXX" with no remediation guidance don't improve security — they improve frustration.

Assign ownership. Security findings without a clear owner get ignored. Your pipeline should route findings to the team responsible for the affected service, not to a central security backlog that no one watches.

Track the trend, not just the count. The number of open findings at any point is less important than whether that number is going up or down over time. A team that is consistently reducing their finding count has a healthy security practice regardless of where they started.

Security is an engineering discipline, not a compliance checkbox. The checklist above is a starting point — but the goal is a team that thinks about security because they understand the risks, not because a gate forced them to.

Questions about your infrastructure? We’re happy to talk through it.

Request a consultation