Security Lab
AppSec Practice by Nadav Czerninski

Runtime Detection in the SDLC: Where Shift-Left Falls Short

Shift-left deserves its place: a team I spoke with last year had strong coverage, including pre-commit SAST hooks, SCA in CI, container image checks before deployment, and weekly reviews of new CVEs against its dependency tree. Yet that coverage had limits. Two weeks after deploying a new service, Oligo's early-access instrumentation detected an active exploitation attempt targeting a CWE-502 deserialization vulnerability in a transitive dependency that SCA had labeled "low reachability." The static call graph had misjudged reachability because a particular input combination activated a code path the analyzer had not traced.

This is not a case against shift-left. It is a case for knowing where its coverage stops and what protects the space beyond it.

Where Shift-Left Excels

Pre-production scanning identifies a broad, clearly defined set of vulnerabilities. SAST can use dataflow analysis to find injection sinks, hardcoded secrets, recognizable deserialization patterns, and known-bad API calls. SCA identifies packages with published CVEs and license concerns. Container image scanning covers infrastructure, while Infrastructure-as-Code (IaC) scanning finds misconfigurations before they create runtime exposure.

This work is valuable, with a clear ROI: fixing a vulnerability in a pull request costs an order of magnitude less than fixing one after deployment. This post is not suggesting that security should move later in the SDLC. Shift-left remains essential.

The issue is what shift-left misses and whether another layer covers those gaps.

Gaps Shift-Left Cannot Close

Zero-day and N-day exploits between scans

Your SCA scan runs in CI. Four days after your last deployment, a critical CVE is published. Within hours of the PoC release, attackers begin exploiting it (we will cover the timing data in a separate post). The next deployment cycle, and therefore the next scan, remains eight days away. During that interval, production contains a known-exploited vulnerability, and no pre-production scan can show whether attackers are actively targeting it.

Transitive dependency reachability errors

Static call graph analysis becomes less accurate for transitive dependencies as the tree grows deeper and dynamic dispatch patterns, such as reflection, plugin architectures, and dependency injection frameworks, make execution paths harder to represent. In a large Java or Node.js application, the graph at depth-3 or depth-4 dependencies is often incomplete. "Not reachable according to the static model" expresses probability, not certainty.

Vulnerabilities triggered by runtime configuration

Certain vulnerabilities become exploitable only under particular runtime configuration states. A deserialization flaw might be reachable only when a specific production feature flag is enabled. An SSRF path might require a particular environment variable in the deployed service. Static scanning examines the code, while production may expose a different effective attack surface than the CI artifact.

Supply chain injection after scanning

When a dependency is compromised after SCA runs, that scan result no longer applies to the package version. Depending on when and how resolution occurred relative to scanning, the artifact that cleared CI may differ from what was analyzed, or may behave differently.

Fileless and memory-resident threats

An attacker who gains RCE through an unpatched vulnerability and works entirely in memory, using injected shellcode or reflective code loading inside an existing process, leaves no disk binary for a file scanner to detect. The execution record exists only in the kernel's process history and the syscalls made by the injected code.

Runtime Detection's Place in the SDLC

Runtime detection does not fit neatly within the "shift-left" framing because it represents a different control type. Pre-production scanning is preventive: it identifies issues before production and leaves time to fix them before exploitation. Runtime detection is detective: it shows when exploitation is happening or has happened.

These controls complement rather than compete with each other. At minimum, a mature AppSec program needs both. The goal is to connect the runtime and pre-production layers so they strengthen one another instead of operating in silos.

The most useful integration pattern we have seen feeds runtime execution data into the pre-production scan backlog. Static analysis produces more findings than any team can remediate simultaneously. Runtime telemetry shows which findings involve code paths executed in production during the past 30 days. Those findings should take priority, regardless of CVSS score. Findings tied to code that has never run in production are lower-priority candidates, not candidates for permanent deprioritization.

A Practical Way to Integrate

In practice, an AppSec program combining shift-left with runtime detection might work like this:

Pre-production: Run SAST and SCA in CI, blocking critical/high findings for known-exploited CVEs (CISA KEV list as the first-pass blocker), while flagging rather than blocking high-CVSS low-reachability findings. Scan container images before deployment and run IaC checks within the infrastructure pipeline.

Production: eBPF instrumentation observes system calls across deployed services. Establish behavioral baselines during a new service's first week. Alert on deviations matching known exploitation patterns, including unexpected execve chains, connections to disallowed IP ranges, and ptrace calls from unexpected parent processes.

Feedback loop: Feed runtime execution coverage into the pre-production scanner's prioritization queue. Move CVE-matched functions called in production during the last sprint to the top of the remediation queue. Keep functions never called in production in the queue, but do not treat them as emergency fixes.

What Runtime Detection Cannot Replace

The boundary is straightforward: runtime detection cannot replace secure coding or the identification of known vulnerabilities before release. If your application contains SQL injection and runtime detection is in place, you will receive an alert when someone exploits it. The attacker has still executed a SQL query that should never have run. Detection is not prevention.

Runtime detection is most valuable as the final honest signal: what is truly happening in production rather than what a static model says might happen. It identifies what escapes pre-production controls, verifies patch effectiveness by showing that the attack path no longer triggers rather than merely that the CVE is closed, and supplies forensic evidence after an incident.

With both layers, a team can answer two separate questions: "Does this vulnerability exist in our code?" (shift-left) and "Is someone exploiting it right now?" (runtime). A team answering only the first has incomplete situational awareness, no matter how mature its shift-left program may be.

See detection patterns in your clusters

Deploy Oligo's eBPF instrumentation and view the runtime graph for your workloads.

Request Access More Articles