BIPI
BIPI

Seven Signals That Your Build Pipeline Is Compromised

Cybersecurity

Most supply-chain attacks are not loud at the moment of compromise. They are loud after the fact — postmortem-loud. Here are the seven signals our IR team looks for that catch the attack while it is still recoverable.

By Arjun Raghavan, Security & Systems Lead, BIPI · November 4, 2025 · 8 min read

#supply-chain#detection#incident-response#ci/cd

Most supply-chain compromises are not detected by the team running the pipeline. They are detected weeks later by an external researcher, a customer, or a security vendor. By then the malicious code has shipped to production, harvested whatever it could, and the cleanup is downstream of the breach instead of upstream of it.

The attacks are not actually quiet. They have to do work — exfiltrate tokens, fetch second-stage payloads, write themselves into other packages. That work produces signals. The signals are visible if you instrument the build pipeline to look for them. Here are the seven we monitor on every engagement.

1. Outbound network calls during npm install

A clean dependency install fetches packages from registry.npmjs.org (or your private mirror) and nothing else. A poisoned dependency that wants to exfiltrate credentials makes additional calls — to the attacker's collection endpoint, to a cloud-metadata service, to anywhere that is not the registry.

The detection is one egress firewall rule. Run npm install in a network-namespaced container that only allows traffic to your registry. Anything else is blocked AND logged. Most teams discover, the first time they enable this, that some legitimate package is also calling out — usually a telemetry beacon or a font CDN. Allowlist those explicitly. Anything else is investigation.

2. Lockfile changes that nobody authored

Lockfile drift between commits is the most common way teams notice a compromise after the fact. The fix is to make drift visible at PR time: any package version added or changed in the lockfile shows up as a separate review block, with a one-line summary of what is being added.

Tools that surface this: pnpm-lock-diff, npm audit signatures, socket.dev's PR comments, Snyk's SBOM diff. Pick one and require it as a blocking review check. PRs that change the lockfile by more than the explicitly-bumped packages get held until a human says 'yes that is correct.'

3. Unexpected lifecycle scripts in new dependencies

preinstall, install, postinstall scripts are the supply-chain attacker's tool of choice. A new dependency that did not have a postinstall script yesterday and does today is suspicious. A direct dependency that adds a postinstall in a patch release is more suspicious. Some legitimate packages need them; most do not.

Detection: a CI step that compares the lifecycle scripts in this commit's lockfile against the previous commit's. New scripts get flagged. We use a small node script for this. The output goes to the same review surface as the lockfile diff.

4. Build duration spikes

Backdoors do work that takes time. Fetching a second-stage payload, decoding obfuscated strings, attempting credential exfiltration. Build durations are usually consistent within a tight window. A 20% jump in build time on an unchanged commit is a signal.

Track build duration as a time-series metric. Alert on anomalies. The alert is rarely a smoking-gun supply-chain attack — usually it is a runner that got rescheduled to a slower instance class — but the alert that matters once a year is the alert that catches the worm at hour zero.

5. Modified PATH or environment variables in CI logs

Sophisticated attackers don't just exfiltrate the env they see. They modify the env to log future commands, intercept future credentials, or persist into the cache. Anything that touches PATH, NODE_OPTIONS, NPM_CONFIG_*, or HTTPS_PROXY during install is a candidate.

Detection: capture the full process environment before and after npm install in CI. Diff. Anything new is flagged. Most installs add nothing; the few that do are obvious.

6. Files written outside the project tree

A clean install writes only inside node_modules and the lockfile. A backdoor that wants to persist writes to ~/.ssh/authorized_keys, ~/.bashrc, /tmp, or other system locations. Containerised builds with read-only filesystem outside the workspace make this easy to detect — the write fails noisily.

Even on hosts with writable filesystems, an inotify watch (Linux) or fs-events (macOS) on the home directory during install will surface the writes. Most attacker tooling does not avoid this because most defenders do not check.

7. Postmortem signals from production

If the previous six all fail, the last line is production telemetry. A poisoned package that ships into a deployment will eventually try to do something — an outbound C2 call from a process that should not network, an unusual file read, an unexpected child process. Runtime EDR or eBPF tools catch these.

This is the slowest detection layer because the attack has already shipped. But it catches the slow-burn campaigns where signals 1-6 missed. Every team should have it. We deploy Falco, Tetragon, or commercial equivalents on production hosts and surface anomalies into the SOC pipeline.

7
Layers of detection
Hours
Time to first signal at hour zero
1
Compromise that justifies the whole stack

What we install on every engagement

  1. Network-namespaced CI runners with egress allowlists.
  2. Lockfile diff as a required PR check.
  3. Lifecycle-script diff in the same PR check.
  4. Build-duration timeseries with anomaly detection.
  5. Process-env diff capture during install.
  6. Read-only filesystem outside the workspace in build containers.
  7. Runtime detection (Falco / Tetragon) on production hosts.

None of this is novel. All of it is standard build-pipeline hygiene that most teams have not gotten around to. The teams that have are the ones that catch the next worm at hour zero, not at week three.

Closing

Detection is the work that nobody celebrates and that pays back the most. Supply-chain attacks will continue. The economics favour the attacker. The teams that survive cleanly are the ones with seven independent layers of detection in their pipeline, each one cheap, each one watching for a different signal. Add them one at a time. Within a quarter you have the kind of build pipeline that catches its own compromise.

Read more field notes, explore our services, or get in touch at info@bipi.in. Privacy Policy · Terms.