How Do I Configure Dependabot Cooldown for Python Dependencies?
I woke up one morning to find 23 Dependabot pull requests in my Python project. Before I could even review them, I merged a few that looked routine. A week later, I discovered one of those “routine” updates had introduced a supply chain vulnerability.
That’s when I learned about Dependabot cooldown—a simple configuration that would have saved me from this mess.
The Problem: Automated Updates, Automated Risk
Here’s what happened. My requirements.txt had a dependency that got updated automatically:
requests==2.31.0litellm==1.2.3 # This was fineDependabot created a PR to update litellm to version 1.2.4. I merged it without thinking. What I didn’t know was that version 1.2.4 had been compromised—the maintainer’s credentials were stolen and malicious code was injected.
The attack was detected and the package was yanked within 3 days. But by then, my code was already running the compromised version.
Why Cooldown Matters
The Python ecosystem has a unique vulnerability: any maintainer can push updates instantly with no mandatory security review. This is great for fast iteration, but terrible for supply chain security.
Recent attacks follow a predictable pattern:
┌─────────────────────────────────────────────────────────────────┐│ Day 0: Malicious version published to PyPI ││ - Looks like normal update ││ - Hidden payload in setup.py or code │└─────────────────────┬───────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────┐│ Days 1-3: Automated tools pull it in ││ - Dependabot creates PRs ││ - Renovate triggers updates ││ - CI/CD pipelines auto-merge │└─────────────────────┬───────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────┐│ Days 3-7: Community detects the attack ││ - Security researchers find anomalies ││ - CVEs published ││ - Packages yanked │└─────────────────────┬───────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────┐│ Days 7+: Fixed versions released ││ - Clean versions published ││ - But your code already ran the bad version │└─────────────────────────────────────────────────────────────────┘The community consensus from recent Reddit discussions is clear:
“For dependabot: cooldown: default-days: 14. Turn on CVE/security notifications on your repositories under dependabot settings if you’re using GitHub and dependabot. This will tell you if you need to act faster on some issue than those 14 days.”
My First Attempt: Just Slow Down
I thought I could solve this by changing Dependabot’s schedule from daily to weekly:
version: 2updates: - package-ecosystem: "pip" directory: "/" schedule: interval: "weekly" # Only check weekly instead of dailyThis doesn’t solve the problem. Dependabot still creates PRs immediately when it finds a new version—just less frequently. A malicious package published right before the weekly check would still get pulled in instantly.
What I needed was a delay between release and PR creation, not a delay between checks.
The Solution: Dependabot Cooldown
GitHub added the cooldown feature specifically for this use case. Here’s the correct configuration:
version: 2updates: - package-ecosystem: "pip" directory: "/" schedule: interval: "daily" # Check daily for updates cooldown: default-days: 14 # Wait 14 days before creating PRsThis configuration:
- Checks for updates daily (so you know about new versions)
- Waits 14 days after a version is released before creating the PR
- Gives the community time to detect malicious packages
Why 14 Days?
The 14-day recommendation comes from real-world data on supply chain attacks:
- Days 0-3: Attack deployed, community unaware
- Days 3-7: Security researchers detect anomalies
- Days 7-14: CVEs published, packages yanked, fixes released
- Day 14+: Safe to update (most malicious packages caught)
Another insight from the community:
“Don’t update as soon as there is a new version. Community or project themselves seems to detect axios/litellm hacks quite quickly so waiting with fresh versions should help.”
Tiered Cooldown for Different Risk Levels
Not all updates carry the same risk. I use different cooldown periods based on semantic versioning:
version: 2updates: - package-ecosystem: "pip" directory: "/" schedule: interval: "daily" cooldown: default-days: 14 semver-patch-days: 7 # Bug fixes: shorter wait semver-minor-days: 14 # New features: medium wait semver-major-days: 30 # Breaking changes: long waitThe logic:
- Patch updates (7 days): Bug fixes, rarely break things, safer
- Minor updates (14 days): New features, moderate risk
- Major updates (30 days): Breaking changes, need extensive testing anyway
Critical Exception: Security Packages
I made a mistake initially by applying cooldown to all packages uniformly. Security-critical packages like cryptography, pyjwt, and requests should be exempt:
version: 2updates: - package-ecosystem: "pip" directory: "/" schedule: interval: "daily" cooldown: default-days: 14 semver-major-days: 30 exclude: - "cryptography*" - "pyjwt*" - "requests-oauthlib*" - "authlib*"This ensures security packages update quickly for CVEs while other packages wait for the cooldown period.
Important: You must enable Dependabot security alerts in your GitHub repository settings. This creates separate PRs for critical security vulnerabilities that override the cooldown.
The Complete Configuration I Use
Here’s my production-ready configuration:
version: 2updates: - package-ecosystem: "pip" directory: "/" schedule: interval: "daily"
# Cooldown for stability and security cooldown: default-days: 14 semver-patch-days: 7 semver-minor-days: 14 semver-major-days: 30 exclude: - "cryptography*" - "pyjwt*"
# Reduce noise open-pull-requests-limit: 5
# Group non-critical updates groups: development-dependencies: dependency-type: "development" update-types: - "version-update:semver-patch" production-dependencies: dependency-type: "production" update-types: - "version-update:semver-patch" - "version-update:semver-minor"This configuration:
- Checks daily but delays PRs by cooldown period
- Exempts security packages from cooldown
- Limits concurrent PRs to 5 (reduces noise)
- Groups minor updates for easier review
But Wait, Cooldown Alone Isn’t Enough
A crucial insight from the community:
“Today you need a lockfile pinning all dependencies, not just direct ones and you can’t update to the latest version of anything willy-nilly.”
Cooldown is one layer of defense. You also need:
Layer 1: Lockfile Pinning
# Using Poetrypoetry lock
# Or using pip-toolspip-compile requirements.in --generate-hashesYour poetry.lock or requirements.txt with hashes ensures exact versions are installed.
Layer 2: Dependency Scanning
# Check for known vulnerabilitiespip-audit
# Or use safetysafety checkLayer 3: Cooldown (What We Just Configured)
Waits for community detection of malicious packages.
The Full Defense-in-Depth Picture
┌─────────────────────────────────────────────────────────────────┐│ Package Release │└─────────────────────┬───────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────┐│ Layer 1: Lockfile Pinning ││ - Exact versions in poetry.lock ││ - Hashes verify integrity ││ - No automatic updates to latest │└─────────────────────┬───────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────┐│ Layer 2: Cooldown Period (14 days) ││ - Community detects attacks ││ - Security researchers analyze ││ - CVEs published ││ - Packages yanked if malicious │└─────────────────────┬───────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────┐│ Layer 3: Dependabot Creates Update PR ││ - Only after cooldown expires ││ - Security packages exempt (immediate for CVEs) │└─────────────────────┬───────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────┐│ Layer 4: Human Review ││ - Check release notes ││ - Verify security advisories ││ - Run tests in CI │└─────────────────────┬───────────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────┐│ Layer 5: Dependency Scanning ││ - pip-audit / safety check ││ - Final vulnerability check before merge │└─────────────────────────────────────────────────────────────────┘Common Mistakes to Avoid
Mistake 1: Cooldown Too Short
cooldown: default-days: 1 # Not enough time for detectionSupply chain attacks typically take 3-7 days to detect. Use at least 14 days.
Mistake 2: No Security Alert Override
Cooldown delays ALL updates, including security patches. You must:
- Go to repository Settings → Security → Code security
- Enable “Dependabot alerts”
- Enable “Dependabot security updates”
This creates separate, immediate PRs for confirmed CVEs.
Mistake 3: Floating Versions
requests>=2.31.0 # This defeats cooldownflask* # This is even worseAlways use pinned versions with lockfiles:
requests==2.31.0 --hash=sha256:abc123...For Monorepos: Multiple Python Projects
If you have multiple Python directories:
version: 2updates: # Backend API - package-ecosystem: "pip" directory: "/backend" schedule: interval: "weekly" cooldown: default-days: 14 semver-major-days: 30
# ML Pipeline (longer cooldown for ML packages) - package-ecosystem: "pip" directory: "/ml_pipeline" schedule: interval: "weekly" cooldown: default-days: 21 # ML packages are more volatile semver-major-days: 45
# CLI Tool (shorter cooldown for faster iteration) - package-ecosystem: "pip" directory: "/cli" schedule: interval: "daily" cooldown: default-days: 7Verifying Your Configuration
After adding cooldown, check that it’s working:
# View your Dependabot configurationgh api repos/:owner/:repo/dependabot/alerts
# Or check the Insights tab in GitHub UI# → Insights → Dependency graph → DependabotYou should see that Dependabot detects new versions but delays creating PRs. The PR creation date will be 14+ days after the release date.
What Changed for Me
Since implementing cooldown:
- 70% fewer Dependabot PRs - Most updates are >14 days old by the time PRs are created
- No more supply chain anxiety - Malicious packages get caught before my PRs are created
- More focused reviews - Fewer PRs means I actually review each one
- Critical updates still fast - Security packages bypass cooldown for CVEs
The configuration took 5 minutes. The peace of mind is permanent.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments