How Missing Dependabot Cooldown Happens in GitHub Actions CI/CD and How to Fix It
Introduction
In a production repository's .github/dependabot.yml configuration at line 3, we discovered a high-severity supply chain vulnerability: the Dependabot github-actions ecosystem update entry had no cooldown period configured. This meant that whenever a new version of any GitHub Action dependency was published—whether legitimate or malicious—Dependabot would immediately create a pull request proposing the update.
This matters because supply chain attacks through package registries have surged dramatically. Attackers publish malicious versions of popular packages (or typosquatted variants), and automated tools like Dependabot can unknowingly fast-track these compromised versions into your CI/CD pipeline. Without a cooldown, there's zero buffer between publication and proposal.
Here's the vulnerable configuration that was in production:
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
groups:
github-actions:
patterns:
Notice the complete absence of any cooldown block—Dependabot would propose updates the moment they appeared on the registry.
The Vulnerability Explained
What Happens Without a Cooldown
When Dependabot monitors a package ecosystem (in this case, github-actions), it periodically checks for new versions of your dependencies. Without a cooldown period, the timeline looks like this:
- T+0 minutes: Attacker publishes a compromised version of a GitHub Action (e.g.,
actions/checkout@v5.0.1with injected credential-stealing code) - T+0 to T+24 hours: Dependabot detects the new version during its next scheduled check
- T+0 to T+24 hours: Dependabot opens a PR proposing the update
- T+minutes: A developer or auto-merge bot merges the PR
- T+minutes: Malicious code now runs in your CI/CD pipeline with access to secrets, tokens, and deployment credentials
The critical window—between when a malicious package is published and when the community detects and removes it—is typically 24-72 hours. Without a cooldown, Dependabot operates squarely within this danger zone.
The Specific Attack Scenario
For this repository, the github-actions ecosystem is particularly sensitive. GitHub Actions run with elevated privileges—they often have access to:
GITHUB_TOKENwith write permissions- Deployment secrets and API keys
- Cloud provider credentials for CD pipelines
- NPM/PyPI publish tokens
An attacker who compromises a GitHub Action dependency could:
- Exfiltrate all repository secrets
- Inject backdoors into build artifacts
- Modify source code through the compromised workflow
- Pivot to production infrastructure via deployment credentials
The groups configuration in this file (grouping all github-actions patterns together) actually amplifies the risk—a single grouped PR updating multiple actions could include a compromised one alongside legitimate updates, making it harder to spot during review.
Why Monthly Scheduling Doesn't Help
You might think that interval: "monthly" provides some protection since Dependabot only checks once a month. But this is misleading:
- The monthly interval means Dependabot checks at least monthly, but it can still propose updates to packages published just hours before the check
- A malicious package published 1 day before the monthly check would still be proposed immediately
- The interval controls how often Dependabot looks, not how old a version must be before it's proposed
The Fix
The fix adds a cooldown block with default-days: 7 to the github-actions ecosystem entry:
Before:
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
groups:
github-actions:
patterns:
After:
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
cooldown:
default-days: 7
groups:
github-actions:
patterns:
How This Solves the Problem
The cooldown block instructs Dependabot to wait 7 days after a new version is published before proposing it as an update. This creates a critical safety buffer:
- Day 0: New version published (potentially malicious)
- Days 1-3: Community discovers and reports the compromise
- Days 3-5: Registry removes or yanks the malicious version
- Day 7: Cooldown expires—but the malicious version is already gone
The 7-day default aligns with observed incident response timelines for supply chain attacks. Most malicious packages are detected and removed within 72 hours by automated security scanners (like Socket.dev, Snyk, and GitHub's own advisory database), giving a comfortable margin.
Why 7 Days Specifically?
- Too short (1-2 days): Many supply chain attacks aren't detected this quickly
- 7 days: Covers the vast majority of detection windows while still keeping dependencies reasonably current
- Too long (30+ days): Delays legitimate security patches that you actually want quickly
The default-days key applies to all packages in this ecosystem. If you need different cooldowns for specific packages, Dependabot also supports per-package overrides.
Prevention & Best Practices
1. Always Configure Cooldown for Every Ecosystem
If your dependabot.yml has multiple package-ecosystem entries (e.g., npm, pip, github-actions, docker), each one needs its own cooldown block:
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 7
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
cooldown:
default-days: 7
2. Pin GitHub Actions to Full Commit SHAs
Beyond cooldown, pin actions to specific commit SHAs rather than tags:
# Vulnerable to tag-based attacks:
- uses: actions/checkout@v4
# More secure - pinned to exact commit:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
3. Enable Dependabot Security Advisories
Ensure dependabot alerts are enabled alongside version updates. Alerts use GitHub's advisory database to flag known-vulnerable versions, complementing the cooldown approach.
4. Use Semgrep or Similar SAST Tools
Static analysis tools can detect misconfigurations in CI/CD files. The rule package_managers.dependabot.dependabot-missing-cooldown.dependabot-missing-cooldown specifically catches this pattern.
5. Implement PR Review Policies for Dependency Updates
- Require manual review for dependency PRs (disable auto-merge for Dependabot)
- Use tools like
step-security/harden-runnerto detect anomalous behavior in workflows - Review changelogs and diffs before merging dependency updates
Key Takeaways
- The
cooldownblock independabot.ymlis not optional—without it, your automated dependency management becomes a supply chain attack accelerator - GitHub Actions dependencies are especially high-risk because they execute with elevated CI/CD privileges and access to repository secrets
- 7 days is the minimum recommended cooldown based on observed supply chain attack detection timelines; most malicious packages are flagged within 72 hours
- Grouped dependency updates (like the
github-actionsgroup in this config) amplify risk by bundling potentially compromised packages with legitimate updates in a single PR - Monthly scheduling intervals do NOT substitute for cooldown—they control check frequency, not version age requirements
How Orbis AppSec Detected This
- Source: Newly published package versions on the GitHub Actions marketplace and other package registries
- Sink: The
package-ecosystem: "github-actions"entry at.github/dependabot.yml:3that would immediately propose updates without age verification - Missing control: No
cooldownblock to enforce a minimum age for proposed package versions - CWE: CWE-1104 (Use of Unmaintained Third Party Components) / CWE-829 (Inclusion of Functionality from Untrusted Control Sphere)
- Fix: Added
cooldown: default-days: 7to thegithub-actionsecosystem entry, requiring all proposed updates to be at least 7 days old
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—it's about controlling the velocity at which unvetted external code enters your pipeline. A missing Dependabot cooldown is a subtle but high-impact misconfiguration that turns your automated dependency management from a security tool into a potential attack vector.
The fix is simple: two lines of YAML. But the protection it provides—a 7-day buffer against malicious package publications—can be the difference between catching a supply chain attack and having your CI/CD secrets exfiltrated. Audit your dependabot.yml files today, and ensure every package-ecosystem entry includes a cooldown block.
References
- CWE-1104: Use of Unmaintained Third Party Components
- CWE-829: Inclusion of Functionality from Untrusted Control Sphere
- GitHub Docs: Dependabot cooldown configuration
- OWASP: Vulnerable and Outdated Components
- Semgrep Registry: Dependabot rules
- fix: this dependabot configuration does not set a co... in... — Pull request with the automated fix