Shift-Left Security in the Pipeline
Moving security controls into the delivery pipeline: which scanners belong where, how to keep findings actionable, and how to avoid the alert fatigue that kills the programme.
Shifting security left means finding problems while the developer still has the context to fix them cheaply. The economics are simple: a vulnerability caught in the editor costs minutes, in code review costs an hour, and in production costs an incident.
The failure mode is equally simple: bolt on five scanners, generate four thousand findings, block every build, and watch the organization disable the whole thing within a month.
Which control belongs at which stage
flowchart LR
A["Editor<br/><small>seconds</small>"] --> B["Pre-commit<br/><small>seconds</small>"]
B --> C["Pull request<br/><small>minutes</small>"]
C --> D["Build<br/><small>minutes</small>"]
D --> E["Pre-deploy<br/><small>minutes</small>"]
E --> F["Runtime<br/><small>continuous</small>"]
A -.- A1["IDE security linting"]
B -.- B1["Secret detection"]
C -.- C1["SAST · IaC scanning · dependency review · policy checks"]
D -.- D1["Container image scan · SBOM generation · artifact signing"]
E -.- E1["Signature and provenance verification · admission policy"]
F -.- F1["DAST · runtime detection · continuous posture scanning"]
| Control | What it finds | False positive tendency | Should block? |
|---|---|---|---|
| Secret detection | Committed credentials | Low | Yes, always |
| SAST | Code-level vulnerability patterns | High without tuning | High severity only |
| SCA / dependency scanning | Known CVEs in dependencies | Medium — reachability matters | Critical/high with a fix available |
| IaC scanning | Insecure infrastructure definitions | Low | Yes, for security-relevant rules |
| Container scanning | OS and library CVEs in the image | Medium — many are unreachable | Critical, with a base image update available |
| DAST | Runtime-exposed vulnerabilities | Medium | No — run against staging, ticket the findings |
| License scanning | Non-compliant dependency licences | Low | Yes, for prohibited licences |
Secret detection deserves special treatment
It is the one control that should block unconditionally, because the cost asymmetry is extreme: a committed credential is compromised the moment it is pushed, and Git history is effectively permanent.
Three layers:
- Pre-commit hook — fastest feedback, and prevents the secret from ever entering history. Bypassable, so not sufficient alone.
- Server-side push protection — rejects the push. Not bypassable by a local configuration.
- Continuous history scanning — finds what was committed before the controls existed, and what slipped through.
And the response must be rotate first, then clean history. Removing a secret from Git history does not un-compromise it; a scraper may have had it within seconds of the push. Teams that rewrite history and skip rotation have done the expensive half of the work and none of the protective half.
Making findings actionable
The difference between a security programme that works and one that gets disabled is almost entirely in how findings are presented.
Report only on changed code in a pull request. A developer who touched one file should not receive four hundred pre-existing findings. Deal with the existing backlog separately, as a prioritised project with its own owner.
Prioritise by exploitability, not by CVSS alone. A critical CVE in a dependency your code never calls is less urgent than a medium one on your authentication path. The signals that matter:
- Reachability — is the vulnerable function actually invoked?
- Exposure — is the component reachable from the internet?
- Known exploitation in the wild — a small subset of CVEs are ever exploited, and those should jump the queue regardless of score.
- Fix availability — a finding with no patch is a risk-acceptance decision, not a developer task.
Give every finding a fix. “SQL injection risk at line 42” is a task. “SQL injection risk at line 42 — use a parameterised query; here is the corrected line” is a fix. Where a tool can generate the patch as a pull request, it should.
Set thresholds by severity and let the rest through. Blocking on everything means blocking on nothing, because the block gets bypassed.
The backlog problem
Introducing scanning to an existing codebase produces a large number of pre-existing findings. The instinct is to fix them all before enabling enforcement; this delays enforcement indefinitely.
flowchart TD
A[Enable scanning in report-only mode] --> B[Baseline: snapshot all existing findings]
B --> C[Block only on NEW findings<br/>from this point forward]
C --> D[Estate stops getting worse immediately]
D --> E[Triage the baseline by exploitability]
E --> F[Burn down critical and high<br/>as scheduled work with an owner]
F --> G[Lower the blocking threshold<br/>as the backlog shrinks]
Stopping the bleeding first is the right order. A codebase that is not getting worse while the backlog burns down is a far better position than one waiting for a cleanup project that never gets prioritised.
Tuning out the noise
Every scanner produces false positives, and untuned scanners produce mostly false positives.
- Suppress with a reason and an expiry, never silently. A suppression file entry should record who, why, and when it should be reconsidered.
- Track the false-positive rate per rule. A rule generating 90% false positives should be disabled — it is consuming attention and providing negative value.
- Tune before enforcing. Run in report-only mode for a few weeks, tune, then turn on blocking. Enforcing an untuned scanner is the fastest way to lose the organization’s cooperation.
Ownership
Findings without an owner are not work; they are a report. Route them automatically using the same service catalogue that drives incident routing — finding in repository X goes to the team that owns repository X, appearing in their normal backlog rather than in a security tool they do not open.
The security team’s job in this model is to own the rules, the thresholds, and the exceptions — not to chase individual findings across the organization.
Adoption checklist
- Secret detection runs pre-commit, at push, and continuously over history.
- Leaked credentials are rotated first; history cleanup is secondary.
- Pull request findings are limited to changed code.
- Prioritisation uses reachability, exposure, and known exploitation — not CVSS alone.
- Every finding includes a concrete fix; automated fix pull requests where possible.
- New scanners run in report-only mode and are tuned before enforcement.
- Existing findings are baselined; only new findings block.
- Suppressions require a reason and an expiry date.
- Findings route to owning teams automatically via the service catalogue.
Last updated 19 Aug 2026, 00:00 UTC.