Skip to Content
GuidePackage Manager

Package Manager

3va install axios --allow-net=registry.npmjs.org # from npm 3va install react@18 --allow-net=registry.npmjs.org # specific version 3va install @std/path --allow-net=jsr.io # from JSR 3va reinstall axios --allow-net=registry.npmjs.org # force-reinstall one package 3va update --allow-net=registry.npmjs.org # update to latest versions

Post-install scripts are blocked by default

preinstall, install, and postinstall lifecycle scripts are not executed by 3va install unless the project names the package in its own package.json:

package.json
{ "3va": { "onlyBuiltDependencies": ["esbuild"] } }

pnpm’s onlyBuiltDependencies and Bun’s trustedDependencies are read as well. Being on the list is not enough on its own:

  • A script that is a single JavaScript file (node install.js) runs inside 3va’s sandbox, with only the permissions your project’s package.json grants that package under "3va".permissions.<pkg>. Whatever the dependency declares in its own package.json is ignored.
  • A shell command (prebuild-install || node-gyp rebuild) is refused, even for a listed package. 3va doesn’t pass a package-authored string to a shell.

3VA_ALLOW_SCRIPTS=1 no longer enables scripts: a process-wide environment variable isn’t a decision anyone can review.

Trusting a package the scanner rejects

The malware scan grades packages by their contents, so tools whose job is to spawn compilers or evaluate code can be rejected. After reviewing one, pin the exact artifact:

package.json
{ "3va": { "trusted": ["oxlint@1.85.0"], "trustedIntegrity": { "oxlint@1.85.0": "sha512-…" } } }

A versioned pin stops applying when the version changes, so an upgrade is scanned again. trustedIntegrity also pins the bytes. A pin without a version doesn’t override a failed scan: pin name@version.

Storage: global content-addressable dedup

Package storage uses the same model as pnpm: a package at version X is stored once on disk (in a global store, relocatable via _3VA_STORE, default ~/.3va/store/), and multiple projects reference it while declaring their own permissions independently — installing the same package in two projects doesn’t double the disk usage, and doesn’t share one project’s granted permissions with another.

3va install resolves all of package.json as one dependency graph, so a transitive or peer range can’t replace the version a direct dependency asked for, and two packages can’t race linking the same files.

It writes 3va-lock.json (sorted, stable between runs) and installs from it without contacting the registry when the store already has every package.

Prerelease versions no longer satisfy plain ranges: >=5.0.0, * or latest could resolve to a nightly build (7.1.0-dev…). A prerelease now matches only when the range names a prerelease of the same major.minor.patch, as in npm.

Audit

3va audit # malware scan + OSV CVE scan (24h cache) 3va audit --secrets # also scan for leaked credentials 3va audit --deny # exit non-zero on CRITICAL/HIGH findings or an incomplete scan 3va audit --json # machine-readable output

Audit runs in three phases:

  1. Malware scan — static analysis of node_modules for known malicious patterns.
  2. OSV CVE scan — queries api.osv.dev for known vulnerabilities; results are cached 24 hours.
  3. Secrets detection (opt-in via --secrets) — 21 patterns covering AWS keys, GitHub/GitLab tokens, Stripe keys, Slack/SendGrid/Twilio keys, private certificates, JWT secrets, npm tokens, database connection strings, and generic passwords/API keys — scanned over the current project’s source files.

A lighter automatic malware scan already gates every downloaded tarball during 3va install (using the same scanning engine as 3va audit, aborting the install on high-severity findings). The full 3va audit command — OSV/CVE scan and, opt-in, secrets detection — does not run automatically; run it yourself after adding new dependencies. See Roadmap for more on this distinction.

Supply-chain checks at install time

  • Tarball integrity — SHA-256/SHA-512 verification. A package with a missing or unknown hash is refused, and a hash that doesn’t match the lockfile aborts the install.
  • 3va ci — installs the lockfile’s versions, transitive packages included, and fails if any package is recorded without a hash.
  • Dependency-confusion protection — .npmrc-pinned scopes resolve only against their private registry; public fallback is refused. A registry set in .npmrc must be in --allow-net, and must use HTTPS unless it is on loopback.
  • Store verification — 3va store verify compares every stored file with the digest recorded when it was stored.
  • Typosquatting detection — edit-distance check against an embedded popular-packages list, warned during install.
  • npm provenance (opt-in strict mode, --require-provenance) — verifies the signing certificate against Sigstore’s Fulcio root and the Rekor transparency-log entry. The signer must be a build of the repository the package declares. The first verified signer of each package is recorded in .3va/provenance-signers.json (commit it); a later release signed by a different identity, or shipped without provenance, is refused.

For install-time performance (3va vs. npm vs. Bun, same package, same warm-cache condition), see the Comparison table — those CI-measured numbers are the only authoritative source; treat any other install-timing figure as stale.