Two hours sounds tiny until you wire it to automation. In September 2025, an attacker phished one npm maintainer and published booby-trapped versions of chalk, debug, and around a dozen other packages that GitHub says were together downloaded more than 2 billion times a week. The malicious code rewrote cryptocurrency wallet addresses inside any browser app that loaded it. npm pulled the poisoned versions after roughly two hours. As human response time, that is quick. As update-bot time, it is a very long morning.
That two-hour number is the whole argument for what GitHub shipped next.
In July 2026, Dependabot changed a default: it now waits at least three days after a release is published before opening a pull request for non-security version updates. The mechanics are small. The admission behind them is not. Speed itself has become part of the attack surface. Once your repo has a version bot, CI, and an agent happy to summarize a diff or patch the breakage a bump causes, pulling the newest public package the instant it lands stops being hygiene and starts being a risk amplifier. For a Node or TypeScript team, dependency freshness is now a security control you configure, not a virtue you chase.
The update bot belongs in your threat model
The old advice came from a sane place. Stale dependencies accumulate known CVEs, API drift, and upgrade cliffs that cost a week when you finally pay them down. So we built habits and tooling to shrink the gap between a release and its adoption.
That logic still holds for security fixes. It is weaker as a blanket rule for ordinary version bumps, because the first minutes after a package publishes are the least-scrutinized minutes it will ever have. GitHub says a growing share of supply-chain attacks share one shape: malicious code ships in a brand-new release, hits the public registry, and reaches build pipelines within minutes, before a human or a scanner has looked at it.
The automation loop is the entire trick: publish, open PR, run CI, smooth over breakage, merge. Each step removes a little friction. Add a coding agent that can summarize the changelog or fix a broken import, and you remove the last human pause — the one where somebody asks whether the release itself had earned trust yet. Green tests will not ask that question for you. They only confirm your code still ran during the most dangerous window of the release's life.
The useful reframing is to treat a brand-new public release as untrusted until it has survived a little time in the open. Renovate users, and anyone letting an agent touch dependency PRs, should read the Dependabot change as a message aimed at them too.
Turn the delay on: the dependabot.yml cooldown
The three-day default does something, but the point is that you can make it a real policy. The cooldown block in dependabot.yml lets you set the waiting window, and tune it by SemVer bump size — a major upgrade is where breakage and typosquats both hide, so it deserves the longest hold:
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 3
semver-major-days: 7
semver-minor-days: 3
semver-patch-days: 2
include:
- "*"
include and exclude take up to 150 dependency globs each, so you can widen the window on the packages you trust least without punishing the whole tree. One thing the config will not let you do by accident: starve a security fix. GitHub is explicit that cooldown applies to version updates only — security updates still open right away, because delaying a patch for an already-public flaw is the one place waiting clearly loses.
The same idea in Renovate
If some repos run Renovate instead, mirror the rule rather than leaving those repos on zero-hour adoption. The minimumReleaseAge option is the equivalent lever, and internalChecksFilter: "strict" is what makes Renovate actually withhold the branch until the age passes instead of opening a PR that merely shows a pending check:
{
"internalChecksFilter": "strict",
"packageRules": [
{
"matchDatasources": ["npm"],
"matchUpdateTypes": ["major", "minor", "patch"],
"minimumReleaseAge": "3 days"
}
]
}
Two tools, one policy. If your coding agent can open or update dependency PRs, give it the same rule. Otherwise you do not have a policy; you have tool-specific accidents.
Decide the lanes before your agents do
A blanket delay on everything is too crude. A security fix, an internal package from a registry you control, and a package that appeared on public npm forty minutes ago are three different risks, and once agents are in the loop the question stops being "update now or later" and becomes which lane the update belongs in.
flowchart TD
A[Update available] --> B{Security fix?}
B -- Yes --> C[Fast lane, open now]
B -- No --> D{Trusted internal registry?}
D -- Yes --> E[Short window]
D -- No --> F[Public npm, 72h hold]
C --> G[Human review + CI]
E --> G
F --> G
G --> H{Merge?}
H -- Yes --> I[Ship]
H -- No --> J[Hold or reject]
The lane that matters is the last one. A private scope in Azure Artifacts earns the short window only if you trust how that package is built and published; a fresh public dependency does not, no matter how small the diff looks or how green the checks are. Written into dependabot.yml, this holds even at 2 a.m. when nobody is reading the PR. Left unwritten, the path of least resistance is always merge.
Cooldown fixes one attack shape, so keep the boring layers
GitHub is refreshingly plain about the limits: cooldown is built for malicious versions that ship, spread, and get caught quickly. It does little against a dormant backdoor, maintainer sabotage, or a compromised build system. That honesty matters, because teams love turning one useful guardrail into a false sense of coverage. The scale says do not: GitHub says the GitHub Advisory Database cataloged more than 6,500 npm malware advisories in the year ending May 2026, up from roughly 6,200 — about 18 newly flagged malicious packages a day.
So keep the layers that work regardless of release age. Pin with a lockfile, refuse install scripts in CI, and scope your build tokens so a poisoned postinstall has nothing to steal:
# CI install: reproducible, and no arbitrary package scripts
npm ci --ignore-scripts
For agent-heavy repos, add one blunt rule the config cannot express: do not give an agent automatic merge authority on a fresh public dependency PR. An LLM can read release notes and patch a broken import. It has no way to know whether a version published forty minutes ago is about to be yanked, and neither do your tests.
GitHub changed one default. The lesson is for every Node repo that mixes package bots, CI, and coding agents: freshness is no longer free, and the cheapest way to buy some safety back is to make waiting the default and write the exceptions down.