How Dependabot Missing Cooldown Happens in GitHub Actions and How to Fix It
Introduction
The .github/dependabot.yml file in this Node.js library controlled how GitHub's Dependabot service proposed dependency updates to the project. It was configured to watch the npm ecosystem, limit open pull requests to 10, assign a specific reviewer (stefcameron), and apply a versioning-strategy of increase. Everything looked reasonable — but a critical security control was absent: there was no cooldown period.
Without a cooldown, Dependabot is free to propose an update to a package the moment a new version lands on the npm registry. That sounds helpful, but it creates a meaningful supply-chain risk: a malicious actor who publishes a compromised package version would have it surfaced as a Dependabot PR almost immediately, before the security community has had a chance to detect and flag the release.
This post walks through exactly what was missing, why it matters for a Node.js library whose vulnerabilities propagate to all downstream consumers, and how a single YAML addition closes the gap.
The Vulnerability Explained
What Was Missing in dependabot.yml
Before the fix, the relevant portion of .github/dependabot.yml looked like this:
# .github/dependabot.yml (BEFORE — vulnerable)
updates:
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: 'weekly'
open-pull-requests-limit: 10
reviewers:
- 'stefcameron'
versioning-strategy: 'increase'
ignore:
# ignore React 19 and related dependencies to keep tests based on R18 for now
Notice what is absent: there is no cooldown block anywhere under the npm ecosystem entry. This means Dependabot operates with zero delay — as soon as a new version of any tracked npm package is published, Dependabot is eligible to open a PR proposing that version.
Why Zero Delay Is a Problem
The npm registry is a high-value target for supply-chain attacks. Attack patterns include:
- Account takeover: An attacker compromises a maintainer's npm credentials and publishes a backdoored patch version (e.g.,
1.2.4over a clean1.2.3). - Typosquatting: A malicious package with a name similar to a popular one gets published and Dependabot picks it up if a dependency name was recently changed.
- Dependency confusion: An internal package name is registered on the public registry with a higher version number, tricking package managers into preferring it.
In all three scenarios, the attacker's window of maximum effectiveness is the period immediately after publication, before security researchers, automated scanners, or the npm security team have had time to analyze and remove the package. A Dependabot configuration with no cooldown shrinks the defender's reaction time to near zero.
Concrete Attack Scenario
Imagine a popular utility in this project's package.json — say, a test helper or a build tool — has its npm account compromised. The attacker publishes version 3.1.1 containing a postinstall script that exfiltrates environment variables. Without a cooldown:
- The malicious
3.1.1lands on npm. - Dependabot's next scheduled run (weekly in this config) picks it up.
- A PR is opened proposing the upgrade, complete with a changelog that looks normal.
- A developer reviews it, sees a minor patch bump, approves, and merges.
- The malicious postinstall script runs in CI and in every developer's local environment.
Because this is a Node.js library (not just an internal application), any downstream consumer who installs it will also pull in the compromised transitive dependency.
The Fix
What Changed
The fix adds a cooldown block directly under the npm package-ecosystem entry, between the reviewers block and versioning-strategy:
# .github/dependabot.yml (AFTER — fixed)
updates:
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: 'weekly'
open-pull-requests-limit: 10
reviewers:
- 'stefcameron'
cooldown:
default-days: 7
versioning-strategy: 'increase'
ignore:
# ignore React 19 and related dependencies to keep tests based on R18 for now
The diff is minimal but impactful:
reviewers:
- 'stefcameron'
+ cooldown:
+ default-days: 7
versioning-strategy: 'increase'
How the Cooldown Works
The cooldown block tells Dependabot to wait at least default-days: 7 after a package version is first published to the registry before it is eligible to be proposed in a PR. The 7-day window is the GitHub-recommended baseline and aligns with the typical detection timeline for malicious packages on the npm registry.
You can also set ecosystem-specific or package-specific overrides:
cooldown:
default-days: 7 # applies to all packages
semver-patch-days: 3 # shorter wait for patch-only bumps
semver-minor-days: 5 # medium wait for minor bumps
For this project, default-days: 7 is the right starting point — it applies uniformly to all npm packages tracked by Dependabot, including the React-related packages currently being ignored for version pinning reasons.
Why This Specific Change Solves the Problem
The 7-day quarantine window provides several defensive layers:
| Defender | Typical Detection Time |
|---|---|
| npm security team automated scanners | Hours to 2 days |
| Security researchers / community reports | 1–5 days |
| CVE / NVD publication | 3–14 days |
| Downstream package audits | 1–7 days |
By waiting 7 days, Dependabot will not surface a version until the majority of these detection mechanisms have had a chance to operate. If a version is flagged and yanked from npm within that window, Dependabot will never propose it.
Prevention & Best Practices
Always Define a Cooldown for Every Ecosystem
If your dependabot.yml manages multiple ecosystems (e.g., npm and github-actions), add a cooldown block to each package-ecosystem entry:
updates:
- package-ecosystem: 'npm'
directory: '/'
schedule:
interval: 'weekly'
cooldown:
default-days: 7
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'weekly'
cooldown:
default-days: 7
Pair Cooldown with Other Supply-Chain Controls
A cooldown is one layer of a defense-in-depth strategy. Combine it with:
npm auditin CI to catch known vulnerabilities in the current lock file.- Lockfile integrity checks — commit
package-lock.jsonand verify it in CI. - Dependency review via GitHub's built-in dependency review action, which blocks PRs that introduce known-vulnerable packages.
- Pinned GitHub Actions versions using full commit SHAs to prevent tag-based attacks.
- Sigstore / npm provenance — prefer packages that publish build provenance attestations.
Use Static Analysis to Catch Missing Cooldowns Early
The Semgrep rule package_managers.dependabot.dependabot-missing-cooldown.dependabot-missing-cooldown detects this pattern automatically. Add it to your CI pipeline:
semgrep --config=p/supply-chain .github/dependabot.yml
Security Standards Alignment
- OWASP A06:2021 – Vulnerable and Outdated Components: Using a cooldown reduces the risk of automatically adopting a newly published vulnerable or malicious component.
- CWE-1357 – Reliance on Insufficiently Trustworthy Component: The absence of a vetting delay means the pipeline implicitly trusts any version published to the registry.
- SLSA Supply Chain Framework: Cooldowns support the principle of verifying artifact integrity before consumption.
Key Takeaways
- The missing
cooldownblock in.github/dependabot.ymlis the root cause — not a misconfigured schedule or an overly broadignorelist. Two lines of YAML close a meaningful supply-chain window. - Zero-delay Dependabot updates are particularly risky for published libraries because a compromised transitive dependency propagates to every downstream consumer who installs the package.
default-days: 7matches the realistic detection timeline for malicious npm packages — it's not an arbitrary number, it reflects how long the ecosystem typically takes to identify and remove bad releases.- The cooldown must be added per ecosystem — a single top-level setting does not exist; if this project later adds a
github-actionsecosystem entry, it will need its owncooldownblock. - Static analysis (Semgrep) caught this before it caused harm — integrating supply-chain linting into your CI pipeline surfaces these configuration gaps before they reach production.
How Orbis AppSec Detected This
- Source: The npm registry — any newly published package version is immediately eligible for a Dependabot PR when no cooldown is configured.
- Sink: The
package-ecosystem: 'npm'entry at line 3 of.github/dependabot.yml, which lacked acooldownblock, meaning Dependabot would propose updates with zero delay. - Missing control: No
cooldownblock with adefault-daysvalue under the npm ecosystem entry — the configuration containedopen-pull-requests-limit,reviewers, andversioning-strategybut omitted the quarantine window entirely. - CWE: CWE-1357 — Reliance on Insufficiently Trustworthy Component.
- Fix: Added
cooldown: default-days: 7between thereviewersandversioning-strategykeys in the npm ecosystem entry, enforcing a 7-day waiting period before any newly published package version is proposed.
Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.
Conclusion
A two-line addition to a YAML configuration file — cooldown: and default-days: 7 — meaningfully reduces the supply-chain attack surface for this Node.js library and all of its downstream consumers. The change is low-friction: it does not prevent Dependabot from proposing updates, it simply ensures those updates have had a week to be scrutinized by the broader security ecosystem before landing in your PR queue.
For teams maintaining open-source libraries or widely-consumed internal packages, this kind of configuration hygiene is not optional. The npm ecosystem sees supply-chain attacks regularly, and automated tooling like Dependabot — while invaluable — needs guardrails to avoid becoming an attack vector itself.
Review your own dependabot.yml files today. If you don't see a cooldown block, you're one compromised package release away from an automated PR that could introduce malicious code into your project.