Locked dependency vulnerability audits
flog audit is a read-only check of exact registry package versions reachable
in the committed flog.lock graph. It validates the lock against every
workspace manifest before making a request and never resolves versions,
installs packages, changes package.json or flog.lock, touches
node_modules, executes scripts, or applies fixes.
flog audit
flog audit --prod
flog audit --workspace @example/web --prod
flog audit --json
--prod removes development roots and development-only workspace reachability.
Runtime dependencies,
optional dependencies selected by the lock, and required peer providers remain
in scope. --workspace uses Flog's exact workspace name/path selection and may
be repeated. The report identifies the selected lock target and whether each
finding is direct or transitive from each reachable workspace, without printing
the complete clean dependency tree.
Advisory source and privacy#
The initial source is the npm-compatible Bulk Advisory endpoint:
/-/npm/v1/security/advisories/bulk. Flog groups the selected graph by the
registry chosen for each real package name by .npmrc (aliases therefore use
their resolved package identity). Each request contains only package names and
the exact locked versions needed for that registry group. It contains no
manifests, source, dependency paths, tokens, unrelated workspaces, or complete
private graph.
Before querying, Flog verifies that each locked tarball belongs to that
package's configured registry host and path. A private artifact from another
source is marked uncovered and its name is not sent to the configured public
registry. Scoped registries are queried only for their own selected packages.
Credentials use the same longest-path matching and redacted diagnostics as
other registry reads. HTTPS is required; FLOG_ALLOW_HTTP=1 exists only for
isolated mock-server testing.
Registries that do not implement the Bulk Advisory endpoint, source mismatches, HTTP refusal, request limits, timeouts, network errors, non-success responses, oversized responses, and malformed or internally inconsistent responses make the audit incomplete. They are never reported as a clean result. Coverage is summarized by registry and count without listing a clean private package inventory.
The Bulk Advisory protocol returns keys only for packages with matching advisories, so an absent requested package is the protocol's normal clean answer, not evidence of truncation. Flog detects truncated JSON, failed batches, unexpected package keys, null arrays, malformed advisories, and conflicting duplicates; if any batch fails, that registry group is uncovered rather than partially accepted.
Findings and policy#
For every returned advisory, Flog independently checks its npm semver range against each exact locked version. Findings contain package/version, advisory ID, URL, title, severity, vulnerable range, direct/transitive status, workspace reachability, registry provenance, and fetch time. Duplicate peer contexts with the same package identity and version are queried once while retaining their reachability.
Every advisory affecting an exact locked version is a finding, regardless of
its reported severity. A missing or unrecognized severity is reported as
unknown; it is never silently treated as safe.
When flog lock or flog add is about to commit a changed graph, Flog runs a
separate fail-closed pre-commit policy over every proposed lock target. The
check happens after overrides and complete resolution, but before flog.lock
or package.json is replaced. It compares exact real package name/version
identities with the validated prior lock:
- an affected identity already present in the prior lock is reported as retained and does not block the reconciliation;
- a newly introduced or changed affected identity blocks the write;
- every affected identity is new when creating the first lock; and
- an incomplete advisory check blocks all writes and is never called clean.
flog lock --force and flog add --force explicitly commit despite complete,
known new findings after printing each package, version, advisory, severity,
title, and URL. Force never bypasses incomplete coverage, an unavailable
endpoint, malformed data, or a timeout. It does not prompt, add an override, or
claim a remediation. add retains its transaction boundary: a blocked policy
leaves both the manifest and lock byte-identical. A permitted change proceeds
through the normal installation phase.
Exit statuses are stable for CI:
| Status | Meaning |
|---|---|
0 |
Complete check with no findings |
1 |
Incomplete or failed check, including stale/missing lock coverage |
2 |
Invalid command usage |
4 |
Complete check with one or more findings |
JSON output has schemaVersion: 1, deterministic arrays, explicit status,
selection, source, summary, coverage, findings, and failures.
Scope and npm differences#
This command reports advisories whose ranges affect exact versions already in
Flog's selected locked graph. It does not implement npm's meta-vulnerability
calculation, remediation planning, npm audit fix, automatic manifest changes,
or npm-specific dependency layout analysis. Production selection is analogous
to npm audit --omit=dev, but Flog derives it from Flog's workspace, optional,
and peer-provider graph, so counts need not match a differently materialized npm
tree. Representative fixtures compare affected and patched exact versions,
development omission, aliases, scoped names, duplicate paths, optional and peer
edges, and failure behavior against the Bulk Advisory contract rather than
claiming full npm CLI parity.
An independently inspected live comparison on 2026-10-31 used Node 26.11.1 and
npm 11.20.0 with production-only one-package fixtures. For fflate@0.7.3, both
commands reported npm advisory 1164783 / GHSA-px8p-9vwx-vf98, moderate
severity, and vulnerable range >=0.7.0 <0.7.5; both treated fflate@0.7.5 as
clean. npm additionally emitted install-layout nodes and a 0.7.5 remediation
plan. Flog deliberately emitted exact lock reachability and coverage instead,
and did not claim or apply a fix.
The response is a point-in-time online observation from the named registry. Advisories can be added or corrected later, and a clean response is not an immutable guarantee that the dependency graph is safe. Preserve the JSON report when provenance and fetch time matter.