Dependency update bots close the gap between a fix being released and a fix being deployed, but configured to merge everything immediately they also deliver a malicious release to your main branch within minutes of it being published. Dependabot and Renovate are now the default way most teams keep libraries current, and the settings that decide their risk (cooldowns, grouping, auto-merge rules, credentials and CI permissions) are usually left at whatever the first engineer chose. This guide explains how both tools work, how release-age cooldowns reduce exposure to compromised packages, when auto-merge is safe, how to keep the bot and its workflows from becoming a credential leak, and how to measure that patching is actually faster. It is for platform engineers, application security teams and engineering managers who own dependency hygiene across many repositories.
Key takeaways
- Speed and safety pull in opposite directions. Malicious releases are usually removed within hours, so a short delay before adopting new versions blocks most of them while costing little in patch latency.
- Cooldowns are now built in. Dependabot applies a default 3-day cooldown to version updates on GitHub.com, Renovate offers
minimumReleaseAgewith 3-day security presets, and pnpm can refuse to install versions younger than a set age. - Security updates are treated differently. Dependabot cooldowns do not apply to security updates, which is the right default: a published advisory changes the risk balance.
- Auto-merge is a policy decision, not a convenience switch. Limit it to patch and minor updates of trusted dependencies that pass real tests, after the cooldown, with branch protection still enforced.
- The bot is a non-human identity. Its tokens, registry credentials and the CI workflows it triggers need least privilege, and commits that only claim to be from a bot must not be trusted.
How Dependabot and Renovate work
| Aspect | Dependabot | Renovate |
|---|---|---|
| Where it runs | Built into GitHub; configured with .github/dependabot.yml | Hosted app or self-hosted CLI across GitHub, GitLab, Bitbucket, Azure DevOps and others; configured with renovate.json and shared presets |
| Update types | Version updates on a schedule; security updates raised from Dependabot alerts | Version updates; vulnerability fix PRs using GitHub alerts or OSV data (vulnerabilityAlerts, osvVulnerabilityAlerts) |
| Release-age delay | cooldown with default-days, semver-major-days, semver-minor-days, semver-patch-days, and include/exclude lists (up to 150 entries, wildcards allowed) | minimumReleaseAge (formerly stabilityDays), minimumReleaseAgeBehaviour, internalChecksFilter |
| Default delay | 3 days for version updates on GitHub.com, GitHub Enterprise Cloud and GitHub Enterprise Server later than 3.21; none for security updates | None unless configured; security:minimumReleaseAgeNpm and similar presets set 3 days for npm, PyPI and crates |
| Grouping and limits | groups, multi-ecosystem-groups, open-pull-requests-limit | packageRules, grouping presets, PR concurrency and hourly limits |
| Auto-merge | Not native: a GitHub Actions workflow uses dependabot/fetch-metadata to read the update type, then enables GitHub auto-merge | Native automerge with automergeType (pr or branch) and platformAutomerge |
| Approval gate | Reviewers, CODEOWNERS and branch protection | Also dependencyDashboardApproval: no branch or PR until someone ticks the update in the Dependency Dashboard |
For broader context on open source risk see the Open Source Security Guide.
Cooldowns: why a short delay works
Most recent package compromises follow the same timeline: an attacker takes over a maintainer account or publishing token, publishes a poisoned version, and the registry removes it within hours once scanners or users notice. The axios npm compromise in March 2026 is the clearest example: malicious versions 1.14.1 and 0.30.4 were live for roughly three hours, yet Dependabot and Renovate proposed the upgrade within minutes and some bot pull requests were merged without review, with at least 895 public repositories upgrading. A cooldown of even one day would have kept those repositories on the clean version.
- How Renovate applies it: each new version must be older than
minimumReleaseAge; until then Renovate sets a pending status check on the branch, and replaces it with a passing check once the age is reached. Renovate requires the release timestamp to come from the registry, so a maintainer cannot fake it. SetminimumReleaseAgeBehaviourtotimestamp-requiredso versions without a timestamp are not treated as stable, andinternalChecksFiltertostrict, which Renovate recommends. - How Dependabot applies it: a release that falls inside its cooldown is skipped at the scheduled check and picked up after the cooldown ends. Use larger values for major versions, which carry more change.
- Installer-level cooldowns: pnpm's
minimumReleaseAge(in minutes, applied to transitive dependencies too) stops a developer or CI job installing a brand-new version even outside the bot, and itstrustPolicy: no-downgradefails installation when a package's trust evidence drops, for example from trusted publishing to no provenance. - Exceptions: exclude your own internal packages (Renovate: a package rule with
minimumReleaseAge: null; Dependabot:exclude), since you control their release.
| Update class | Suggested cooldown | Auto-merge | Rationale |
|---|---|---|---|
| Security fix for a published advisory, reachable code | None | No: fast-track human review | Known exploit risk outweighs compromise risk; still review the diff |
| Patch update, widely used dependency | 3 days | Yes, if tests pass | Low change, most malicious releases removed in that window |
| Minor update | 3 to 7 days | Optional for dev dependencies and well-tested libraries | New features can carry new transitive dependencies |
| Major update | 14 days or more | No | Breaking changes need human reading of release notes |
| New transitive dependency introduced | As per parent | No | A new package name is the classic way malware enters |
| Internal packages | None | Per team policy | You control the publisher |
| GitHub Actions and container base images | 3 to 7 days, pinned by digest or commit SHA | Only digest bumps of trusted publishers | Actions run with CI secrets; tags can be moved |
Auto-merge: when it is safe
Auto-merge is safe only when the merge gate tests something meaningful and the update cannot bypass it. Renovate's own documentation notes most people leave major updates to a human and shows auto-merging only minor, patch, pin and digest updates.
- Keep branch protection on: auto-merge should wait for required status checks and, for sensitive repositories, a code owner review. Never give the bot permission to bypass rulesets.
- Merge only after the cooldown: with Renovate the pending
minimumReleaseAgecheck blocks auto-merge until the age is reached; with Dependabot the cooldown means the PR is not opened early. - Filter by update type and package: in the Dependabot workflow, check
steps.metadata.outputs.update-typeequalsversion-update:semver-patch(or minor) and that the dependency is on an allowlist. - Tests must exercise the dependency: a green build with no tests is not a gate. Renovate refuses to auto-merge without checks unless you set
ignoreTests; do not set it. - Watch for install scripts: a patch release that adds a
postinstallscript or new dependency should drop out of auto-merge. Tools that diff package contents help here. - Batch, do not flood: group low-risk updates weekly; dozens of daily PRs train reviewers to approve without reading.
Securing the bot and its pipeline
The update bot reads private registries, opens branches and triggers CI. That makes it a privileged non-human identity, and its workflows are a route for a malicious package to reach secrets.
- Dependabot workflow permissions: GitHub gives workflows triggered by Dependabot a read-only
GITHUB_TOKENby default and does not expose Actions secrets to them; secrets they need must be stored separately as Dependabot secrets. Keep it that way, and do not work around it withpull_request_targetplus checkout of the PR head. - Code execution during updates: Dependabot disables external code execution during updates when registries are configured;
insecure-external-code-execution: allow(Bundler, Mix, pip) lets manifest code run with access to those registry credentials. Leave it off unless unavoidable. - Registry credentials: give the bot read-only, scoped tokens for private registries and rotate them. Prefer short-lived credentials where the platform supports OIDC.
- Self-hosted Renovate: run it with a GitHub App installation token scoped to the repositories it manages rather than a personal access token, and isolate its runner from production networks.
- Do not trust bot names: the fake Dependabot commits campaign in 2023 used stolen personal access tokens to push commits disguised as Dependabot fixes that added secret-stealing workflows. Require signed commits or verify the actor through the platform, and review workflow file changes regardless of author.
See the GitHub and GitHub Actions Security Guide for runner and workflow hardening.
Reference configuration
These are starting points for a shared organisation preset, not drop-in files; adjust package lists and days to your risk appetite and check option names against the current documentation.
Dependabot (.github/dependabot.yml)
- Per ecosystem block:
package-ecosystem: "npm",directory: "/",schedule.interval: "weekly",open-pull-requests-limit: 10. - Cooldown:
cooldown.default-days: 3,semver-minor-days: 7,semver-major-days: 14, with internal scopes incooldown.exclude. - Grouping: a
groupsentry collecting patch and minor updates into one weekly PR, majors left as individual PRs. - Actions: a separate
package-ecosystem: "github-actions"block so pinned commit SHAs in workflows are kept current. - Auto-merge workflow: triggered on
pull_request, runs only whengithub.actor == 'dependabot[bot]', readsdependabot/fetch-metadata(pinned by commit SHA) and enables auto-merge only for allowlisted packages with update typeversion-update:semver-patch; grant onlycontents: writeandpull-requests: writeto that job.
Renovate (shared preset)
- Extends:
config:recommendedplus thesecurity:minimumReleaseAgeNpmstyle presets for each ecosystem in use. - Release age:
minimumReleaseAge: "3 days",minimumReleaseAgeBehaviour: "timestamp-required",internalChecksFilter: "strict", and a package rule withminimumReleaseAge: "14 days"formatchUpdateTypes: ["major"]. - Auto-merge: a package rule with
matchUpdateTypes: ["patch", "pin", "digest"],matchDepTypes: ["devDependencies"]andautomerge: true; everything else leavesautomergefalse. - Approval:
dependencyDashboardApproval: truefor majors and for packages on a high-risk list. - Vulnerability fixes: keep
vulnerabilityAlertsenabled with its own label so security PRs are visible and bypass normal schedules, as Renovate does by default.
Implementation plan
- Baseline: list repositories with and without an update bot, current config, auto-merge rules and median age of open dependency PRs.
- Standard config: publish a shared Renovate preset or a Dependabot template with cooldowns per update class, grouping, PR limits and auto-merge rules from the tables above.
- Pilot: apply it to five to ten repositories with good test coverage; measure PR volume, merge time and breakages for a month.
- Lock down permissions: confirm read-only tokens for bot-triggered workflows, scoped registry tokens and branch protection that the bot cannot bypass.
- Enable auto-merge in stages: start with dev dependencies and patch updates, then extend to minor updates for allowlisted packages.
- Add installer cooldowns: where the package manager supports it (for example pnpm), set a minimum release age in the repository so manual installs follow the same rule.
- Roll back: if a bad update merges, revert the PR, pin the last good version, and use the bot's ignore rule for the bad version; if malicious, follow the Malicious Open Source Package Response Playbook and rotate any secret the CI job could reach.
- Roll out: enforce the standard config through organisation-level presets and report on drift.
Decision guidance
- Dependabot or Renovate: Dependabot suits GitHub-only estates that want zero infrastructure; Renovate suits mixed platforms, monorepos and teams that need fine-grained package rules, shared presets and dashboard approval.
- Small team: enable the bot with default cooldown, group updates weekly, auto-merge dev dependency patches only.
- Large organisation: central presets, an allowlist of auto-merge-eligible packages, metrics per team, and an internal proxy that applies its own release-age rule for every build, not just bot PRs.
- Regulated or high-risk services: no auto-merge to production branches; use dashboard approval or required code owner review.
Detection and measurement
- Merged versions later yanked: alert when a version your repositories merged is removed from the registry or flagged in an OSV malicious package advisory.
- Bypassed cooldowns: report PRs merged for versions younger than policy, and manual installs of brand-new versions in CI logs.
- Bot actor anomalies: commits claiming bot authorship that were not created by the platform's bot identity, and workflow file changes in dependency PRs.
- New install scripts or dependencies: flag update PRs that add install hooks or new transitive packages.
Metrics:
- Median time from security advisory to merged fix (target set by your remediation policy, as OWASP ASVS 5.0 V15.1.1 requires).
- Percentage of repositories using the standard bot configuration.
- Percentage of merged updates that respected the cooldown.
- Open dependency PRs older than 30 days per team.
- Number of auto-merged updates later reverted, and why.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| NIST SP 800-53 Rev. 5 | SI-2, RA-5, CM-3 | Flaw remediation, vulnerability monitoring, configuration change control for merged updates |
| NIST CSF 2.0 | PR.PS-02, ID.RA-01 | Software maintained commensurate with risk; vulnerabilities identified and recorded |
| OWASP ASVS 5.0 | V15.1.1, V15.2.1 | Documented remediation time frames; components kept within them |
| MITRE ATT&CK | T1195.001 Compromise Software Dependencies and Development Tools | Malicious releases pulled in by automation |
Common failure patterns
- Auto-merge everything, immediately: the axios case showed bots proposing and merging a backdoored release within minutes of publication.
- Security fixes left waiting: applying a long cooldown to security updates too, or letting security PRs queue behind version PRs, slows the patches that matter.
- Green builds with no tests: auto-merge gated on a pipeline that only lints proves nothing about the update.
- Secrets exposed to update PRs: workaround workflows that give dependency PRs write tokens or secrets let a malicious install script exfiltrate them. Worms such as the Shai-Hulud npm worm spread by stealing exactly these CI and publishing tokens.
- Trusting the author label: commits that look like Dependabot are not proof of origin.
- PR floods: ungrouped updates across hundreds of repositories create review fatigue and rubber-stamp approvals.
Practitioner checklist
- Run an update bot on every active repository with a shared, version-controlled configuration.
- Set cooldowns: about 3 days for patch, longer for minor and major, none for advisory-driven security fixes.
- Use Renovate
minimumReleaseAgeBehaviour: timestamp-requiredandinternalChecksFilter: strict, or Dependabotcooldownwith semver-specific values. - Restrict auto-merge to allowlisted patch and minor updates that pass meaningful tests, never majors.
- Keep branch protection and required checks enforced for bot PRs.
- Keep Dependabot-triggered workflows read-only without secrets; avoid
pull_request_targetworkarounds. - Scope and rotate the bot's registry credentials; run self-hosted Renovate as a GitHub App.
- Pin GitHub Actions and base images by commit SHA or digest and let the bot update them.
- Alert on merged versions later yanked or flagged malicious, and rehearse rollback.
Standards and references
- GitHub Docs: Dependabot options reference
- GitHub Docs: Automating Dependabot with GitHub Actions
- Renovate Docs: Minimum Release Age
- Renovate Docs: Configuration options
- pnpm: Settings (minimumReleaseAge, trustPolicy)
- OWASP: Application Security Verification Standard 5.0
- NIST: SP 800-53 Rev. 5
- MITRE ATT&CK: Compromise Software Dependencies and Development Tools
Related NHI Mgmt Group resources: Open Source Security Guide · Malicious Package and Dependency Confusion Guide · Package Registry Security Comparison Guide · OWASP CI/CD Top 10 CICD-SEC-3 Dependency Chain Abuse Guide