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 supply chain security vulnerability hiding in plain sight — not in application code, but in the .github/dependabot.yml configuration file at line 4. The file configured automated dependency updates for both GitHub Actions and npm packages with a weekly schedule, but it was missing a critical safety mechanism: a cooldown period.
This matters because this repository is a Node.js library — vulnerabilities in its dependency management don't just affect one application; they propagate to every downstream consumer who installs this package. Without a cooldown, a threat actor who publishes a malicious package version could see it automatically proposed as an update within hours, potentially merged by an unsuspecting maintainer, and then distributed to thousands of downstream users.
The Vulnerability Explained
Here's the vulnerable dependabot.yml configuration (simplified to show the relevant sections):
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
groups:
actions:
patterns: ['*']
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
day: monday
groups:
npm:
patterns: ['*']
Notice what's missing: there is no cooldown block in either ecosystem entry. This means that when Dependabot runs its weekly check on Monday, it will propose updates to any package version that exists at that moment — even if it was published seconds earlier.
How This Gets Exploited: A Concrete Attack Scenario
-
Attacker identifies the target: They see this Node.js library uses Dependabot with no cooldown (this information is public in the
.github/dependabot.ymlfile on GitHub). -
Attacker compromises or typosquats a dependency: They publish a malicious version of a package in the
npmecosystem that this library depends on — or they compromise an existing package maintainer's account and push a backdoored release. -
Timing the attack: They publish the malicious version on a Sunday night. On Monday morning, Dependabot runs its weekly check and immediately proposes a PR to update to the malicious version.
-
The PR looks legitimate: Because the update is grouped under the
npmgroup withpatterns: ['*'], it may be bundled with other legitimate updates, making the malicious change harder to spot. -
Downstream impact: If merged, the malicious dependency becomes part of the library. Every downstream consumer who runs
npm installornpm updatepulls in the compromised code.
The same attack vector applies to the github-actions ecosystem — a compromised GitHub Action version could execute arbitrary code in CI/CD pipelines, potentially exfiltrating secrets, modifying builds, or injecting backdoors.
Why Weekly Scheduling Isn't Enough
A common misconception is that interval: weekly provides adequate protection because it limits how often updates are checked. However, the schedule only controls frequency of checks, not the age of packages being proposed. A package published 1 minute before the weekly check runs will still be immediately proposed. The cooldown period is an orthogonal control that ensures packages have existed for a minimum duration before being considered.
The Fix
The fix adds a cooldown block with default-days: 7 to both package ecosystem entries in .github/dependabot.yml:
Before:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
groups:
actions:
patterns: ['*']
After:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
cooldown:
default-days: 7
groups:
actions:
patterns: ['*']
The identical change was applied to the npm ecosystem entry:
Before:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
day: monday
groups:
npm:
patterns: ['*']
After:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
day: monday
cooldown:
default-days: 7
groups:
npm:
patterns: ['*']
Why This Solves the Problem
With default-days: 7, Dependabot will now ignore any package version that was published less than 7 days ago. This 7-day buffer provides:
-
Community vetting time: If a package version is malicious, the community typically identifies and reports it within days. The npm security team can yank compromised packages before the cooldown expires.
-
Stability assurance: Newly published versions sometimes have bugs that are quickly patched. Waiting 7 days means you're more likely to get a stable release.
-
Attack window elimination: An attacker can no longer time a malicious publish to coincide with Dependabot's schedule. They would need the malicious version to survive public scrutiny for a full week.
Why Both Ecosystems Need the Fix
The change was applied to both the github-actions and npm entries because:
github-actions: Compromised Actions execute directly in CI/CD with access to repository secrets, deployment keys, and build artifacts.npm: Compromised npm packages become transitive dependencies for all downstream consumers of this Node.js library.
Both attack surfaces are critical and require the cooldown protection independently.
Prevention & Best Practices
-
Always configure cooldown periods: Any new
dependabot.ymlfile should includecooldown: default-days: 7(or higher) for every package ecosystem entry from day one. -
Consider longer cooldowns for critical dependencies: For security-sensitive dependencies, you might use ecosystem-specific overrides to set longer cooldown periods.
-
Audit your Dependabot configuration regularly: Treat
.github/dependabot.ymlas a security-critical file. Include it in security reviews and code audits. -
Use lockfiles and integrity checks: Combine cooldown periods with
npm audit, lockfile verification, and Subresource Integrity (SRI) hashes where possible. -
Enable Dependabot security alerts separately: Cooldown periods apply to version updates only. Security advisories (via
dependabot alerts) should still be acted upon immediately. -
Scan configuration files with static analysis: Use tools like Semgrep with rules targeting Dependabot misconfigurations to catch these issues in CI.
-
Review grouped PRs carefully: The
patterns: ['*']grouping means all dependency updates come in a single PR. While convenient, this makes it easier to overlook a malicious update hiding among legitimate ones. Consider more granular grouping for critical dependencies.
Key Takeaways
- A
dependabot.ymlwithoutcooldownis an open door for supply chain attacks — the weekly schedule provides zero protection against newly published malicious packages. - This Node.js library's missing cooldown affected two ecosystems (
github-actionsandnpm), meaning both CI/CD pipelines and downstream consumers were at risk. - The
patterns: ['*']grouping amplified the risk by bundling all updates together, making it easier for a malicious update to slip through review unnoticed. - 7 days is the minimum recommended cooldown — it aligns with typical response times for npm security advisories and community reporting of compromised packages.
- Configuration-as-code vulnerabilities are often overlooked because they don't involve traditional application logic, but they can have outsized impact on supply chain security.
How Orbis AppSec Detected This
- Source: Newly published package versions in the npm registry and GitHub Actions marketplace that Dependabot would immediately propose without vetting.
- Sink: The
dependabot.ymlconfiguration at lines 4 and 17 (thepackage-ecosystementries) which control automated PR creation for dependency updates. - Missing control: No
cooldownblock was present in either ecosystem entry, meaning zero delay between package publication and update proposal. - CWE: CWE-1395 (Dependency on Vulnerable Third-Party Component)
- Fix: Added
cooldown: default-days: 7to both thegithub-actionsandnpmpackage ecosystem entries in.github/dependabot.yml.
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 application code — it's about securing the entire pipeline that brings external code into your project. A missing cooldown in dependabot.yml is a subtle but high-impact vulnerability that could allow freshly published malicious packages to be automatically proposed and potentially merged into your codebase.
For this Node.js library, the stakes were particularly high: any compromised dependency would flow downstream to every consumer. The 2-line fix — adding cooldown: default-days: 7 — creates a critical safety buffer that gives the security community time to identify and remove malicious packages before they reach your repository.
If you maintain any project with Dependabot enabled, check your dependabot.yml today. If you don't see a cooldown block, you're running without a safety net.