Documentation menu

Guides

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.