How Often Should a Drupal Site Run Composer Audit for Security?

Composer audit should run on every CI build plus a recurring cron job, because advisory data changes even when a Drupal site's code doesn't.

A Drupal site should run `composer audit` on every CI build or commit, plus a recurring scheduled job such as a nightly or weekly cron task, rather than only when someone updates modules. `composer audit` is a built-in Composer command, added in version 2.4, that checks a project's installed or locked package versions against known security vulnerability advisories (php.watch). The reason a fixed "check it occasionally" schedule falls short is that the vulnerability database behind the command changes independently of the site. Packagist's advisory feed is updated continuously as new CVEs and GitHub advisories are published, so a Drupal site's dependency set can turn vulnerable overnight with no code change on the site's side (Packagist).

Table of Contents

What Composer Audit Actually Checks

`composer audit` compares the package versions a project has installed, or the exact versions pinned in `composer.lock`, against a security advisory database. It has run automatically after every `composer update` since Composer 2.4, whose first release candidate shipped on 2022-07-21, unless a project disables that behavior (php.watch). The data it checks against comes from the Packagist.org Security Advisory API, which pulls together the GitHub Advisory Database and the FriendsOfPHP/security-advisories feed.

That means the results cover disclosures from across the entire PHP ecosystem, not just advisories written specifically for Drupal (Packagist). Running the command with the `–locked` flag audits the versions written into `composer.lock` without requiring the packages to actually be installed on disk. The command also exits with a non-zero status code equal to the number of matched advisories, which is what makes it usable as an automated pass/fail gate rather than something a person has to read and interpret (php.watch; DefectDojo parser docs).

Why Drupal's Own Security Advisories Don't Cover This

Drupal's Security Team only issues advisories for projects hosted on Drupal.org and for libraries bundled directly with core, such as jQuery. It does not issue advisories for third-party libraries that a contributed module pulls in through Composer, no matter how the site installed them (Drupal.org, PSA-2022-06-20). That same 2022 notice explains that, starting with Drupal 9.4, the Security Team stopped publishing separate "just-in-case" advisories every time one of core's own Composer dependencies got a routine update; those updates are now folded into ordinary core patch releases instead.

The notice places responsibility for tracking vulnerabilities in every other dependency on site maintainers, and names Composer's own audit tooling as the way to do it (Drupal.org). Drupal.org's release calendar reinforces the gap: contributed-project security advisories go out on a Wednesday release window, and core security releases follow a monthly window, typically the third Wednesday. Because third-party Composer libraries fall under neither cadence, a site that relies only on Drupal's advisory emails can remain unaware of a vulnerable dependency indefinitely (Drupal.org, security advisory policy).

Where Scheduled Audits Fit Versus Build-Time Audits

The practical pattern described across these sources is two-layered: wire `composer audit` into continuous integration so it runs on every commit or build, and back that with a recurring scheduled job, such as nightly or weekly cron, that re-checks the dependency set even when nobody is actively pushing code (Packagist). The build-time layer catches a newly introduced vulnerable dependency the moment it's added. The scheduled layer catches the more common case: a dependency that was clean when it was last installed, but has since had an advisory published against it.

Since advisory data updates continuously, a site that only audits at deploy time can go weeks or months between checks if deploys are infrequent. A platform-level example of the build-time layer is Pantheon's Integrated Composer, which runs `composer audit` automatically against a site's `composer.json` and `composer.lock` on every build. As of an August 2026 release note, it blocks promotion to the Test environment if the latest build carries open advisories that haven't been explicitly acknowledged — audited on every push, not on a calendar (Pantheon; Pantheon release notes).

Setting Up the Scheduled Job

A site that doesn't run on a platform with built-in Composer auditing needs to assemble the scheduled layer itself. The command itself requires nothing beyond a working Composer installation and the project's existing `composer.lock` file.

Running the scheduled check doesn't require a deploy. It only requires reading the current `composer.lock`, which is why it can run on a timer independently of the release cycle.

  • Add `composer audit –locked` as a step in the CI pipeline that already runs on pull requests or merges, so a vulnerable addition is caught before it reaches production.
  • Add a separate cron-triggered job, at minimum weekly, that runs the same command against the current `composer.lock` on an environment that mirrors production dependencies.
  • Treat a non-zero exit code as a build failure or an alert, since the exit code equals the number of matched advisories (php.watch).
  • Review any matched advisory against the specific package and version in use, since the database draws from the broader PHP ecosystem rather than Drupal-specific reporting (Packagist).
  • Keep Drupal's own core and contributed-project advisories as a separate feed to monitor, since `composer audit` does not replace them — it covers the dependencies they don't (Drupal.org).

Frequently Asked Questions

Does Drupal's core security team already run Composer audit for me?

No. Drupal's Security Team issues advisories only for Drupal.org-hosted projects and libraries bundled with core; it explicitly leaves other Composer dependencies to site maintainers and points to audit tooling as the way to track them (Drupal.org).

Is checking Composer audit only when I update modules good enough?

No, because the advisory database Composer audit checks against is updated continuously, independent of when a site last changed its dependencies, so a vulnerability can appear with no action on the site's part (Packagist).

What does a non-zero exit code from Composer audit mean?

The command's exit code equals the number of matched security advisories, which lets CI systems treat the run as a pass/fail gate rather than needing a human to read the output (php.watch).


You Might Also Like