lpm audit
Scan installed packages for vulnerabilities, behavioral risks, and (optionally) hardcoded secrets.
lpm auditWalks every installed package and reports:
- Confirmed vulnerabilities — npm packages are cross-referenced against OSV.dev;
@lpm.dev/*packages get vulnerability data from the registry's per-version metadata. - Behavioral flags — static analysis surfaces risky behaviors (
eval,child_process, network access, filesystem writes, native code, etc.). Registry-provided behavioral metadata for@lpm.dev/*packages is normalized into the same severity ladder, including info-level tags such as WebSockets and URL string literals. See the full tag list underlpm query. - Quality score — for
@lpm.dev/*packages. Scores below 40 surface as moderate; below 20 surface as high. - Dependency-confusion warnings — when an installed
@lpm.dev/*package's bare name collides with a popular npm package (react,lodash, etc.), the audit warns about the registry-confusion risk. - Optional secret scan — with
--secrets, scans the installed source for hardcoded API keys, tokens, and private keys.
Works in any project, not just LPM.dev Registry-published ones. Discovery walks lpm.lock, package-lock.json, pnpm-lock.yaml, yarn.lock, or bun.lock (text form). Without a supported lockfile, it recursively walks nested node_modules/ package directories without following symlinks and reports that inventory as degraded.
The vulnerability scan fails closed. If OSV.dev is unavailable, returns an incomplete batch, or omits advisory details that cannot be hydrated, lpm audit exits non-zero and never reports a clean audit. The same applies when the LPM.dev Registry cannot return exact metadata for an installed @lpm.dev/* version. Under --json, an incomplete OSV scan returns the audit envelope with success: false, osv_degraded: true, and osv_degraded_reason; other registry failures use the standard error envelope.
The signatures subcommand is a focused check for npm registry package signatures. It verifies the installed package set against npm-compatible dist.signatures metadata and exits non-zero when any registry package cannot be verified.
Examples
lpm audit
lpm audit --level high # only show high-severity findings
lpm audit --secrets # also scan for hardcoded credentials
lpm audit --fail-on vuln # CI: exit non-zero only on confirmed vulns
lpm audit --fail-on behavior # CI: exit non-zero only on critical behaviors
lpm audit --secrets --fail-on secrets # CI: exit non-zero only on hardcoded secrets
lpm audit --fail-on all # CI: exit non-zero on either (default)
lpm audit signatures # verify npm registry package signatures
lpm audit signatures --json # machine-readable signature report
lpm audit fix # bump vulnerable direct deps and reinstall
lpm audit --fix --dry-run # plan the same fixes without writing files
lpm audit --json # structured output for toolingCI gating
lpm audit exits non-zero when its findings trip the active --fail-on policy. The implicit default is conservative — high-severity behavioral signals like eval don't fail CI unless you ask for them explicitly with --fail-on all.
An incomplete vulnerability scan always exits non-zero, regardless of --fail-on. A network or advisory-data failure is not evidence that the installed tree is clean.
| Policy | Exit code 1 when |
|---|---|
| (no flag, implicit default) | Vulnerabilities or critical behavioral flags (obfuscation, protestware, high-entropy strings). Excludes high behaviors so existing pipelines that tolerate eval don't break. |
vuln | Any confirmed vulnerability — OSV (npm) or registry-side advisory (@lpm.dev) |
behavior | Any critical or high behavioral flag |
secrets | Any hardcoded-secret finding from lpm audit --secrets |
all (explicit) | Vulnerabilities + critical behaviors + high behaviors + secrets — the strict union |
For finer control, use lpm query — its CSS-like selectors target individual flags or combinations.
Fixing vulnerabilities
lpm audit fix
lpm audit --fix
lpm audit fix --dry-runlpm audit fix is the canonical form; lpm audit --fix is an alias for npm-compatible muscle memory. Both read the package exposed at each direct root node_modules path and match its exact name and version to the lockfile, so transitive copies cannot be selected merely because they have a higher matching version. If the lockfile contains multiple source identities for that same installed name and version, the dependency is reported as source-ambiguous and skipped rather than guessing or sending its name to a metadata endpoint. They support dependencies, devDependencies, optionalDependencies, npm aliases such as npm:lodash@^4, and registry advisories for @lpm.dev/* packages.
For npm packages, the fixer evaluates every relevant OSV affected range against available registry versions and chooses the lowest newer version proven unaffected. This preserves maintained release lines when a patch exists instead of jumping to the highest fixed version from another major line. On apply, the manifest entry is pinned to that exact planned version (npm aliases retain their npm: identity), and verification rejects any different installed version; dry-run and apply therefore report the same target. Complex or non-registry source protocols such as catalog:, workspace:, file:, git, and JSR are reported as skipped rather than rewritten into semver dependencies. Transitive-only findings are not changed.
The fix pass currently operates only in LPM CLI-managed projects; it does not rewrite npm / pnpm / yarn / bun lockfiles. Fix and dry-run planning hold the project's install transaction lock against other LPM operations. Immediately before the first write, a real fix also compares the exact package.json bytes read for planning and aborts without overwriting if an editor or another process changed them. It then snapshots package.json, lpm.lock, and lpm.lockb, invalidates the install cache, reinstalls silently, and rechecks the exact version installed against OSV.dev or exact LPM.dev Registry metadata. --json therefore emits one audit-fix document without nested install output. A failed install or verification restores the snapshotted files; because node_modules/ is not copied as part of the transaction, run lpm install after a failed fix if the installed tree needs to converge with the restored lockfile.
--dry-run reports the same plan without mutating package.json, lpm.lock, or node_modules.
Registry signatures
lpm audit signaturesVerifies npm registry package signatures for the installed tree. LPM CLI reads lpm.lock when present; for lockfiles from other package managers it uses the discovered installed package list and hydrates npm metadata as needed.
Human output is intentionally compact:
! Registry signatures · 1 verified · 1 not verified
unsigned-pkg@1.0.0 missing dist.signaturesA clean tree exits zero:
✓ Registry signatures verified · 247 verifiedUnder --json, the envelope includes aggregate counts and one row per package:
{
"success": false,
"scanned": 2,
"verified": 1,
"not_verified": 1,
"skipped": 0,
"packages": [
{ "name": "signed-pkg", "version": "1.0.0", "status": "verified", "signatures_verified": 1 },
{
"name": "unsigned-pkg",
"version": "1.0.0",
"status": "not_verified",
"reason": "missing_signatures",
"reason_detail": "missing dist.signatures",
"signatures_verified": 0
}
]
}Statuses are verified, not_verified, or skipped. Skipped rows cover packages outside this signature surface, such as non-registry sources and @lpm.dev/* packages. Any not_verified row makes the command exit with code 1.
Severity levels
lpm audit --level highSuppresses anything below the threshold. Ladder from most-to-least severe: critical → high → moderate (alias medium) → info (alias low). Default is info (show everything). Any other value is rejected as a usage error before the audit starts.
Secret scanning
lpm audit --secretsScans the installed source tree under node_modules/ for hardcoded API keys, access tokens, private keys, and similar credentials — the same scanner that runs as part of lpm publish. Useful as a final check before shipping a Docker image or deploying.
Requires node_modules/ to exist (errors with a run \lpm install` firsthint otherwise).--secretsstill runs as its own scan mode, but it participates in--fail-on`:
lpm audit --secretsuses the command's default gate policy (all), so a detected secret exits non-zero.lpm audit --secrets --fail-on secretsgates on secret findings only.lpm audit --secrets --fail-on vulnor--fail-on behaviorkeeps the secret scan informational.--levelis still ignored in secrets mode.
Flags
| Flag | Effect |
|---|---|
--level <critical|high|moderate|info> | Minimum severity to report (default: info; aliases: medium, low) |
--fail-on <vuln|behavior|secrets|all> | CI exit-code policy (secrets applies to --secrets; all includes secret findings too) |
--secrets | Scan installed source for hardcoded secrets (separate scan mode; consults --fail-on, still ignores --level) |
--fix | Alias for lpm audit fix |
--dry-run | With --fix, show the fix plan without changing files |
Plus the global flags — --json is especially useful for piping into CI gates.
Subcommands
| Subcommand | Effect |
|---|---|
fix | Update vulnerable direct dependency instances to verified unaffected versions, then reinstall |
signatures | Verify npm registry package signatures for the installed tree |
See also
lpm query— inspect packages by behavioral tag- Security audit — concept overview and tag reference
lpm publish— runs the same secret scanner before upload