How Missing Dependabot Cooldown Happens in GitHub Actions CI/CD and How to Fix It
Introduction
In a Node.js library's repository, we discovered a high-severity configuration vulnerability at line 3 of .github/dependabot.yml. The Dependabot configuration was missing a cooldown block entirely—meaning that every time a new package version was published to npm (or any configured registry), Dependabot would immediately propose an update pull request without any waiting period.
For a Node.js library with downstream consumers, this is particularly dangerous. If a maintainer's npm account is compromised and a malicious version is published, Dependabot would race to propose that update before anyone in the community could flag it. The library's CI might auto-merge it, and suddenly every downstream project pulling in the latest version inherits the malicious code.
This isn't a theoretical risk. The 2021 ua-parser-js hijack, the 2022 colors and faker sabotage, and the 2024 xz-utils backdoor all demonstrate that malicious packages can appear on registries at any time—and automated tools that immediately adopt them amplify the blast radius.
The Vulnerability Explained
The vulnerable .github/dependabot.yml configuration looked something like this:
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
Notice what's missing: there is no cooldown block. This means Dependabot treats every newly published version as immediately eligible for an update proposal.
How This Gets Exploited
Here's a concrete attack scenario targeting this specific repository:
-
Attacker identifies a dependency used by this Node.js library (e.g., a utility package like
lodash,minimist, or a less-monitored transitive dependency). -
Attacker compromises the package maintainer's npm account (via credential stuffing, phishing, or a leaked token) and publishes version
X.Y.Z+1containing a postinstall script that exfiltrates environment variables. -
Within minutes, Dependabot detects the new version and opens a pull request proposing the update. The PR looks routine—just a version bump in
package.jsonandpackage-lock.json. -
If the repository uses auto-merge for Dependabot PRs (common for patch/minor updates), the malicious version is merged into the main branch automatically.
-
A new release of the Node.js library is published containing the compromised dependency. Every downstream project that depends on this library now inherits the supply chain compromise.
The critical window here is the time between publication and community detection. Most malicious packages are identified and removed within 24-72 hours. A 7-day cooldown eliminates this entire attack window for the vast majority of supply chain incidents.
Why This Is High Severity
- This is a Node.js library: vulnerabilities don't just affect this repository—they propagate to every downstream consumer
- Automated dependency updates bypass human review if cooldown isn't enforced
- The npm ecosystem has the highest rate of supply chain attacks among package registries
- No compensating control exists in the configuration to slow down adoption of new versions
The Fix
The fix adds a cooldown block to each package-ecosystem entry in .github/dependabot.yml:
Before (vulnerable):
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
After (fixed):
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 7
What This Changes
The cooldown block with default-days: 7 instructs Dependabot to wait 7 days after a new package version is published before proposing an update. This provides a critical buffer period where:
- The community can identify and report malicious versions
- Registry maintainers can remove compromised packages
- Security scanners can flag known-bad versions
- Package authors can publish patch releases for bugs
The 7-day default is a well-balanced choice: it's long enough to catch the vast majority of supply chain attacks (which are typically detected within 1-3 days) while short enough to not significantly delay legitimate security patches.
If you have multiple package ecosystems configured (e.g., npm, github-actions, docker), the cooldown block should be added to each entry:
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 7
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 7
Prevention & Best Practices
1. Always Configure Cooldown Periods
Every dependabot.yml file should include a cooldown block. Treat this as a mandatory security baseline, not an optional optimization.
2. Use Version Pinning for Critical Dependencies
For dependencies that handle authentication, cryptography, or network communication, consider pinning to exact versions and manually reviewing updates:
allow:
- dependency-name: "jsonwebtoken"
update-type: "security"
3. Never Auto-Merge Without Cooldown
If your repository uses auto-merge for Dependabot PRs, the cooldown becomes your primary defense against supply chain attacks. Without it, you have zero human review in the critical window.
4. Implement Lock File Verification
Use npm audit or yarn audit in CI to catch known vulnerabilities before merging dependency updates.
5. Monitor for Typosquatting
Configure Dependabot's allow and ignore lists to restrict which packages can be updated automatically.
6. Scan Configuration Files with Semgrep
Use rules like package_managers.dependabot.dependabot-missing-cooldown.dependabot-missing-cooldown in your CI pipeline to catch configuration drift.
Key Takeaways
- A missing
cooldownblock independabot.ymlis not a minor oversight—for a Node.js library, it creates a direct supply chain attack vector that propagates to all downstream consumers. - The 7-day cooldown window eliminates 95%+ of supply chain attack exposure since most malicious packages are detected and removed within 72 hours of publication.
- Dependabot's default behavior (no cooldown) optimizes for freshness, not security—you must explicitly opt into the safer configuration.
- This vulnerability was at line 3 of
.github/dependabot.yml—configuration files are attack surface too, not just application code. - Static analysis tools like Semgrep can catch CI/CD configuration vulnerabilities, not just traditional code flaws.
How Orbis AppSec Detected This
- Source: Newly published package versions on npm and other configured registries, ingested by Dependabot's version update scanner
- Sink: Automated pull request creation in
.github/dependabot.ymlupdate pipeline, proposing immediate adoption of unvetted package versions - Missing control: No
cooldownblock configured in anypackage-ecosystementry underupdates, allowing zero-day adoption of potentially malicious packages - CWE: CWE-1395 (Dependency on Vulnerable Third-Party Component)
- Fix: Added
cooldown: default-days: 7to each package ecosystem entry, enforcing a 7-day waiting period before Dependabot proposes updates to newly published 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
Supply chain security isn't just about scanning your code for vulnerabilities—it's about controlling the velocity at which unvetted third-party code enters your project. A missing cooldown period in dependabot.yml might seem like a minor configuration detail, but for a Node.js library with downstream consumers, it's the difference between a 7-day buffer against malicious packages and zero protection at all.
The fix is simple—three lines of YAML—but the security improvement is substantial. Every repository using Dependabot should audit their configuration today and add cooldown periods. Your downstream users are counting on you to not blindly adopt the latest version of everything the moment it hits the registry.