A malicious package does not need to stay online for a week. It only needs to be available when your developer laptop, CI runner, dependency bot, or editor auto-update mechanism asks for it.

That is the uncomfortable lesson from the latest wave of developer supply chain incidents. Fast takedown is useful. It is not the same as prevention.

TL;DR

  • Supply chain malware often wins in the first minutes or hours after publication.
  • A minimum package age policy delays adoption of new dependency versions until the ecosystem has had time to detect obvious abuse.
  • This is not a replacement for pinning, provenance, OIDC, staged publishing, or code review. It is a timing control that makes those controls more likely to matter.
  • Apply shorter delays to security fixes and emergency releases, longer delays to routine updates, editor extensions, development-only packages, and AI tooling.
  • If your organization cannot answer “what installs new code automatically within the first hour?”, it does not yet have this control.

The Attack Window Is Small

Modern supply chain attacks exploit automation. A package is published, a lockfile update lands, a CI job runs, an extension auto-updates, or a developer opens a trusted workspace. The malicious code executes before a human has read a changelog.

That is why “the malicious version was removed quickly” can be a misleading comfort. If the attacker gets 18 minutes, three hours, or one business morning, that may be enough for token theft, repository cloning, CI/CD persistence, or package republishing.

The defensive question is not only:

How fast can we detect and remove a bad release?

It is also:

Why were we willing to install a brand-new release before anyone else had time to detect it?

What Minimum Package Age Means

Minimum package age is a policy that says:

Do not install or propose a newly published dependency version until it is at least X old.

The value of X depends on the context. Three hours may reduce exposure to obvious registry abuse. Twenty-four to seventy-two hours may be more appropriate for routine dependency automation. High-risk developer tools, editor extensions, build plugins, and packages with install scripts may deserve a longer window.

This is not “never update.” It is “do not be first unless there is a reason.”

The control works because many malicious releases are discovered quickly by maintainers, registries, downstream users, and security vendors. A delay gives the ecosystem time to raise the flag before your systems execute the new code.

Where It Helps

Minimum age is most useful when new code is installed automatically or semi-automatically:

SurfaceRiskUseful delay
Dependency botsOpens PRs (pull requests) for malicious versions before review context existsCooldown before PR creation or automerge
CI/CD buildsPulls new transitive packages during buildLockfiles, mirrors, and delayed registry promotion
Developer laptopsInstalls packages or extensions with local credential accessApproved catalogs and extension age rules
Editor extensionsAuto-update moves malicious code into trusted workspacesDisable uncontrolled auto-update for high-risk extensions
AI coding toolsPull plugins, skills, templates, and packages with little reviewTreat agent tooling as executable dependency surface

The target is not only production runtime dependencies. Development dependencies often run with better access than production code: source trees, SSH keys, package tokens, cloud profiles, and local credentials.

Where It Does Not Help

This control has limits.

It will not stop a maintainer who has been compromised for weeks. It will not detect a malicious change hidden inside a legitimate release. It will not protect you if your lockfile already points to a bad version. It also creates a tradeoff: delaying ordinary updates can delay bug fixes.

That is why minimum age should be policy-driven, not dogma.

Use exceptions for:

  • actively exploited security fixes
  • emergency vendor patches
  • packages owned and released by your own organization
  • releases that have already been manually reviewed
  • tightly pinned internal mirrors where artifacts are scanned and promoted deliberately

The point is to slow blind adoption, not to block urgent remediation.

Practical Implementation

Dependabot

GitHub’s Dependabot supports a cooldown option for version updates. Security updates are excluded, which is the right default: you usually want vulnerability fixes to move faster than routine feature updates.

version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
cooldown:
default-days: 3
semver-major-days: 7
semver-minor-days: 3
semver-patch-days: 1

This does not make updates safe. It gives review, registry abuse detection, and community reporting time to catch up.

Renovate

Renovate supports minimumReleaseAge. For npm, Renovate’s own documentation uses a three-day example because packages less than 72 hours old can still be unpublished from the npm registry.

{
"prCreation": "not-pending",
"internalChecksFilter": "strict",
"packageRules": [
{
"matchDatasources": ["npm"],
"minimumReleaseAge": "3 days"
}
]
}

For high-risk ecosystems, use package rules. A build plugin that runs arbitrary install scripts should not follow the same policy as a small CSS patch.

CI/CD

CI systems should not resolve fresh dependency versions during release builds unless that is an explicit design decision.

For release pipelines:

  • use lockfiles and fail if the lockfile changes unexpectedly
  • pin GitHub Actions to full-length commit SHAs where practical
  • separate pull request workflows from release workflows
  • avoid sharing caches across untrusted and trusted workflow boundaries
  • use OIDC (OpenID Connect, the short-lived token identity behind trusted publishing) instead of long-lived package tokens
  • require review for changes under .github/workflows/

The goal is simple: a new package should not become a production artifact merely because a resolver found it first.

Developer Workstations

Developer endpoints need a softer version of the same policy.

Start with visibility:

Terminal window
code --list-extensions --show-versions
npm config get ignore-scripts
git config --global --get-regexp url

Then define what is allowed:

  • approved editor extension list
  • no automatic installation of newly published extensions on sensitive workstations
  • review for extensions that access source control, terminals, credentials, or AI-agent configuration
  • separate throwaway environments for testing unfamiliar packages
  • package manager settings that prevent install-time scripts where the workflow allows it

This is where many teams fail. They govern production deployment but leave the developer workstation as a private plugin marketplace with cloud credentials.

A Detection Angle

Minimum age is a prevention control, but it also gives defenders better detection points.

Alert on:

SignalWhy It Matters
Dependency update to a version published less than 24 hours agoPossible early adoption of a malicious release
New editor extension version installed across many endpoints at onceAuto-update blast radius
Release workflow resolving dependencies instead of using a checked-in lockfileBuild is not reproducible
New id-token: write permission in GitHub ActionsExpands OIDC token exposure
Workflow change plus package publish in the same short windowCommon supply chain compromise pattern
Install-time script added to a dependency updateDirect execution path during install

If you have a software asset inventory, add package age to it. If you have EDR telemetry, watch developer tools touching credential stores shortly after dependency or extension updates.

What To Do This Week

  1. List every place that can install code automatically: dependency bots, CI, package managers, devcontainers, editor extensions, browser extensions, AI coding tools, and internal templates.
  2. Add a default 24-72 hour cooldown for routine dependency updates.
  3. Exempt security updates from the slow path, but require evidence that they are actually security fixes.
  4. Disable automerge for new major and minor dependency releases unless minimum age has passed.
  5. Pin release workflows and make lockfile drift fail the build.
  6. Inventory VS Code extensions and block unmanaged auto-update on sensitive developer machines.
  7. Rotate long-lived package publishing tokens toward OIDC or another short-lived identity model.

You do not need a perfect supply chain program to start. You need to stop being the first uncontrolled install after a package hits the registry.



Sources