2.4 in August adds an audit command that checks the lock file against the Packagist advisory database, which several separate tools had been doing.
$ composer audit
Found 2 security vulnerability advisories affecting 1 package:
+-------------------+------------------------------------------+
| Package | guzzlehttp/guzzle |
| CVE | CVE-2022-31090 |
| Affected versions | >=7.0.0,<7.4.5 |
+-------------------+------------------------------------------+
$ echo $?
1 # so it can gate a build
$ composer audit --format=json --locked
Reading the lock file rather than the installed tree means it works in CI without a full install, which is what makes it cheap enough to run on every push. The exception process is the part that has to be decided before turning it on: a transitive advisory with no fixed version will eventually block a deploy, and the answer needs to be a documented override with an expiry rather than a disabled step.