How Dependabot Missing Cooldown Happens in GitHub Actions and How to Fix It
Introduction
The .github/dependabot.yml file is the unsung gatekeeper of your dependency supply chain. It decides when Dependabot wakes up, which ecosystems it watches, and — critically — how quickly it proposes adopting brand-new package versions. In this Node.js library, a static analysis scan flagged that neither the npm nor the github-actions ecosystem entries included a cooldown block. That omission meant Dependabot was configured to open pull requests for packages the instant they appeared on the registry, with no waiting period whatsoever.
For a library whose vulnerabilities ripple downstream to every consumer, that is a meaningful risk surface — and one that is trivially easy to close.
The Vulnerability Explained
What "no cooldown" actually means
When Dependabot runs its weekly check and finds a new package version, it compares the publication timestamp against the current time. Without a cooldown setting, the threshold is effectively zero days — any version published even minutes ago is eligible to be proposed.
The vulnerable configuration looked like this (lines 7–11 and 23–27 of .github/dependabot.yml):
# npm ecosystem — BEFORE
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 5
groups:
# The toolchain is dev-only (the package ships no runtime dependencies)
...
# github-actions ecosystem — BEFORE
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
groups:
actions:
patterns:
...
Neither entry contains a cooldown block. Both ecosystems will happily surface a package version that was published seconds before the scheduled run.
Why this is a real threat
Supply-chain attacks against the npm and GitHub Actions ecosystems are not theoretical. Attackers use several well-documented techniques:
- Package hijacking: Gaining control of a maintainer's account and publishing a malicious patch or minor release under a trusted package name.
- Dependency confusion: Publishing a private-package name to the public registry with a higher version number, tricking automated tooling into pulling the attacker's code.
- Typosquatting with version bumps: Publishing a lookalike package and waiting for automated tools to pick it up.
In all three scenarios, the attack window is the period between publication and detection. Security researchers, registry abuse teams, and automated scanners typically need 24–72 hours to identify and remove malicious packages. A 7-day cooldown comfortably covers that window.
The specific risk for this project
Because this is a Node.js library, its package.json influences every downstream project that installs it. A malicious transitive dependency introduced via a zero-cooldown Dependabot PR could silently exfiltrate secrets, tamper with build artifacts, or open a reverse shell — and the blast radius extends to every consumer of the library, not just this repository.
The GitHub Actions ecosystem carries equal risk: a compromised action pinned to a new tag could exfiltrate GITHUB_TOKEN, steal repository secrets, or tamper with release artifacts.
The Fix
The fix is four lines of YAML — two lines added to each ecosystem entry:
# npm ecosystem — AFTER
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 7 # ← NEW
open-pull-requests-limit: 5
groups:
...
# github-actions ecosystem — AFTER
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 7 # ← NEW
groups:
actions:
patterns:
...
What the cooldown block does
The cooldown.default-days setting tells Dependabot to skip any package version whose publication date is less than N days old. With default-days: 7, a version published on Monday will not appear in a Dependabot PR until the following Monday at the earliest — regardless of how many weekly runs occur in between.
You can also tune cooldowns per-dependency type if your project has mixed risk tolerance:
cooldown:
default-days: 7
semver-patch-days: 3 # Patch releases are lower risk — wait less
semver-minor-days: 5 # Minor releases — medium wait
semver-major-days: 14 # Major releases — extra scrutiny
For this fix, default-days: 7 was chosen as a sensible, conservative baseline that matches GitHub's own recommendation.
Why both ecosystems needed the change
The diff touches two separate package-ecosystem entries. Each entry is an independent Dependabot configuration object; a cooldown block on the npm entry has no effect on the github-actions entry, and vice versa. Fixing only one would leave the other ecosystem unprotected — a subtle but important detail when reviewing the change.
Prevention & Best Practices
1. Always set a cooldown in new Dependabot configurations
Make cooldown: default-days: 7 part of your team's Dependabot configuration template. If you use a repository template or an internal cookiecutter, bake it in so that every new project inherits the setting.
2. Consider ecosystem-specific risk profiles
GitHub Actions versions (especially those pinned to mutable tags like v3) can change behavior without a version bump. Consider using semver-major-days: 14 for actions to allow extra time for community review of major releases.
3. Combine cooldown with SHA pinning for actions
For the highest-assurance posture, pin GitHub Actions to a full commit SHA rather than a tag, and use a tool like Dependabot's groups alongside cooldown to batch and review updates deliberately.
4. Lint your Dependabot configuration in CI
The Semgrep rule package_managers.dependabot.dependabot-missing-cooldown.dependabot-missing-cooldown can be run in your CI pipeline to catch regressions — for example, if a new package-ecosystem entry is added without a cooldown block.
# .github/workflows/semgrep.yml (excerpt)
- name: Run Semgrep
run: semgrep --config=p/supply-chain .github/
5. OWASP and CWE alignment
This issue aligns with:
- OWASP A06:2021 – Vulnerable and Outdated Components: Using components without verifying their integrity and provenance.
- CWE-1104 – Use of Unmaintained Third-Party Components: Insufficient controls over third-party software lifecycle management.
Key Takeaways
- Both ecosystem entries in
.github/dependabot.ymlrequired the fix independently — acooldownblock on one entry does not propagate to others. - Zero-cooldown Dependabot is an automated supply-chain attack surface: any malicious package published to npm or the Actions marketplace could reach your PR queue within hours.
- Seven days is the recommended default because it exceeds the typical 24–72 hour window that security teams need to detect and remove malicious packages from public registries.
- This Node.js library's downstream consumers were also at risk — a compromised transitive dependency introduced here would affect every project that installs this package.
- The Semgrep rule
dependabot-missing-cooldownreliably detects this pattern and can be integrated into CI to prevent regressions when new ecosystem entries are added.
How Orbis AppSec Detected This
- Source: The
.github/dependabot.ymlconfiguration file, specifically theupdatesarray entries for thenpmandgithub-actionspackage ecosystems (lines 6 and 22). - Sink: Dependabot's version-update pipeline — the point at which a newly published package version is evaluated for PR creation with no time-based gate.
- Missing control: Neither
package-ecosystementry contained acooldownblock, meaning the effective wait period before proposing any new package version was zero days. - CWE: CWE-1104 – Use of Unmaintained Third-Party Components (supply-chain lifecycle control).
- Fix: Added
cooldown: default-days: 7to both thenpmandgithub-actionsentries in.github/dependabot.yml, introducing a mandatory 7-day waiting period before Dependabot can propose any newly published package version.
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 is one of the easiest supply-chain risks to introduce and one of the easiest to fix. Four lines of YAML in .github/dependabot.yml — two for npm, two for github-actions — transform Dependabot from a tool that could inadvertently fast-track a malicious package into one that gives the security community a full week to catch problems before they reach your codebase.
For a Node.js library with downstream consumers, that 7-day buffer is not just a nice-to-have: it is a meaningful layer of defense against the kind of supply-chain attacks that have compromised high-profile projects in recent years. Keep your Dependabot configurations linted, template the cooldown block into every new project, and treat your .github/dependabot.yml with the same security scrutiny you apply to your application code.