---
author: Jan Brennenstuhl
canonical_url: https://www.janbrennenstuhl.eu/dependency-updates/
description: Automatic dependency updates spread compromised packages faster than humans can react. Version pinning, provenance verification, and repository proxies turn blind trust into controlled trust.
id: jb-automatic-dependency-updates
kind: essay
license:
  name: CC BY 4.0
  scope: Original text; credited third-party media retain their own rights.
  url: https://creativecommons.org/licenses/by/4.0/
markdown_url: https://www.janbrennenstuhl.eu/dependency-updates/index.md
modified: '2026-05-17T00:00:00+02:00'
published: '2026-05-15T00:00:00+02:00'
review_basis: publication
review_status: reviewed
reviewed: '2026-05-15'
series: agentic-appsec
status: published
title: 'Dependency Updates: latest Is Not a Security Strategy'
topics:
- application-security
---

# Dependency Updates: latest Is Not a Security Strategy

Past and present supply chain compromises prove that automatic dependency updates are attack amplifiers. Here is what controlled trust looks like in practice.

## Key findings

<a id="f-deps-pin-exact-versions"></a>
1. A version range like `^1.14.0` trusts every future matching release, which the Axios attackers used in 2026, so teams should pin exact versions and force transitive ones with overrides. (https://www.janbrennenstuhl.eu/dependency-updates/#f-deps-pin-exact-versions)
<a id="f-deps-7-day-cooldown"></a>
2. According to Wiz, a 7-day release-age cooldown covers 90% or more of recent supply chain incidents, and it would have blocked both the Axios and TanStack compromises. (https://www.janbrennenstuhl.eu/dependency-updates/#f-deps-7-day-cooldown)
<a id="f-deps-provenance-not-enough"></a>
3. The TanStack worm shipped malicious npm packages with valid SLSA Build Level 3 attestations, so provenance verification is necessary but not enough on its own. (https://www.janbrennenstuhl.eu/dependency-updates/#f-deps-provenance-not-enough)


On March 31, 2026, [North Korean state actors compromised Axios](https://www.microsoft.com/en-us/security/blog/2026/04/01/mitigating-the-axios-npm-supply-chain-compromise/ "Microsoft: Mitigating the Axios npm supply chain compromise"), an npm package with over 70 million weekly downloads. Any project declaring `axios@^1.14.0` connected to attacker C2 infrastructure the next time `npm update` ran. Six weeks later, a [self-propagating worm hit 42 TanStack packages](https://snyk.io/blog/tanstack-npm-packages-compromised/ "Snyk: TanStack npm packages compromised"). It reached Mistral AI, UiPath, and [OpenAI](https://thehackernews.com/2026/05/tanstack-supply-chain-attack-hits-two.html "The Hacker News: TanStack Supply Chain Attack Hits Two OpenAI Employee Devices") within hours. It also carried valid [SLSA provenance](https://slsa.dev/spec/v1.0/levels "SLSA security levels") attestations, signed by the legitimate build pipeline.

The same infrastructure that helps us stay current also amplified these attacks. Automated dependency updates pushed the compromised packages into production builds faster than any human could react.

We learned that outdated dependencies are dangerous. That is true. But many teams have flipped the lesson around. _Newer_ is treated as _safer_. It is not.

<a id="the-trust-problem"></a>
## The Trust Problem

Modern package managers are not static library linkers. They are code execution pipelines. A single `npm install` can run [arbitrary install scripts](https://docs.npmjs.com/cli/v11/using-npm/scripts "npm scripts documentation"), read credentials, and run with full CI permissions. It does this across hundreds of transitive packages that nobody on the team has reviewed. Every dependency expands your [trusted computing base](https://en.wikipedia.org/wiki/Trusted_computing_base "Trusted Computing Base").


> It's not every dependency you add that's a problem; it's every dependency you update.
>
> — Ben Hoyt, [Every dependency you add is a supply chain attack waiting to happen](https://benhoyt.com/writings/dependencies/)



Two problems arise here:

1. Version ranges like `^1.14.0` do not mean _"I trust version 1.14.0"_. They mean _"I trust every future release that matches this constraint"_. That is a large, open-ended trust delegation. The Axios attackers used exactly that. Version `1.14.1` was a [manifest-only change](https://www.microsoft.com/en-us/security/blog/2026/04/01/mitigating-the-axios-npm-supply-chain-compromise/ "Microsoft: Mitigating the Axios npm supply chain compromise") that added a malicious dependency while leaving the Axios source code untouched. [Semantic versioning](https://semver.org/ "Semantic Versioning Specification") signals maintainer intent, not trustworthiness. The same applies to [floating Docker tags](https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html "OWASP Docker Security Cheat Sheet"), [unpinned GitHub Actions](https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions#using-third-party-actions "GitHub: Security hardening for GitHub Actions"), and `latest` tags everywhere.

2. Tools like [Dependabot](https://docs.github.com/en/code-security/tutorials/secure-your-dependencies/dependabot-quickstart-guide) and [Renovate](https://docs.renovatebot.com/) normalized constant dependency updates. At scale, they improve visibility and shorten the window for known CVEs. But they also changed how we consume trust. Security automation quietly became trust automation. Dependency update PRs receive less review than internal code, even though they run with the same or higher privilege. The volume is overwhelming and eventually the workflow shrinks to: CI passes → vulnerability score drops → merge. That creates a dangerous illusion. _"No known CVEs"_ does not mean _"safe"_. Supply-chain attacks are newly published, initially undetected, semantically valid, and technically _"up to date"_.


> False positive alerts are not only a waste of time, they also reduce security by causing alert fatigue and making proper triage impractical.
>
> — Filippo Valsorda, [Turn Dependabot Off](https://words.filippo.io/dependabot/)



The [XZ Utils backdoor](https://en.wikipedia.org/wiki/XZ_Utils_backdoor "XZ Utils backdoor") in 2024 showed how long-running social engineering can compromise critical infrastructure. The [Mini Shai-Hulud](https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack "Wiz: Shai-Hulud 2.0 Supply Chain Attack") incidents in 2025 and the ongoing supply chain attacks show that the attack surface extends well beyond maintainer compromise. It reaches into version ranges, build pipelines, provenance systems, and the update automation that ties them together. These are not theoretical risks. They are documented, attributed attacks against the most popular packages in the ecosystem.

<a id="what-controlled-trust-looks-like"></a>
## What Controlled Trust Looks Like

There is no perfect fix for supply-chain risk. There are practical ways to replace blind trust with controlled trust:

<a id="pin-versions"></a>
### Pin Versions

Remove `^` and `~` from `package.json` or whatever dependency manifest you use. Use exact versions. For transitive dependencies, force the version with [overrides](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#overrides "npm overrides"):

```json
{
  "dependencies": { "axios": "1.14.0" },
  "overrides": { "axios": "1.14.0" }
}
```

Lockfiles like `package-lock.json`, `pnpm-lock.yaml`, `Cargo.lock`, and `poetry.lock` do not make dependencies safe. They make dependency state reproducible. You cannot investigate what you cannot reproduce.

<a id="enforce-release-age-cooldowns"></a>
### Enforce Release-Age Cooldowns

Supply-chain attacks have a short half-life. The compromised TanStack versions lasted about three hours before someone caught them. A [release-age cooldown](https://nesbitt.io/2026/03/04/package-managers-need-to-cool-down.html "Package Managers Need to Cool Down") rejects packages younger than a threshold. That gives the community time to spot compromises before they reach your builds:

```ini
# ~/.npmrc
min-release-age=7

# pnpm-workspace.yaml
minimumReleaseAge: 1440

# ~/.bunfig.toml
[install]
minimumReleaseAge = 604800

# ~/.config/uv/uv.toml
exclude-newer = "7 days"
```

A seven-day cooldown [covers 90% or more of recent supply chain incidents](https://www.wiz.io/blog/practical-package-security-the-unofficial-guide "Wiz: Practical Package Security - The Unofficial Guide"). It would have prevented both the Axios and TanStack compromises.

<a id="control-upgrade-cadence"></a>
### Control Upgrade Cadence

Filippo Valsorda [recommends a better model](https://words.filippo.io/dependabot/#test-against-latest-instead-of-updating "Test against latest instead of updating") than auto-updating: Run your test suite against the latest dependency versions daily in a sandboxed CI job. You get early warning of breakage without pulling untrusted code into production. You still update. You do it on your schedule, after review, when you are ready.

<a id="verify-provenance-but-do-not-trust-it-alone"></a>
### Verify Provenance, But Do Not Trust It Alone

The TanStack attack is the first documented case of malicious npm packages carrying valid [SLSA Build Level 3](https://slsa.dev/spec/v1.0/levels#build-l3 "SLSA Build Level 3") attestations. Provenance verification is necessary but not sufficient. Pair it for instance with [deep package inspection](https://socket.dev "Socket: Supply Chain Security") to catch suspicious network calls, filesystem access, and hidden scripts before they run.

<a id="deploy-repository-proxies"></a>
### Deploy Repository Proxies

Place package managers behind a properly configured repository proxy like [Sonatype Nexus](https://www.sonatype.com/products/sonatype-nexus-repository), [JFrog Artifactory](https://jfrog.com/artifactory/), or an internal mirror. These proxies should be configured not only to mirror (ideally approved) dependencies, but also quarantine suspicious releases and scan for known malware. But keep in mind that most scanners only detect known threats. Sophisticated attacks are novel by design. Proxy scanning is one layer, not a replacement for version pinning and controlled upgrades.

<a id="use-reachability-aware-scanning"></a>
### Use Reachability-Aware Scanning

Not every CVE in your dependency tree matters. A vulnerability in a function you never call does not deserve the same urgency as one that is on your hot path. Go's [govulncheck](https://go.dev/doc/tutorial/govulncheck "Go Vulnerability Checking") traces your actual call graph and filters out findings in code your application never reaches. Other ecosystems are catching up. At a minimum, make sure your scanner can tell whether a vulnerable package is actually used. The best scanners go further and trace the call graph down to the specific vulnerable function.

<a id="reduce-dependency-surface-area"></a>
### Reduce Dependency Surface Area


> A little copying is better than a little dependency.
>
> — [Go Proverbs](https://go-proverbs.github.io/)



Every package adds code, maintainers, credentials, infrastructure, and trust assumptions. Modern ecosystems normalize [absurd dependency depth](https://research.swtch.com/deps "Russ Cox: Our Software Dependency Problem"). Before adding a package, ask: can we write this in 30 lines? If yes, write it. A [coding agent](https://www.janbrennenstuhl.eu/topics/agentic-engineering/) can do most of the work for you.

<a id="controlled-trust-not-blind-trust"></a>
## Controlled Trust, Not Blind Trust

The lesson from 2025 and 2026 supply-chain attacks is not _"never update"_. Stale dependencies become liabilities too. The lesson is that **blind trust does not become safer just because it is automated**.

Secure software supply chains are built on controlled trust: Pinned versions. Enforced cooldowns. Verified provenance. Proxy repository managers. Reachability-aware scanning. A small dependency surface. The fastest update is not always the safest. Sometimes the safest thing to do is wait.

---

_Updated on May 17th: Referenced THN report on "the TanStack supply chain attack hitting two OpenAI employee devices" and the "Practical Package Security" guide by Wiz._


---

Cite as: Jan Brennenstuhl. "Dependency Updates: latest Is Not a Security Strategy." Brennenstuhl on Security, 15 May 2026. https://www.janbrennenstuhl.eu/dependency-updates/
License: CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/) for the original text; credited third-party media keep their own rights.
