PackAttest
See it. Select it. Ship it.
Early prototype · v0.1.0 · MIT licensed · Feedback welcome
PackAttest is a small command-line tool for the npm ecosystem that prevents accidental file leaks in published packages. It treats the final tarball as the source of truth and requires explicit human approval of every file before release.
Install globally and run pa review from any package directory:
npm install -g packattest
pa review
The problem
In npm, what gets published is typically defined by .npmignore or the
files field in package.json. These are configured
before the final artifact exists.
Build tools evolve. Defaults change. Outputs drift. New files appear. And nothing in
most workflows requires a human to review the actual artifact before it is published.
The result is a recurring class of incident: source maps exposing internal logic,
.env files bundled by accident, debug artifacts and test data shipping
to production.
npm pack --dry-run can show you the contents, but it is optional, has no
memory of the previous release, and leaves no record that a review happened. Hope is
not a security property.
The model
- Artifact is truth. Decisions are based on the final packaged tarball — not the source tree, not configuration files. If it is in the tarball, it ships.
- Explicit human approval. Before publishing, every file in the artifact must be consciously selected. No implicit inclusion, no silent defaults.
- Attestation. Approval is recorded as a verifiable file — artifact hash, selected files, reviewer identity, source commit — and committed alongside the code.
- CI enforcement. The pipeline rebuilds the artifact and compares it to the attestation. If anything has changed since review, publishing fails hard.
How it works
PackAttest exposes three commands:
pa review — pack the artifact, diff it against the
version currently tagged latest on the registry, and present the exact
file list. Nothing is preselected; every file must be toggled and confirmed.
After review, an attestation file is written to the repository:
{
"version": 1,
"package_name": "your-package",
"package_version": "1.4.0",
"artifact_hash": "sha256:6ecd7fb...",
"selected_files": [
"package/dist/index.js",
"package/package.json",
"package/README.md"
],
"reviewed_at": "2026-04-04T16:01:27.907Z",
"reviewer": "git:your-name",
"source_commit": "595b0df...",
"tool_version": "0.1.0"
}
pa publish — verify the current artifact against the
attestation and publish locally.
pa verify — the same verification flow for CI, with
structured log output. Rebuilds the artifact, checks the hash, and publishes only if
everything matches. If the artifact has drifted since pa review, the
pipeline fails.
What it doesn't solve
PackAttest is intentionally narrow. It helps prevent accidental file inclusion, unexpected build artifacts, and scope expansion between releases.
It does not:
- detect secrets inside otherwise-intended files
- stop deliberate malicious publishing
- protect compromised developer environments
Those are different problem spaces, requiring different tools. PackAttest addresses one specific, common, and repeatedly demonstrated failure mode: not realizing a file was in the package.
Get started
Install from npm:
npm install -g packattest
Or install from source:
git clone https://github.com/divohna/PackAttest.git
cd PackAttest && npm install && npm install -g .
Then, from any package directory:
pa review
Feedback, critiques, and contributions welcome.