Safeguard
Security Guides

Auditing PHP Dependencies with composer audit

Composer ships a native security auditor. Learn to run composer audit against your composer.lock, catch abandoned packages, and extend it with continuous SCA.

Priya Mehta
Security Researcher
5 min read

PHP still powers an enormous share of the web, and most of that PHP is built on Composer packages. A modern Laravel or Symfony application resolves a dependency tree far larger than its composer.json suggests — frameworks, ORMs, HTTP clients, and their own dependencies stack up quickly, and every one of them is a potential entry point. For years, auditing that tree meant reaching for an external tool. Since Composer 2.4, it no longer does: composer audit is built in.

How composer audit works

composer audit reads your composer.lock — the exact, resolved set of packages and versions — and checks them against the Packagist security advisories database, which aggregates advisories from the PHP security community and the GitHub Advisory Database. Because it works from the lockfile, it covers the full transitive graph, not just your direct requirements.

Run it from your project root:

composer audit

The output lists each advisory: the affected package, the CVE or advisory identifier, a severity, a title, and a link. For CI, request machine-readable output:

composer audit --format=json

If you only care about what runs in production, exclude development dependencies:

composer audit --no-dev

One of composer audit's most practical features is that it also surfaces abandoned packages — dependencies whose maintainers have marked them as no longer maintained, often pointing to a successor. Abandonment is a leading indicator of future unpatched vulnerabilities, so you want to know early. Control how it is treated:

composer audit --abandoned=report
composer audit --abandoned=fail

report lists them without failing; fail makes an abandoned dependency break the audit. In a strict pipeline, --abandoned=fail forces a conversation about replacing dead dependencies before they become a security problem.

Integrating into CI

composer audit exits non-zero when it finds an advisory, so wiring it into a pipeline is straightforward:

composer install --no-interaction
composer audit --no-dev --abandoned=report

Run it on every pull request and on a schedule against your default branch, so newly disclosed advisories in code you already shipped surface even when no one is changing dependencies.

Auditing during install, not just on demand

Composer can audit automatically as part of install and update, so a newly introduced vulnerability is flagged the moment a dependency change lands rather than waiting for someone to remember to run the command. You control this through the audit block in composer.json and the abort behavior on the command line — for example, running composer update with auditing enabled will report advisories for the packages you just pulled in. This shifts the check left: the developer who added the risky package sees the warning in their own terminal, in the same command that introduced it, which is far cheaper than catching it three pull requests later. Pair automatic install-time auditing with a scheduled audit of your deployed branch and you cover both new changes and newly disclosed advisories in already-shipped code.

The limits

  • No reachability. composer audit tells you a vulnerable version is installed. It cannot tell you whether your application invokes the vulnerable class or method, so a flaw in a mail transport you configured out is reported the same as one in your active request path.
  • Advisory latency. It is only as current as the advisories it consumes. Freshly published malicious or typosquatted packages have no advisory yet and pass silently.
  • Snapshot only. Each run is a point-in-time check. There is no SLA tracking, no shared accepted-risk record with an expiry, and no consolidated view across the many sites and services a PHP shop often maintains.
  • No remediation. It identifies the problem; updating composer.json constraints, resolving conflicts, and validating the app is manual.

Going further with continuous SCA

Keep composer audit as your fast native gate — the abandoned-package detection alone justifies running it on every build. Then layer a continuous platform for what it cannot see. Safeguard's software composition analysis ingests the same composer.lock and adds call-path reachability, so the advisories that touch code your application actually executes rise to the top of the queue and the rest are visibly deprioritized rather than treated as equally urgent.

Because a PHP estate is rarely a single repository, an accurate, portable inventory matters: SBOM Studio captures the full resolved Composer graph as a standards-based bill of materials you can archive, diff between releases, and hand to customers or auditors on request. And developers keep their existing workflow through the Safeguard CLI, which runs the same scan locally and in CI with policy enforced centrally.

For teams weighing continuous scanning across many sites, the pricing overview shows how it scales past the run-it-per-repo model.

PHP dependency audit checklist

  1. Commit composer.lock so audits reflect exactly what you deploy.
  2. Run composer audit --no-dev on every pull request and fail on advisories.
  3. Use --abandoned=fail (or at least report) to catch dead dependencies before they rot.
  4. Schedule a recurring audit of your default branch to catch newly disclosed CVEs in shipped code.
  5. Add reachability-aware, continuous scanning so triage centers on exploitable findings and every site reports into one policy.

composer audit turned PHP dependency auditing from an add-on into a first-class part of the toolchain, and its abandoned-package awareness is genuinely ahead of the curve. Add reachability, cross-repository policy, and autonomous remediation, and you move from a per-build warning to a managed program.

Bring prioritized, continuous auditing to your PHP applications — create a free account or read the documentation.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.