Audit Command
The audit command lists known security advisories affecting your installed dependencies. It works on both composer.lock and package-lock.json, like composer audit / npm audit, but in a single pass and with whatsdiff's output formats.

Usage
whatsdiff audit [options]
Options
Comparison Options
--from- Commit, branch, or tag to compare from (enables diff mode)--to- Commit, branch, or tag to compare to (diff mode; defaults toHEAD)--at- Audit the lockfile at a specific commit, tag, or branch instead of the working tree
Output Options
--format,-f- Output format:text(default),json, ormarkdown--no-fix- Skip the suggested-fix version lookup (faster, no extra registry calls)
Filtering Options
--include- Audit only specific package managers (comma-separated:composer,npmjs)--exclude- Exclude specific package managers (comma-separated:composer,npmjs)
Failure Options
--fail-on- Severity threshold for non-zero exit:low(default),medium,high,critical, ornone--allow-unrated- Do not trip--fail-onfor advisories whose severity has not been rated upstream yet
By default, advisories with an unrated severity are treated as meeting any threshold (fail-safe). Pass --allow-unrated if you would rather not block on advisories that are still pending a CVSS score.
Cache Options
--no-cache- Disable caching and force fresh data retrieval from advisory registries
Option Conflicts
--atcannot be used with--fromor--to--includeand--excludeare mutually exclusive
What It Does
The audit command:
- Reads
composer.lockand/orpackage-lock.jsonfrom the working tree (or from a specific ref if--atis given). - Resolves the installed version of each package and queries the corresponding registry for known security advisories.
- Filters advisories by affected version range to only report those that actually impact your installed versions.
- Computes the lowest safe upgrade for each vulnerable package (skipped with
--no-fix). - Displays results in your preferred format (text, JSON, or markdown).
The command supports three modes:
- Current state (default) - audit the working-tree lockfiles.
- Point-in-time (
--at) - audit the lockfile as it existed at a specific commit, tag, or branch. - Diff mode (
--from/--to) - report only advisories that are newly introduced between two refs. Useful in PR pipelines to surface vulnerabilities a change introduces without re-flagging pre-existing ones.
Example Output
$ whatsdiff audit
2 vulnerable packages, 4 security advisories
symfony/cache v8.0.5 → fixed in v8.0.12
○ CVE-2026-45073 SQL Injection in PdoAdapter::doClear() via Unsanitized $prefix
symfony/yaml v8.0.1 → fixed in v8.0.12
○ CVE-2026-45304 YAML Parser Exponential Memory Allocation via Recursive Collection-Alias Expansion ("Billion Laughs")
○ CVE-2026-45305 YAML Parser ReDoS via Catastrophic Backtracking in Parser::cleanup() Regex
○ CVE-2026-45133 YAML Parser Stack Exhaustion via Unbounded Recursion in Nested Blocks, Sequences, and Mappings
Legend: ○ rating pending (4)
Severity bullets are colored in interactive terminals (red for critical/high, yellow for medium, cyan for low, gray for unrated), and CVE IDs are rendered as clickable hyperlinks where supported.
Examples
Basic Usage
Audit the current working-tree lockfiles:
whatsdiff audit
JSON Output for CI/CD
Output in JSON format for parsing in scripts:
whatsdiff audit --format=json
Markdown Output
Generate a markdown report for a PR description or release notes:
whatsdiff audit --format=markdown > security-report.md
Audit at a Specific Commit or Tag
Audit the lockfile as it existed at a released version:
whatsdiff audit --at=v2.3.0
Diff Mode - New Advisories Between Refs
Only report advisories that were newly introduced between two refs:
whatsdiff audit --from=v2.2.0 --to=v2.3.0
Fail Only on High or Critical Findings
Useful in CI when you want to allow low/medium advisories without blocking the build:
whatsdiff audit --fail-on=high
Audit a Single Ecosystem
Only audit Composer packages, skipping package-lock.json:
whatsdiff audit --include=composer
Skip the Fix-Version Lookup
Run faster by skipping the suggested-fix resolution:
whatsdiff audit --no-fix
Force Fresh Data
Bypass the cache and reload advisories from the registries:
whatsdiff audit --no-cache
Output Formats
Text (default)
Human-readable output with colored severity bullets, package name and installed version, a suggested fix version, and a legend at the bottom counting advisories by severity. CVE IDs are rendered as clickable hyperlinks in terminals that support OSC 8.
JSON
Machine-readable output suitable for scripts and CI integrations. Sample (trimmed to a single advisory):
{
"mode": "current",
"from": null,
"to": null,
"summary": {
"vulnerable_packages": 2,
"total_advisories": 4,
"by_severity": {
"critical": 0,
"high": 0,
"medium": 0,
"low": 0,
"unknown": 4
},
"max_severity": "unknown"
},
"audits": [
{
"name": "symfony/cache",
"type": "composer",
"installed_version": "v8.0.5",
"suggested_fix_version": "v8.0.12",
"max_severity": "unknown",
"advisories": [
{
"advisory_id": "PKSA-z7t6-zt6p-wtng",
"cve": "CVE-2026-45073",
"title": "CVE-2026-45073: SQL Injection in PdoAdapter::doClear() via Unsanitized $prefix",
"link": "https://symfony.com/cve-2026-45073",
"affected_versions": ">=8.0.0,<8.0.12",
"severity": "unknown"
}
]
}
]
}
In diff mode, mode is "diff" and from / to hold the resolved commit hashes.
Markdown
A markdown report with a summary table and one section per severity, suitable for pasting into PR descriptions or issues:
# Security Audit
## Summary
| Severity | Count |
|----------|-------|
| Unknown | 4 |
## Unknown
### symfony/cache (`v8.0.5`)
**Fix available:** upgrade to `v8.0.12`
| ID | Severity | Title |
|----------------------------------------------------------|----------|----------------------------------------------------------------------------------|
| [CVE-2026-45073](https://symfony.com/cve-2026-45073) | Unknown | CVE-2026-45073: SQL Injection in PdoAdapter::doClear() via Unsanitized $prefix |
Exit Codes
The command uses standard exit codes for integration with scripts and CI/CD pipelines:
| Exit Code | Status | Description |
|---|---|---|
0 |
SUCCESS | No advisories meet the --fail-on threshold |
1 |
FAILURE | At least one advisory meets or exceeds the threshold, or invalid options were passed |
2 |
ERROR | Lock file missing, network/registry error, or git error |
Pass --fail-on=none to always exit 0 regardless of findings (useful when you only want the report).
Use Cases
1. CI/CD - Fail the Build on High or Critical Advisories
Block deployments when a serious vulnerability is detected, while tolerating low/medium ones:
name: Security Audit
on: [pull_request, push]
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Need full history for diff-mode runs
- name: Install whatsdiff
run: composer global require whatsdiff/whatsdiff
- name: Audit dependencies
run: whatsdiff audit --fail-on=high
Tighten or loosen the gate by changing --fail-on (critical, high, medium, low, or none).
2. Pull Request - Only Report Newly Introduced Advisories
In a PR pipeline, use diff mode to surface only the vulnerabilities a change introduces, ignoring pre-existing ones already present on main:
- name: Audit new advisories vs main
run: |
whatsdiff audit \
--from=origin/main \
--to=HEAD \
--format=markdown \
--fail-on=medium \
> new-advisories.md
- name: Comment on PR
uses: marocchino/sticky-pull-request-comment@v2
with:
path: new-advisories.md
This keeps PR feedback focused on what the author actually changed.
Supported Lock Files
composer.lock(PHP/Composer)package-lock.json(JavaScript/npm)
Both files are audited automatically if present in your project. Use --include or --exclude to scope the audit to a single ecosystem.