How Dependabot Missing Cooldown Happens in GitHub Actions and How to Fix It
Introduction
The .github/dependabot.yml file is the gatekeeper for automated dependency updates. When it is misconfigured, it can become an unguarded door for supply chain attacks. In this repository—a Node.js library whose vulnerabilities flow directly to every downstream consumer—Dependabot was configured to check for updates on a weekly schedule across three separate package-ecosystem entries, but none of them included a cooldown block. That means the moment a malicious actor publishes a new version of a dependency, Dependabot could surface it as an update candidate before a single security researcher has had the chance to flag it.
This post walks through exactly what was misconfigured in .github/dependabot.yml, why it matters for a Node.js library in particular, and how adding six lines of YAML closes the gap.
The Vulnerability Explained
What is a Dependabot Cooldown Period?
Dependabot's cooldown feature (introduced in 2024) lets you specify a minimum age—in days—that a package version must reach before Dependabot will propose it as an update. Without it, Dependabot operates on a "latest is best" assumption and will happily open a pull request for a package version that was published five minutes ago.
The Vulnerable Configuration
Before the fix, .github/dependabot.yml contained three package-ecosystem entries, all structured like this:
# VULNERABLE — no cooldown block
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
- package-ecosystem: "npm"
directory: "/playground"
schedule:
interval: "weekly"
day: "monday"
The Semgrep rule package_managers.dependabot.dependabot-missing-cooldown.dependabot-missing-cooldown matched at line 9 of this file—the first updates entry—and the same pattern repeated across all three ecosystems.
Why This Is a High-Severity Issue
The absence of a cooldown period is not just a theoretical concern. Supply chain attacks via package registries are a well-documented and growing threat:
- Typosquatting and dependency confusion: An attacker publishes a malicious package with a name close to a popular one. Without a cooldown, Dependabot may propose it within hours.
- Account takeover: A legitimate package maintainer's npm account is compromised. The attacker publishes a new version with a backdoor. Without a cooldown, automated pipelines can pull it in before the compromise is detected.
- Protestware and sabotage: A maintainer deliberately introduces malicious code in a new release. The 7-day window gives the community time to identify and report the issue.
Attack Scenario Specific to This Repository
This is a Node.js library—meaning it is a dependency of other projects. Consider this chain:
- An attacker compromises a popular npm package that this library depends on.
- The attacker publishes version
X.Y.Z+1with a maliciouspostinstallscript. - Dependabot, running on Monday morning, sees the new version and opens a PR.
- A developer, trusting the automated update, merges it.
- The malicious code is now part of this library's published artifact.
- Every downstream consumer who installs or updates this library executes the malicious script.
Without a cooldown, steps 2–4 can happen within a single business day. With a 7-day cooldown, the community has a full week to detect and report the malicious version before it ever reaches a Dependabot PR.
The Fix
What Changed
The fix adds a cooldown block with default-days: 7 to all three package-ecosystem entries in .github/dependabot.yml. Here is the complete before/after diff:
Before (vulnerable):
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
# ← no cooldown block
After (fixed):
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
cooldown:
default-days: 7
The same change was applied to both npm entries—the one targeting the root / directory and the one targeting /playground:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
cooldown:
default-days: 7
- package-ecosystem: "npm"
directory: "/playground"
schedule:
interval: "weekly"
day: "monday"
cooldown:
default-days: 7
Why All Three Entries Needed the Fix
Each package-ecosystem entry is evaluated independently by Dependabot. A cooldown on the root npm entry does not cascade to the /playground npm entry or to the github-actions entry. Leaving any one of them without a cooldown would preserve the attack surface. All three entries were updated to ensure consistent protection across the entire dependency update pipeline.
How default-days: 7 Works
The cooldown block supports two sub-keys:
default-days: The minimum number of days a package version must be published before Dependabot will propose it. Set to7here.semver-patch-days,semver-minor-days,semver-major-days(optional): Override the default for specific semver bump types. For example, you might trust patch releases after 3 days but require 14 days for major version bumps.
The configuration in this fix uses default-days: 7 as a sensible, balanced default—long enough for the community to detect obvious malicious releases, short enough that legitimate security patches still reach the project within a reasonable timeframe.
Prevention & Best Practices
Always Include a Cooldown Block
Make cooldown: default-days: 7 a standard template element in every dependabot.yml you create. The GitHub documentation explicitly recommends this as a supply chain hardening measure.
Tune Cooldowns by Semver Level
For higher-risk projects, consider a tiered approach:
cooldown:
default-days: 7
semver-patch-days: 3 # Patch releases are lower risk
semver-minor-days: 7 # Minor releases get the standard wait
semver-major-days: 14 # Major releases warrant extra scrutiny
Combine Cooldown with Dependency Review
A cooldown period is one layer of defense. Pair it with:
- GitHub's Dependency Review Action: Blocks PRs that introduce known-vulnerable packages.
npm auditin CI: Catches vulnerabilities in the lock file on every push.- Signed commits and provenance: Use npm's package provenance feature to verify that a published package was built from a known source.
Use Static Analysis to Catch Misconfigurations
Semgrep's rule package_managers.dependabot.dependabot-missing-cooldown.dependabot-missing-cooldown can be run in CI to catch this issue before it reaches production. Add it to your .semgrep.yml or use the Semgrep GitHub Action to scan configuration files on every pull request.
Relevant Standards
- CWE-1357: Reliance on Insufficiently Trustworthy Component — the authoritative classification for this class of vulnerability.
- OWASP A06:2021 — Vulnerable and Outdated Components: Automated dependency updates without vetting controls fall squarely in this category.
- SLSA (Supply-chain Levels for Software Artifacts): The SLSA framework recommends controlling the provenance and age of dependencies as part of supply chain integrity.
Key Takeaways
- A weekly Dependabot schedule is not a cooldown. The
schedule.intervalcontrols when Dependabot looks for updates; thecooldownblock controls how old a version must be before it is proposed. These are independent settings and both are needed. - All three
package-ecosystementries in.github/dependabot.ymlrequired individual fixes. Cooldown settings do not inherit or cascade across entries—each ecosystem is configured in isolation. - This is a Node.js library, making the blast radius unusually large. A malicious package merged here doesn't just affect this project; it affects every project that depends on it.
- Seven days is the community-recommended minimum. Most high-profile supply chain attacks (e.g., the
event-streamincident, thenode-ipcprotestware) were publicly identified within 24–72 hours of publication. A 7-day window provides meaningful protection. - Static analysis can and should catch this. The Semgrep rule that detected this issue is free and can be integrated into any CI pipeline to prevent the misconfiguration from being introduced in the first place.
How Orbis AppSec Detected This
- Source: The
updatesentries in.github/dependabot.ymldefine which package ecosystems and directories Dependabot monitors. Without a cooldown, every newly published package version is a potential source of malicious input to the dependency graph. - Sink: The Dependabot pull request creation process—specifically, the three
package-ecosystementries at lines 9, 17, and 25 of.github/dependabot.yml—where newly published versions are surfaced without any age-based filtering. - Missing control: The
cooldownblock was entirely absent from all three entries, meaning no minimum publication age was enforced before Dependabot would propose a version update. - CWE: CWE-1357 — Reliance on Insufficiently Trustworthy Component.
- Fix: Added
cooldown: default-days: 7to each of the threepackage-ecosystementries, enforcing a 7-day waiting period before any newly published package version is proposed as a Dependabot update.
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 cooldown block in dependabot.yml is easy to overlook—it doesn't break any builds, it doesn't throw any errors, and the configuration looks perfectly valid without it. But for a Node.js library with downstream consumers, it is a meaningful gap in the supply chain security posture. The fix is six lines of YAML per ecosystem entry, and the protection it provides—a 7-day buffer between a package being published and Dependabot proposing it—is disproportionately valuable relative to the effort required.
Supply chain attacks are increasingly the vector of choice for sophisticated adversaries precisely because they exploit the trust that developers place in automated tooling. Configuring that tooling defensively, including something as simple as a cooldown period, is a concrete and measurable step toward a more resilient software supply chain.