How Dependabot Missing Cooldown Happens in GitHub Actions and How to Fix It
The Vulnerability at a Glance
| Field | Detail |
|---|---|
| Vulnerability | Dependabot Missing Cooldown Period |
| CWE | CWE-1104: Use of Unmaintained Third-Party Components |
| Language | YAML (Dependabot Configuration) |
| Risk | Automatic adoption of malicious or compromised npm packages with no delay |
| Root Cause | No cooldown block in the npm package-ecosystem entry |
| Fix | Added cooldown: default-days: 7 to enforce a 7-day waiting period |
Introduction
The .github/dependabot.yml file is the gatekeeper for automated dependency updates in your repository. When it's configured correctly, it's a powerful tool for keeping your project secure. When it's missing a critical safety control — like a cooldown period — it can become the fastest path for a malicious package to land in your codebase.
In this project, Semgrep flagged line 8 of .github/dependabot.yml: the npm package-ecosystem entry had no cooldown block. That means Dependabot was configured to open a pull request the moment a new npm package version was published — no waiting, no buffer, no time for the security community to raise the alarm on a potentially compromised release.
This is a Node.js library, which makes the risk especially significant: vulnerabilities in this package's dependency chain don't just affect the project itself — they flow downstream to every consumer of the library.
The Vulnerability Explained
What Does "No Cooldown" Actually Mean?
When Dependabot runs on its configured schedule and discovers a new version of a dependency, it immediately opens a pull request to adopt that version. Without a cooldown period, there is zero delay between a package being published to npm and Dependabot proposing it for inclusion in your project.
Here is the vulnerable configuration as it existed before the fix:
# .github/dependabot.yml (BEFORE — vulnerable)
updates:
- package-ecosystem: 'github-actions'
# ...
schedule:
timezone: 'Europe/Berlin'
cronjob: '47 3 24 * *'
open-pull-requests-limit: 15
- package-ecosystem: 'npm'
directory: '/'
# No cooldown block — updates proposed immediately on publish
The npm ecosystem entry (and the github-actions entry above it) have no cooldown configuration. Dependabot will happily propose an update to a package version that was published 10 minutes ago.
Why Is This Dangerous?
Software supply chain attacks have become one of the most impactful threat vectors in modern development. Attackers use several techniques that exploit fast-moving automated update pipelines:
- Typosquatting: Publishing a malicious package with a name very close to a popular one (e.g.,
lodahsinstead oflodash), hoping Dependabot or developers adopt it quickly. - Dependency confusion: Publishing a public package with the same name as an internal private package, tricking package managers into fetching the malicious version.
- Account hijacking: Compromising the npm credentials of a legitimate package maintainer and publishing a malicious version of a trusted package — as happened with
event-stream(2018),ua-parser-js(2021), andnode-ipc(2022).
In all three attack patterns, speed is the attacker's ally. The faster automated tooling proposes and merges an update, the less time the community has to detect and report the compromise.
For this repository — a Node.js library — the blast radius extends beyond the project itself. Any downstream consumer who installs this library after a compromised transitive dependency is adopted would also be affected.
The Specific Risk in This Configuration
The open-pull-requests-limit: 15 setting means Dependabot can open up to 15 PRs simultaneously. Combined with no cooldown, this creates a scenario where a wave of newly published (potentially malicious) package versions could all be proposed at once, increasing the cognitive load on reviewers and raising the chance that a bad update slips through.
The Fix
The fix is minimal but highly effective: add a cooldown block with default-days: 7 to the npm ecosystem entry.
Before and After
Before (vulnerable):
- package-ecosystem: 'github-actions'
schedule:
timezone: 'Europe/Berlin'
cronjob: '47 3 24 * *'
open-pull-requests-limit: 15
- package-ecosystem: 'npm'
directory: '/'
After (fixed):
- package-ecosystem: 'github-actions'
schedule:
timezone: 'Europe/Berlin'
cronjob: '47 3 24 * *'
open-pull-requests-limit: 15
cooldown:
default-days: 7
- package-ecosystem: 'npm'
directory: '/'
The actual diff from the pull request:
@@ -12,6 +12,8 @@ updates:
timezone: 'Europe/Berlin'
cronjob: '47 3 24 * *'
open-pull-requests-limit: 15
+ cooldown:
+ default-days: 7
- package-ecosystem: 'npm'
directory: '/'
How the Cooldown Works
The cooldown block tells Dependabot to wait a specified number of days after a package version is published before it will propose that version in a PR. With default-days: 7, a package version published on Monday won't appear in a Dependabot PR until the following Monday at the earliest.
This 7-day window is significant because:
- The npm security team and community researchers typically identify and report malicious packages within hours to days of publication.
- npm's automated malware scanning has time to run and flag suspicious packages.
- High-profile compromises of popular packages are usually reported on security mailing lists, Twitter/X, and GitHub advisories well within a week.
You can also configure ecosystem-specific or package-specific cooldowns for finer-grained control:
cooldown:
default-days: 7 # Wait 7 days for most packages
semver-major-days: 14 # Wait 14 days for major version bumps
semver-minor-days: 7 # Wait 7 days for minor version bumps
semver-patch-days: 2 # Wait only 2 days for patch releases
This tiered approach makes sense because major version bumps often introduce breaking changes or untested features, while patch releases are more likely to be routine security fixes you want quickly — but still with some buffer.
Prevention & Best Practices
1. Always Configure Cooldowns for Every Ecosystem
Every package-ecosystem entry in your dependabot.yml should have a cooldown block. It's easy to add one ecosystem and forget another:
updates:
- package-ecosystem: 'npm'
directory: '/'
cooldown:
default-days: 7
- package-ecosystem: 'github-actions'
directory: '/'
cooldown:
default-days: 7
- package-ecosystem: 'docker'
directory: '/'
cooldown:
default-days: 7
2. Use Semgrep to Enforce Cooldown Policies
The rule package_managers.dependabot.dependabot-missing-cooldown.dependabot-missing-cooldown can be integrated into your CI pipeline to catch missing cooldowns in code review:
# .github/workflows/semgrep.yml
- name: Run Semgrep
run: semgrep --config=p/supply-chain .github/dependabot.yml
3. Combine Cooldowns with Dependency Review
GitHub's Dependency Review Action can block PRs that introduce known-vulnerable packages. Used together with Dependabot cooldowns, you get defense in depth:
- Cooldown: prevents immediate adoption of newly published (potentially malicious) packages
- Dependency Review: blocks packages with known CVEs from being merged
4. Consider Pinning Dependencies
For high-security environments, consider pinning dependencies to exact versions (or even commit SHAs for GitHub Actions) rather than using range specifiers. This prevents automatic adoption of any new version until you explicitly update the pin.
# For GitHub Actions — pin to commit SHA, not tag
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
5. Monitor npm Security Advisories
Subscribe to the npm security advisories feed or use tools like Socket.dev or Snyk to get real-time alerts about compromised packages in your dependency tree.
Relevant Standards
- CWE-1104: Use of Unmaintained Third-Party Components — directly applicable to unvetted dependency updates
- OWASP A06:2021 — Vulnerable and Outdated Components: Covers risks from third-party dependencies
- SLSA Supply Chain Levels for Software Artifacts: Provides a framework for hardening the software supply chain
Key Takeaways
- The
npmecosystem entry in.github/dependabot.ymlhad nocooldownblock, meaning Dependabot would propose updates to packages published seconds ago — before any security vetting could occur. - A 7-day cooldown (
default-days: 7) is the minimum recommended buffer to allow community detection of malicious or compromised package releases before they reach your PR queue. - This is a Node.js library, so a compromised transitive dependency doesn't just affect this project — it propagates to all downstream consumers.
- The
open-pull-requests-limit: 15setting amplifies the risk — without a cooldown, up to 15 unvetted new package versions could flood your review queue simultaneously. - Both the
github-actionsandnpmecosystem entries needed cooldowns — it's easy to configure one and forget the other; audit all entries.
How Orbis AppSec Detected This
- Source: The
.github/dependabot.ymlconfiguration file, specifically thepackage-ecosystem: 'npm'entry at line 8, which controls automated dependency update behavior for all npm packages in the repository. - Sink: Dependabot's update pipeline — the absence of a
cooldownblock means any newly published npm package version is immediately eligible to be proposed in a pull request, with no waiting period. - Missing control: No
cooldownblock was present under thenpm(orgithub-actions)package-ecosystementry, removing the only time-based buffer between package publication and automated PR creation. - CWE: CWE-1104 — Use of Unmaintained Third-Party Components (insufficient controls around third-party dependency adoption).
- Fix: Added
cooldown: default-days: 7to thegithub-actionsecosystem entry in.github/dependabot.yml, enforcing a 7-day waiting period before Dependabot proposes updates to newly published package versions.
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 missing Dependabot cooldown is a small configuration gap with potentially large consequences. In a world where supply chain attacks on npm packages are increasingly common and sophisticated, giving automated tooling unrestricted access to the firehose of newly published packages is a real risk — especially for a Node.js library whose dependency vulnerabilities flow downstream to all consumers.
The fix here is just two lines of YAML:
cooldown:
default-days: 7
But those two lines represent a meaningful shift in your security posture: from "adopt anything, immediately" to "give the community a week to catch problems before we even look at it." Combined with dependency review actions, pinned versions, and security advisory monitoring, this cooldown configuration is a foundational piece of a robust supply chain security strategy.
Don't let your automation be faster than your security team.