Introduction
In a Node.js library's repository, we discovered a high severity supply chain misconfiguration in .github/dependabot.yml at line 8. The file configured two package ecosystems—npm and github-actions—with weekly update schedules, reviewer assignments, and dependency grouping, but critically omitted a cooldown block from both entries. This meant that the moment a new version of any dependency was published to npm or the GitHub Actions marketplace, Dependabot could immediately propose it for adoption—even if that version had been published minutes ago by a threat actor who had compromised a maintainer's account.
For a Node.js library, this is especially dangerous: vulnerabilities don't just affect the repository itself—they propagate to every downstream consumer who installs the package.
The Vulnerability Explained
What's a Dependabot Cooldown?
GitHub's Dependabot can be configured with a cooldown block that tells it to wait a specified number of days after a package version is published before proposing an update. This waiting period serves as a critical buffer: it gives the open-source community, security researchers, and automated scanning tools time to identify and flag compromised or unstable releases.
The Vulnerable Configuration
Here's what the original .github/dependabot.yml looked like for the npm ecosystem entry:
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "endlesstrax"
groups:
# ...
And similarly for the github-actions ecosystem:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "endlesstrax"
groups:
# ...
Neither entry includes a cooldown block. This means Dependabot will propose updates to packages the instant they appear—zero delay.
How Could This Be Exploited?
Consider a realistic attack scenario specific to this repository:
-
Account Takeover: An attacker compromises the npm credentials of a maintainer of one of this library's dependencies (e.g., a utility package in the grouped dependencies).
-
Malicious Publish: The attacker publishes a new patch version (e.g.,
1.2.4) containing a post-install script that exfiltrates environment variables or injects a backdoor. -
Immediate Proposal: Because there's no cooldown, Dependabot creates a PR within the next weekly check cycle—potentially within hours of the malicious publish.
-
Merge and Propagate: The reviewer (
endlesstrax) sees what looks like a routine patch bump in a grouped PR. If merged, the malicious code enters the library, and every downstream consumer who runsnpm installornpm updatepulls in the compromised dependency. -
Supply Chain Cascade: Since this is a Node.js library consumed by others, the blast radius extends far beyond this single repository.
This isn't theoretical. The ua-parser-js, event-stream, and colors/faker incidents all involved malicious versions being published and rapidly adopted before the community could react.
Why Weekly Scheduling Isn't Enough
Some developers assume that a schedule: interval: "weekly" setting provides protection because it limits check frequency. However, the schedule only controls when Dependabot looks for updates—not how old a version must be before it's considered safe to propose. A package published 6 days and 23 hours ago would still be proposed on the next weekly check with no cooldown.
The Fix
The fix adds a cooldown block with default-days: 7 to both package ecosystem entries in .github/dependabot.yml:
Before (npm ecosystem, line 8):
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "endlesstrax"
After:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 7
reviewers:
- "endlesstrax"
Before (github-actions ecosystem):
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "endlesstrax"
After:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
cooldown:
default-days: 7
reviewers:
- "endlesstrax"
Why This Works
The cooldown: default-days: 7 directive instructs Dependabot to ignore any package version that was published fewer than 7 days ago. This 7-day window provides:
- Community vetting time: The npm security team, GitHub Advisory Database, and community reporters typically identify compromised packages within hours to days of publication.
- Automated scanning coverage: Services like Socket.dev, Snyk, and npm's own malware detection pipeline have time to analyze new versions.
- Stability assurance: Even non-malicious packages sometimes publish broken versions that get yanked within days.
Both ecosystem entries needed the fix because:
- npm: Direct dependency risk—malicious packages execute code during install or at runtime.
- github-actions: CI/CD pipeline risk—malicious actions can exfiltrate secrets, modify builds, or inject artifacts.
Prevention & Best Practices
1. Always Configure Cooldown Periods
For any dependabot.yml configuration, include a cooldown block as standard practice:
cooldown:
default-days: 7
For highly sensitive projects, consider extending to 14 or even 30 days.
2. Use Dependency Grouping Carefully
While grouping dependencies (as this repository does) reduces PR noise, it can also obscure individual malicious updates within a batch. Combine grouping with cooldown periods and careful review.
3. Enable Lock File Verification
Ensure your package-lock.json or yarn.lock integrity hashes are verified during CI. This catches tampered packages even if they bypass the cooldown.
4. Adopt Supply Chain Security Tools
- npm audit signatures: Verify registry signatures on packages
- Socket.dev: Detect suspicious package behavior
- Sigstore/npm provenance: Verify packages were built from their claimed source
5. Lint Your Dependabot Configuration
Use Semgrep or similar tools to scan your .github/dependabot.yml for misconfigurations as part of your CI pipeline:
# Example CI step
- name: Scan Dependabot config
run: semgrep --config "p/supply-chain" .github/
6. Pin GitHub Actions by SHA
For the github-actions ecosystem specifically, pin actions to full commit SHAs rather than tags to prevent tag-based attacks.
Key Takeaways
- A
cooldown: default-days: 7block is essential in everypackage-ecosystementry—not just one. This repository had two ecosystems (npmandgithub-actions) and both were vulnerable. - Weekly scheduling is not a substitute for cooldown—the schedule controls check frequency, not version age requirements. These are orthogonal security controls.
- Node.js libraries have amplified supply chain risk because their vulnerabilities propagate to all downstream consumers via
npm install. - Both runtime dependencies (npm) and CI/CD dependencies (github-actions) need cooldown protection—attackers target both vectors.
- The
endlesstraxreviewer could have unknowingly merged a malicious grouped PR if a compromised package was published and immediately proposed by Dependabot.
How Orbis AppSec Detected This
- Source: Newly published package versions on npm registry and GitHub Actions marketplace (external, untrusted input to the dependency update pipeline)
- Sink:
.github/dependabot.ymlconfiguration at lines 8 and 21—thepackage-ecosystementries fornpmandgithub-actionsthat feed directly into automated PR creation - Missing control: No
cooldownblock to enforce a minimum age requirement on proposed package versions before they're surfaced to maintainers - CWE: CWE-1104 (Use of Unmaintained Third Party Components) — broadly applicable to supply chain trust decisions
- Fix: Added
cooldown: default-days: 7to both package-ecosystem entries, ensuring a 7-day quarantine period before newly published versions are proposed
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 attacks continue to be one of the most effective vectors for compromising software at scale. A missing Dependabot cooldown period might seem like a minor configuration oversight, but for a Node.js library with downstream consumers, it represents a direct path from a compromised upstream package to production systems. The two-line fix—adding cooldown: default-days: 7 to each ecosystem entry—creates a critical 7-day buffer that leverages the collective vigilance of the open-source community as a security control. Always configure cooldown periods in your Dependabot configuration, and treat your CI/CD configuration files with the same security rigor as your application code.