The files field in package.json is an allowlist of what goes into your published npm package. A root .npmignore does not override it, though one in a subdirectory does. If you set neither, npm falls back to .gitignore. An allowlist is safer than a blocklist because new files stay out by default.
What the docs say
The npm package.json documentation describes files as an array of patterns for entries included when the package is installed as a dependency. Leaving the field out includes everything by default.
Some files are always included: package.json, the README, the LICENSE, the file named in main, and the files named in bin. Some are ignored by default, such as .DS_Store, .git, node_modules and lock files. Most can be re-included with a pattern, but the docs say .git, .npmrc, node_modules, package-lock.json, pnpm-lock.yaml and yarn.lock cannot be included.
On .npmignore: at the root of the package it will not override the files field, but in subdirectories it will. Without an .npmignore, .gitignore is used instead.
Why this is a security question
Published packages are public and permanent in practice, even after unpublish. Accidentally shipped files cause real incidents: environment files, test fixtures with real credentials, internal scripts, and source maps. A blocklist approach, where everything ships unless excluded, fails the first time someone adds a new file.
An allowlist reverses that. Only listed paths ship.
How to set it up
- Add a files array listing only your build output and any needed assets, such as the dist folder.
- Remove reliance on .npmignore at the root, where it does not override files.
- Check subdirectory .npmignore files, which do take effect.
- Run npm pack with the dry run option in CI and compare the file list to what you expect. See npm pack dry run: check what you are about to publish.
- Fail the release if the list contains env files, key files or map files you did not plan to ship.
| Method | Default behavior | Risk |
|---|---|---|
| No files field, no .npmignore | .gitignore is used, everything else ships | Higher |
| .npmignore at root only | Blocklist with gaps | Medium |
| files allowlist | Only listed paths ship | Lower |
Common mistakes
People add an npmignore at the root and assume the files field is now irrelevant, or the reverse. The docs say the root npmignore does not override files. Teams also check the repository but never open the tarball, so ignored paths in one place and shipped paths in another go unnoticed. Finally, a files pattern that is too broad, such as a whole source folder, can pull in fixtures and example config. Be as specific as the package allows.
Quick check
Does a root .npmignore override the files field?
No. According to the npm docs, at the package root it does not override files, but in subdirectories it does.
What happens if I have neither files nor .npmignore?
npm uses .gitignore, and everything not ignored there is included.
Safeguard's free scan at gold.safeguard.sh/scan checks the dependencies you consume, and its policies can gate dependency changes before merge.
Sources
Last reviewed: 19 October 2026.