What's diff whatsdiff
CLI Tool

Audit Command

List known security advisories affecting your installed dependencies.

On this page 8

audit reports the known security advisories affecting the versions you actually have installed. It covers composer.lock and package-lock.json in a single pass, and for each vulnerable package it resolves the lowest version that fixes the problem.

The audit command output

bash
whatsdiff audit
code
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)

In an interactive terminal the severity bullets are coloured (red for critical and high, yellow for medium, cyan for low, grey for unrated) and CVE IDs become clickable links wherever the terminal supports OSC 8.

Three modes

By default, audit reads the lock files in your working tree.

--at audits the lock file as it existed at a given commit, tag, or branch:

bash
whatsdiff audit --at=v2.3.0

--from and --to switch to diff mode, which reports only the advisories a change introduces and leaves pre-existing ones alone. In a pull request pipeline this keeps the feedback on what the author actually touched:

bash
whatsdiff audit --from=v2.2.0 --to=v2.3.0

Options

Option Description
--from Commit, branch, or tag to compare from (enables diff mode)
--to Commit, branch, or tag to compare to (defaults to HEAD)
--at Audit the lock file at a given commit, tag, or branch
-f, --format Output format: text (default), json, or markdown
--no-fix Skip the suggested-fix lookup, saving the extra registry calls
--include Only these package managers (comma-separated: composer, npmjs)
--exclude Everything but these package managers
--fail-on Severity threshold for a non-zero exit: low (default), medium, high, critical, or none
--allow-unrated Do not trip --fail-on on advisories with no upstream severity rating
--no-cache Bypass the cache and fetch fresh advisories
Note

--at cannot be combined with --from or --to, and --include cannot be combined with --exclude.

An advisory whose severity has not been rated upstream yet counts towards any --fail-on threshold, so a pending CVSS score never slips through. Pass --allow-unrated if you would rather not block on those.

Exit codes

Code Meaning
0 No advisory meets the --fail-on threshold
1 An advisory meets or exceeds the threshold, or the options were invalid
2 Lock file missing, or a network, registry, or git error

Pass --fail-on=none to always exit 0 when you only want the report.

Output formats

The text format above is the default: a coloured list with the installed version, a suggested fix, and a legend counting advisories by severity.

JSON

bash
whatsdiff audit --format=json

Trimmed to a single advisory:

json
{
    "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 and to hold the resolved commit hashes.

Markdown

bash
whatsdiff audit --format=markdown > security-report.md

A summary table followed by one section per severity, ready to paste into a pull request or an issue:

markdown
# 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   |

Failing a build on serious advisories

Block the deploy on high and critical findings while tolerating the rest:

yaml
name: Security Audit

on: [pull_request, push]

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0  # diff-mode runs need the full history

      - 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.

Reporting new advisories on a pull request

Diff mode plus markdown output gives you a comment covering only what the branch introduced:

yaml
- 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

Use analyse to see every dependency change rather than the vulnerable ones, or check to test a single package.