Build script produces output
Why it matters
A missing prepublishOnly script means a developer can run npm publish against stale or missing dist/ output — shipping a broken release to every consumer before anyone notices. ISO 25010 fault-tolerance requires that the release process itself catch this class of error. SLSA L1 requires that the build is reproducible and that the published artifact reflects the declared source version. A manual build-then-publish workflow is an invitation for version skew between source and registry.
Severity rationale
Medium because the gap between build and publish is a procedural failure mode that produces broken releases — not a security issue, but a reliability one that affects all consumers of the broken version.
Remediation
Add a prepublishOnly script that guarantees a fresh build runs before every npm publish.
{
"scripts": {
"build": "tsup",
"prepublishOnly": "npm run build"
}
}
prepublishOnly runs automatically before npm publish (not before npm install). For packages that need CI-only publishing, also add a prepack hook — it runs before both npm pack and npm publish. Confirm the build output directory in scripts.build matches the paths in main, module, and exports.
Detection
-
ID:
build-script -
Severity:
medium -
What to look for: List all scripts in package.json. For each build-related script, check
package.jsonscriptsfor abuildscript (or equivalent):- A
buildscript exists and invokes the detected build tool - A
prepublishOnlyscript that runs the build before publishing - The build output directory (
dist/,lib/,build/) exists or would be created by the build script - The
main/module/exportspaths reference the build output directory For Python: check for a build command inpyproject.tomlorMakefile. For Rust:cargo buildis implicit.
- A
-
Pass criteria: A
buildscript exists inpackage.jsonthat invokes the build tool, AND aprepublishOnlyscript exists that ensures the build runs beforenpm publish. The output directory referenced bymain/exportswould be produced by the build — at least 1 build script must be configured (build, prepublishOnly, or equivalent). Report: "X build scripts configured." -
Fail criteria: No
buildscript, OR noprepublishOnlyscript (risk of publishing stale/missing build output), OR the build script exists but its output directory doesn't match whatmain/exportsreference. -
Skip (N/A) when: The package publishes source directly (no build step) — e.g., a pure JavaScript package with no transpilation. Also skip for Go (no build artifact for libraries) and Python packages that use only
pyproject.tomlwith a standard build backend. -
Detail on fail:
"Build script runs 'tsup' but there is no prepublishOnly script. If a developer runs 'npm publish' without building first, stale or missing dist/ files will be published." -
Remediation: Always ensure the build runs before publishing. The
prepublishOnlyscript runs automatically beforenpm publish:{ "scripts": { "build": "tsup", "prepublishOnly": "npm run build" } }Some teams also add a
prepackscript (runs beforenpm pack, whichnpm publishcalls internally). Either works.
External references
- iso-25010:2011 · reliability.fault-tolerance — Fault tolerance — prepublishOnly guards against publishing stale artifacts
- ssdf:800-218 · PS.3.1 — Create and maintain software bill of materials and build provenance
- slsa:1.0 · L1 — SLSA L1 — scripted build ensures reproducible artifact production
Taxons
History
- 2026-04-18·v1.0.0·Initial import from sdk-package-quality·automated