In 2017, Equifax let through a known flaw in an Apache Struts dependency. The fix had existed for two months: the breach exposed the data of 147 million people and cost up to 700 million dollars in penalties. A simple dependency scan in CI would have flagged it. Four years later, Log4Shell (CVE-2021-44228) hit millions of Java applications: teams already scanning their dependencies identified and fixed it within hours, the others audited by hand for weeks.
This lesson explains the shift-left principle: why a problem costs more the later it is found, and how to gradually move tests, security and infrastructure validation to the start of the cycle. It is for developers, ops and quality or security leads who are discovering DevSecOps and want to understand this principle before choosing tools.
What you will learn
- Define the shift-left principle and trace its origin
- Explain why the cost of fixing grows over time
- Tell apart the three dimensions of shift-left: tests, security, infrastructure
- Combine the human practices (threat modeling, review checklist, security champions) with the tools
- Implement a gradual approach, from pre-commit hooks to IaC scanning
- Avoid the classic pitfalls: alert fatigue, excessive blocking, no shift-right
What is shift-left?
Shift-left means detecting a problem as early as possible in the development cycle, because it costs less to fix there. Instead of waiting for the end of the project to test and audit, these activities are moved ("shift") towards the beginning ("left") of the process. It is the founding principle of DevSecOps.
In practice, you write tests before or during development, you scan the code on every commit rather than once a month, you check dependencies automatically rather than by hand before release, and you validate infrastructure before provisioning it rather than in production.
Shift-left is not entirely new: Test-Driven Development (TDD, writing the test before the code) dates from the 2000s. What changed is the systematic application of the principle to every aspect of development: functional, security, infrastructure, compliance.
Why "left"?
The term comes from drawing the development cycle on a horizontal timeline, where time flows from left to right. In the approach inherited from the waterfall model, security tests arrive just before release: a dedicated team audits under schedule pressure, and whatever it finds is expensive both to rewrite and to postpone.
Shift-left reverses this logic by moving checks to the code phase, or even the design phase. It does not remove the final checks: it drastically reduces what they find, because the checks happened earlier. The term was popularised by Larry Smith in 2001 in Dr. Dobb's Journal, about functional testing; its extension to security came with the rise of DevSecOps from 2015.
Why does a late fix cost more?
A problem found late costs more to fix, and the gap widens at every stage passed. The table gives commonly quoted orders of magnitude, to be read as a trend and not as a measurement: the historical multipliers, often attributed to an "IBM Systems Sciences Institute", have never been traced to a verifiable study, but the direction of the gap is widely agreed.
| Detection phase | Order of magnitude | Why | Concrete example |
|---|---|---|---|
| IDE, pre-commit | 1 | The developer fixes it immediately, fresh context | 5 minutes to remove a hard-coded secret |
| CI, pull request | A few times more | Review, tests to re-run | 30 minutes: understand the alert, fix, push again |
| Staging | Ten times more | Full test cycle, possible rollback | 2 hours: investigation, fix, new test cycle |
| Production | A hundred times more | Incident, rollback, communication, post-mortem | 1 to 2 days of a mobilised team |
| After a compromise | Beyond comparison | Forensics, fines, reputation, legal | Weeks to months: Equifax, up to 700 M$ |
What drives the cost up
Five factors explain this growth, and knowing them helps justify shift-left to management that thinks in deadlines and budget. Lost context first: the more time passes, the more the developer has to reconstruct what they had in mind. The knock-on effect next: code written on top of the bug depends on it, and fixing it can break what follows.
Coordination adds up in production, where the fix mobilises development, operations, security and communication. Then come the business impact on users and revenue, and legal obligations: a data breach triggers notification to the regulator and to the people affected, within strict deadlines.
What DORA measures
The DORA State of DevOps 2024 report quantifies the gap between teams: the best performers deploy up to 182 times more often than the lowest, and recover from an incident up to 2,293 times faster. DORA lists "shifting left on security" among the technical capabilities that explain this gap; as early as 2016, its report found that the best-performing teams spent 50% less time fixing security issues. Shift-left is not a brake, it is a measured accelerator.
How much does a data breach cost?
IBM's Cost of a Data Breach 2026 report, run with the Ponemon Institute across 602 organisations hit by a breach, puts the average cost of a data breach at 4.99 million dollars, a record, up 12% in a year. The same report finds that organisations making extensive use of automation and AI in their security save an average of 1.93 million dollars per incident. Shift-left is only part of that automation, but it is its first link: a check that runs on every commit does not depend on an auditor's vigilance.
The three dimensions of shift-left
Shift-left applies to three complementary areas: functional tests, security and infrastructure. Each one brings its own benefits, and their combination produces the best results.
Functional tests
This is "classic" shift-left, the one that gave the concept its name. Historically, a dedicated QA team tested the application once development was "done": developers had switched context, each bug forced a step back, and QA became a bottleneck. Shift-left brings each kind of test closer to the moment the code is written.
| Practice | Description | Benefit | Feedback |
|---|---|---|---|
| TDD | Write the test before the code | Emerging design, guaranteed coverage | Seconds |
| Unit tests | Test each function in isolation | Fast feedback, easy maintenance | Seconds |
| Integration tests | Test interactions between components | Interface problems caught | Minutes |
| Contract tests | Validate the APIs between services | Interface regressions avoided | Minutes |
The key principle: each test runs as early as possible. A 10 ms unit test in the IDE is worth more than a five-minute end-to-end test in CI. The lesson Testing strategies goes deeper into the test pyramid.
Security
This is the heart of DevSecOps: integrating security checks from development onwards instead of leaving them to a final audit. Traditionally, security worked as a gatekeeper: a dedicated team approved or rejected releases just before production, was seen as a brake, and found flaws that had become expensive. Shift-left distributes the checks over the whole cycle.
| Phase | Checks | Tools | What you catch |
|---|---|---|---|
| IDE | Security linters, real-time secrets | Semgrep, Snyk extensions | Dangerous patterns while writing |
| Pre-commit | Secret scanning, format validation | Gitleaks, pre-commit hooks | Secrets before they reach the repository |
| CI/CD | SAST, SCA, IaC scanning | Semgrep, Trivy, Checkov | Vulnerabilities in code and dependencies |
| Build | Image scanning, signing | Trivy, Cosign | Image vulnerabilities, integrity |
The security team does not disappear: it changes role. Instead of approving each release, it defines the rules, maintains the tools and builds the teams' skills. The OWASP Top 10:2025, which replaces the 2021 edition, adds two categories, Software Supply Chain Failures and Mishandling of Exceptional Conditions: the supply chain must be monitored continuously, not audited from time to time. The lesson OWASP Top 10 details each category.
Infrastructure
With Infrastructure as Code (IaC, infrastructure described in versioned files rather than through clicks in a console), infrastructure becomes code, and it must be tested before being applied. Without shift-left, a misconfiguration is found at provisioning time, or in production when an attacker exploits it: a public bucket, a security group open to everything, a container running as root.
| What | When | How | What you catch |
|---|---|---|---|
| Terraform | Before terraform apply | Checkov, OPA | Public buckets, missing encryption, open ports |
| Kubernetes | Before kubectl apply | Kubescape, kube-linter | Root containers, clear-text secrets, missing limits |
| Dockerfiles | Before docker build | Hadolint, Dockle | Unofficial images, root user, useless layers |
| CloudFormation | Before deployment | cfn-lint, Checkov | Non-compliant AWS configurations |
The advantage of IaC is that the same review tools apply to infrastructure: a configuration change goes through a pull request and CI, exactly like an application code change, with the same traceability.
Which part of shift-left stays human?
Tools only cover part of shift-left: the earliest checks are human, and no scanner replaces them. Three practices complete the automated chain, from design to code review, and the last one relies on a role of its own, the security champion.
Model threats before writing code
Threat modeling is the earliest form of shift-left: it identifies attack scenarios during design, when a fix means changing a diagram or an architecture decision. You do it for every significant feature, when integrating an external service, or when data flows change. The lesson Threat modeling with STRIDE gives the method.
Train developers
A developer who does not know a vulnerability will not recognise it in their own code: it is not a matter of skill, but of knowledge passed on. Short, regular sessions, on examples taken from the team's real stack, are worth more than an annual training session soon forgotten. The lesson Training teams in security builds that programme.
Add a security checklist to pull requests
Each pull request can carry a short checklist that any reviewer
applies, without waiting for an expert: no secret in the diff, user input
validated, parameterised SQL queries, authentication checked on new endpoints,
new dependencies justified. GitHub's CODEOWNERS file also adds a designated
reviewer as soon as a sensitive file changes.
That designated reviewer is often a security champion: a developer who keeps their job in the team and carries an extra security responsibility, bridging the gap with the security team. It is neither a full-time expert nor an improvised role: the lesson Security Champions: build and run a programme explains how to turn it into a structured programme.
How do you implement shift-left?
Rollout must be gradual: trying to do everything at once is the best way to frustrate teams and give up. The five steps below go from the most cost-effective check to the most complete, and each one is added once the previous one is accepted by the team.
-
Start with pre-commit hooks
It is the most cost-effective investment: pre-commit hooks run on the developer's machine, before the code reaches the repository. A secret committed by mistake is blocked immediately.
Terminal window pip install pre-commitcd my-projectpre-commit installThen create a
.pre-commit-config.yamlfile at the root:.pre-commit-config.yaml repos:# Secret detection- repo: https://github.com/gitleaks/gitleaksrev: v8.30.1hooks:- id: gitleaks# Formatting and basic checks- repo: https://github.com/pre-commit/pre-commit-hooksrev: v6.0.0hooks:- id: trailing-whitespace- id: end-of-file-fixer- id: check-yaml- id: check-added-large-filesThis file enables Gitleaks and formatting checks. A
revis a tag, and therefore mutable:pre-commit autoupdate --freezereplaces it with the matching commit SHA. The pre-commit framework guide (in French) details the available hooks.Blocking before the commit saves a much heavier clean-up. A committed secret stays in the Git history even after a
git revert, which adds a reverse commit without erasing the old one: all that is left is revoking the secret, then rewriting the history.Keep these hooks fast, under ten seconds or so. Beyond that, developers get into the habit of
git commit --no-verify, the option that skips every pre-commit hook, and the check no longer protects anything. -
Add SAST to CI
Then add static analysis (SAST, analysing source code without running it) to each pull request. The job runs in the official Semgrep image, pinned by digest: a tag can be rewritten, a digest never.
.github/workflows/security.yml name: Security Scanon: [pull_request]permissions: {} # nothing by default, each job declares its needsjobs:sast:runs-on: ubuntu-24.04permissions:contents: readsecurity-events: write # required to upload the SARIF reportcontainer:image: semgrep/semgrep:1.178.0@sha256:32e459968daabe7ab86968184a29109b9564aa00392401156f9788452b42786bsteps:- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1with:persist-credentials: false- run: semgrep scan --config p/python --config p/owasp-top-ten --error --sarif --output semgrep.sarif- name: Upload the SARIF reportif: always() # upload even when the scan failed the jobuses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4.38.2with:sarif_file: semgrep.sarifChoose the rules based on your language: on an obvious Flask SQL injection, the generic
p/security-auditruleset reports nothing, whilep/pythonandp/owasp-top-tencatch it. The lesson Security testing gives the full measurement. Then refine according to the false positives you meet. -
Analyse dependencies (SCA)
Software composition analysis (SCA) detects known vulnerabilities (CVEs, public flaw identifiers) in third-party libraries, which make up most of the code of a modern application. The job below runs Trivy from its image pinned by digest: it fails on a critical vulnerability and only reports the high ones.
sca:runs-on: ubuntu-24.04permissions:contents: readcontainer:image: aquasec/trivy:0.75.0@sha256:af6acf9a6b85dfe389a1941505c0ce9efef52a4719635e1a962f022a3d855daasteps:- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1with:persist-credentials: false- run: trivy fs --severity CRITICAL --exit-code 1 . # fails the job- run: trivy fs --severity HIGH --exit-code 0 . # reports without blockingThis pinning is not excessive caution. In March 2026, Trivy's release automation was compromised (CVE-2026-33634): a tampered v0.69.4 release was published, then
0.69.5,0.69.6andlatestimages on Docker Hub. A checksum file downloaded with the release does not protect against a compromised release; a digest chosen after review freezes the exact binary. -
Scan the IaC
If you use Terraform, CloudFormation or Kubernetes, add a configuration scan with Checkov, also run from its pinned image.
iac:runs-on: ubuntu-24.04permissions:contents: readcontainer:image: bridgecrew/checkov:3.3.22@sha256:617c76e3f9b1f7907ebca9abb6b9d746844edcb48e9bd775e4692c69c1c6ac47steps:- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1with:persist-credentials: false- run: checkov --directory terraform/ --framework terraform --compact --skip-check CKV_AWS_123,CKV_AWS_456Document each rule excluded with
--skip-checkin a comment or a ticket: an exclusion without justification becomes debt. -
Measure and iterate
Shift-left is a practice that improves, not a one-off project. Track four metrics every month and tune the rules accordingly; the targets in the table are starting points, not standards.
Metric What it shows Starting target Vulnerabilities per phase Shift-left effectiveness Most in pre-commit and CI, fewest in production Mean time to fix Team responsiveness Under 24 h for critical False positive rate Rule quality Under 10% Bypass rate Team buy-in Under 5%
Why warn before blocking?
A check that blocks from day one gets bypassed before it has proved its worth. The jobs above show the target state, but they are introduced in two stages: warning mode, which shows the alerts without stopping the job, then blocking mode, once the noise is gone.
For Semgrep, it all comes down to the --error option. Without it,
semgrep scan exits with code 0 even when it finds a result: the job stays
green and the team sees the alerts without being blocked. With it, the scan
exits with code 1 as soon as a result remains, and the job fails. Measured
with Semgrep 1.178.0 on a deliberate Flask SQL injection: 0 without the
option, 1 with it. Start without it, and add it once the false positives are
dealt with.
Trivy applies the same logic within a single job: --exit-code 1 on
critical fails the job, --exit-code 0 on high only reports. Then lower
that blocking threshold as the team works through its alerts, rather than
blocking everything from the start.
What remains is to make the failure readable. Uploading the SARIF report (a
standard format for analysis results) to GitHub's Security tab carries
if: always(). Without that condition, the failed scan would skip the following
steps, and the developer would see a red job without the details of the
results, precisely when they need them.
Which pitfalls should you avoid?
A badly introduced shift-left can do more harm than good. The table links each pitfall to the symptom that gives it away and to its fix; the most frequent is the first one, blocking everything from the start, which pushes teams towards bypassing.
| Pitfall | Symptom | Cause | Solution |
|---|---|---|---|
| Blocking everything | Permanently red pipeline, frustrated developers | Rules too strict from the start | Block the critical, alert on the rest, tighten gradually |
| Ignoring false positives | 500 alerts a day that everyone ignores | Badly configured tools | Documented exclusions, each one justified |
| Tools without training | Bypasses with --no-verify | Rules imposed without explanation | Train, explain the why, involve developers |
| Shift-left without shift-right | False sense of security | Focus on CI only | Add DAST in staging and production monitoring |
| No owner | Alerts that linger | Unclear responsibility | One owner per alert, in the ticket flow |
| No metrics | No way to know whether it works | No tracking | Measure vulnerabilities per phase, delays, false positives |
Alert fatigue
The most insidious pitfall is alert fatigue: when developers receive hundreds of alerts a day, they end up ignoring everything, real critical flaws included. Four steps prevent it: prioritise (only the critical blocks), give context (a CVE in a test dependency matters less than in production), deduplicate, and make each alert lead to a clear action.
A scanner only gets adopted if it meets four criteria, summarised in the table: a tool that misses one ends up bypassed. The most decisive is precision: faced with 500 alerts of which 450 are false, the team soon stops reading the other 50. Fewer rules that are reliable are better.
| Criterion | Target | If missed |
|---|---|---|
| Speed | A few seconds in the IDE, under 5 minutes in CI | Bypassed or disabled |
| Precision | Under 10% false positives | Alerts ignored |
| Actionable | Clear explanation and suggested fix | Frustration, escalation |
| In context | In the IDE or the pull request, not in a separate report | Feedback never read |
Shift-left or shift-right?
Shift-left has a natural complement, shift-right, which extends checks to the end of the cycle, that is, in production. Some problems only appear in real conditions: real load, interactions with third-party systems, emerging behaviours at large scale, or a zero-day attack no scan covers.
| Practice | Description | Goal |
|---|---|---|
| Feature flags | Enable a feature for part of the users | Limit the impact of a bug |
| Canary releases | Deploy to a small fraction before the rest | Detect before spreading |
| Blue/green | Two identical environments, instant switch | Immediate rollback |
| Chaos engineering | Inject deliberate failures | Validate resilience |
| Security monitoring | Detect abnormal behaviour in real time | Spot attacks |
The two approaches form a continuum: shift-left reduces the number of problems reaching production, shift-right detects those that get through anyway and limits their impact. The best-performing teams do both.
Key points
- Shift-left moves tests, security and infrastructure validation to the start of the cycle.
- A problem costs more the later it is found; the quoted multipliers are orders of magnitude.
- Three dimensions: functional tests, security, infrastructure.
- The earliest checks are human: threat modeling, review checklist, security champions.
- Start with pre-commit hooks, the most cost-effective check, and keep them under ten seconds or so.
- Run SAST in warning mode first, then add
--errorto block. - Pin security tools by digest: Trivy itself was tampered with in March 2026.
- Do not block everything: the critical blocks, the rest alerts.
- Add shift-right: monitoring, progressive deployments, chaos engineering.
Knowledge check
Check that the essentials of this lesson are in place. The questions only cover what has just been explained here.
Knowledge check
Check what you have learned with this interactive quiz
How it works
- The timer starts when you click Start
- Multiple choice, true/false and short answer questions
- You can move between questions
- Detailed results are shown at the end
Starts the quiz and the timer
Review
(0/0)Score by domain
A domain groups several guides and gets several questions, so its score is more reliable than a per-topic score, which often rests on a single question.
Summary
Strengths
No topic passed at 80% on at least two questions yet.
Weak areas
No topic below the pass mark.
Recommended next
Hints before you try again?
Continue the course: Shared responsibility: who does what in security
A new full quiz with random questions
Work again only on the questions you missed
FAQ: frequently asked questions
These short answers cover the questions that come up most often about shift-left: its cost, how to roll it out without blocking teams, and false positives. Each one reads on its own.
--no-verify. Next comes alert fatigue: too many untriaged false positives, and real critical flaws end up ignored with the rest. Finally, practising shift-left without shift-right gives a false sense of security: dynamic tests and production monitoring remain essential.CODEOWNERS on sensitive files, completes the scanners without waiting for an expert.--error, Semgrep exits with code 0) while you remove the noise, then make it blocking. Every exclusion gets documented: without a justification, it becomes debt.