Skip to content

Quarantine new dependency releases while raising security advisories immediately #3137

Open

Description

@AlexSkrypnyk

Summary

Automated dependency updates currently have 2 opposite problems, and fixing the first one on its own makes the second one worse.

Routine updates are adopted the moment a release is published. That is exactly the window in which a compromised package release is live and not yet yanked - the pattern behind recent package-registry supply-chain incidents, where malicious versions were published and pulled within hours.

Security fixes, meanwhile, are adopted too slowly, because Renovate can't see the advisories. Renovate already has a fast path for advisory-driven updates: its built-in vulnerabilityAlerts defaults skip the group schedules, the concurrent pull request limit and any minimum release age. That path only opens for advisories Renovate can read, which on GitHub means Dependabot alerts that are enabled and readable by the Renovate app or token. Dependabot alerts are disabled on this repository, so every fix arrives as an ordinary update, inherits its group's schedule, and can wait up to a week after the advisory is published before a pull request appears.

The fix has 2 halves: quarantine new releases for a minimum age, and make advisories visible to Renovate so their fixes take the exempt path and are raised immediately. A quarantine on its own adds days to every fix Renovate can't see, so it can't land without the visibility half. Visible advisories on their own are safe to land, but they leave the compromised-release window wide open.

At a glance

A ROUTINE RELEASE THAT TURNS OUT TO BE COMPROMISED (PUBLISHED ON DAY 0)

  day           0      1      2      3      4      5      6      7
                ├──────┼──────┼──────┼──────┼──────┼──────┼──────┤
  registry      ├┤ live for hours, then pulled
  today         * PR can open in that window; the Actions group automerges
  proposed      ├─ 3-day quarantine ─┤ gone before it can be proposed


A SECURITY FIX IN A WEEKLY GROUP (ADVISORY PUBLISHED ON DAY 0)

  day           0      1      2      3      4      5      6      7
                ├──────┼──────┼──────┼──────┼──────┼──────┼──────┤
  today         ├───── up to 7 days, until Sunday's window ──────┤ PR
                advisory not visible to Renovate: the fix is a routine update
  proposed      * PR on the next run
                advisory visible to Renovate: its built-in exemption applies


WHAT EACH HALF FIXES ON ITS OWN

                           routine release        security fix
                           is proposed at         is proposed after
                           ─────────────────────  ─────────────────────
  today                    any age       exposed  up to 7 days   slow
  quarantine only          3+ days old   ok       up to 10 days  slower
  visible advisories only  any age       exposed  the next run   ok
  both halves              3+ days old   ok       the next run   ok

Details

renovate.json puts every PHP package behind before 2am on Sunday, Drupal core behind before 2am, JavaScript packages behind before 2am on Sunday, and container images and Actions behind before 3am. There's no minimum release age and no vulnerabilityAlerts block. The missing block isn't what slows fixes down, since Renovate's built-in defaults already exempt advisory-driven updates. Dependabot alerts are disabled on this repository, so Renovate never receives an advisory to act on. The GitHub Actions group is configured with automerge: true, so an Actions release can be adopted and merged automatically within minutes of publication with no human in the loop.

The security audit job already tells a project it is exposed - composer audit --locked fails the build as soon as an advisory lands against a resolved dependency. What's missing is the other half: Renovate never sees the advisory the audit just reported, so the remedy doesn't start until the group's schedule allows it. The result is a repository that knows it is vulnerable and then waits up to a week for the bot to offer the fix, or has someone bump it by hand.

Setting a minimum release age changes the risk profile cheaply. Routine updates arrive a few days later than they do today, and releases that are pulled, yanked or superseded inside that window never reach the project at all. The cost is bounded and predictable; the benefit is that the project is never the first consumer of a compromised release.

Proposed implementation

1. Add the quarantine as a top-level setting

A top-level minimumReleaseAge in renovate.json applies to every manager at once, so no per-group rules need touching and the existing grouping and schedules stay exactly as they are:

"minimumReleaseAge": "3 days",

Three days is the proposal, not a fixed requirement: long enough to cover the observed window in which malicious releases were pulled, short enough that a weekly grouped update is unaffected in practice, since the group only runs once a week anyway. For the container-image and GitHub Actions groups, which run nightly, this is the only group where the delay is actually visible.

2. Rely on the built-in advisory exemption, and label it

vulnerabilityAlerts is the config object Renovate applies to pull requests raised in response to an advisory, and its built-in defaults are already the exemption this change needs: schedule: [], minimumReleaseAge: null and prConcurrentLimit: 0. Renovate's docs also state that schedule is always ignored for these pull requests and can't be overridden. So once Renovate can see an advisory, its fix already skips the group windows, the quarantine from section 1 and the routine prConcurrentLimit: 10 queue, with nothing added to renovate.json.

The one addition worth making is the label:

"vulnerabilityAlerts": {
  "labels": ["Dependencies", "Security"]
},
  • labels reuses the repository's existing Security label, so advisory pull requests are distinguishable at a glance with no new label to create.
  • enabled, minimumReleaseAge, schedule and prConcurrentLimit stay out, since setting them would only restate the defaults. prPriority stays out too: advisory pull requests aren't held by the routine limit, so there's no queue for them to jump.

3. Make advisories visible to Renovate

This is the half that changes behaviour, and it needs a decision rather than a config line. Renovate can learn about advisories 2 ways, and the template supports 2 Renovate deployment modes through the installer's dependency-updates provider handler, which behave differently:

  • Hosted app (renovatebot_app): reads the repository's Dependabot alerts, provided the dependency graph and Dependabot alerts are enabled in the repository settings and the app has read access to Dependabot alerts. Dependabot alerts are disabled on this repository, so the app currently sees no advisories.
  • Self-hosted via CI (renovatebot_ci): runs from .github/workflows/update-dependencies.yml with token: ${{ secrets.RENOVATE_TOKEN }}. The same repository settings apply, and that token must be able to read the repository's Dependabot alerts, or vulnerabilityAlerts silently does nothing and the feature appears to work while doing exactly nothing. The settings and the token permission requirement have to be documented as part of this change.

osvVulnerabilityAlerts: true is the fallback when Dependabot alerts can't be read, since it sources advisories from the OSV database instead. It's flagged experimental upstream and only covers direct dependencies, so it should be evaluated rather than adopted blindly.

4. Make quarantined updates visible

With a quarantine in place, an update that is waiting out its window is reported as pending in the Dependency Dashboard. The self-hosted workflow sets RENOVATE_DEPENDENCY_DASHBOARD: ${{ vars.RENOVATE_DEPENDENCY_DASHBOARD || 'false' }}, so the dashboard is off unless a project opts in - which means quarantined updates would be invisible by default and the delay would look like the bot having stopped working.

Either the dashboard default flips for projects using the quarantine, or the documentation states plainly that the dashboard is how pending updates are seen. This needs deciding as part of the change, not after someone reports the bot as broken.

5. Verify with a dry run before merging

The workflow already supports this: set the RENOVATE_DRY_RUN repository variable to true and inspect the run log. Renovate's docs and defaults already settle how the exemption behaves, so the run is for the 2 things config can't show: that Renovate actually reads advisories in each deployment mode, and that routine updates younger than the window are held back. Both should be confirmed against a real run rather than assumed.

Scope limitation worth knowing up front

This repository does not commit a root composer.lock. Advisory detection works from a resolved dependency graph, so the template repository itself will get little or nothing from the PHP side of this - the alerts have nothing precise to match against. Consumer projects, which do commit a lock file, are where the benefit actually lands.

The practical consequence is that this cannot be fully validated on the template and needs checking against a consumer project. It also means the JavaScript side, which does commit package-lock.json, is the only part observable here, and only once Dependabot alerts are enabled.

Acceptance criteria

  • A top-level minimum release age is configured, so a release is not proposed until it has been published for at least that long.
  • The chosen window is documented with the reasoning, so projects can lengthen or shorten it deliberately.
  • Updates raised in response to a published security advisory are exempt from the quarantine and are not subject to the group schedules, appearing as soon as the advisory is available.
  • Advisory-driven pull requests carry the existing Security label so they are distinguishable from routine grouped updates.
  • An advisory fix is not blocked by the routine concurrent-pull-request limit.
  • Existing grouping and schedules for routine updates are unchanged.
  • Automerged groups remain automerged, but only for releases that have cleared the quarantine window.
  • Renovate can read advisories in both the hosted and the self-hosted mode, through Dependabot alerts or the OSV fallback, and the repository settings and self-hosted token permission this needs are documented.
  • Pending quarantined updates are discoverable, either by the dashboard default or by documentation that states how to see them.
  • The quarantine doesn't land before advisory visibility, since on its own it adds days to every fix Renovate can't see.
  • The behaviour is verified with a dry run, confirming that Renovate reads advisories and that routine updates inside the window are held back.
  • The configuration passes the existing Renovate config validation step in the dependency-update workflow.
  • Installer fixtures and snapshots are updated, since renovate.json is processed by the installer's dependency-updates provider handler and shipped to consumers.
  • The documentation covers the interaction between the quarantine, the advisory exemption and the update schedules, and how a project turns either half off if its policy requires batching.

Activity

  1. added this to the 1.42.0 milestone on Sep 17, 2026
  2. added
    SecurityIssue or a pull requests that address a security vulnerability
    on Sep 17, 2026
  3. changed the title [-]Raise dependency security advisories immediately instead of on the grouped schedule[/-] [+]Quarantine new dependency releases while raising security advisories immediately[/+] on Sep 17, 2026
  4. added
    ConfirmedThe issue was triaged and confirmed for development
    and removed
    ConfirmedThe issue was triaged and confirmed for development
    on Sep 17, 2026
  5. moved this from BACKLOG to To do for current release in Vortex 1.xon Sep 17, 2026
  6. modified the milestones: 1.42.0, 1.43.0 on Oct 8, 2026
  7. moved this from To do for current release to Next release in Vortex 1.xon Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    SecurityIssue or a pull requests that address a security vulnerability

    Type

    No type

    Projects

    • Status
      Next release

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions