Vulnerabilities
.npmrc vs an npm Token on Production Origins
October 27, 2024
.npmrc vs an npm token on a production origin is a leftover config file versus the credential that file often carries. A reachable /.npmrc is the same class of miss as /.env or /package.json: the marketing CDN served a build artifact that was never meant for browsers. The token belongs in a private CI secret or a server-only env, not in a public object. RoastMyOpsec currently signatures /.env, /.git/HEAD, and /package.json. It may not fetch /.npmrc today. Still deny the name at the edge. Do not list it in robots.txt — that advertises the path instead of closing it.
The practical difference
.npmrc is npm's per-project or per-user config: registry maps, scopes, and sometimes an _authToken line. An npm token is the secret that authenticates to a private registry. Teams copy the project folder into a static bucket and both hitchhike onto the origin.
A token in a public .env is already incident-class — the roast signatures that path. A token living only inside .npmrc is the same incident if the file is downloadable. A token-free .npmrc that only names a private registry is still an inventory leak. None of these files belong next to index.html.
How to choose based on what you shipped
If you shipped a static export or a repo-root sync to the CDN: fail CI when .npmrc appears in the artifact, deny the basename at the edge, and rotate any registry token that might have been in that tree. Keep registry mapping in private CI. Do not Disallow the name in robots.txt as if crawlers were the only readers.
| Option | When it wins | Watch-out | Takeaway |
|---|---|---|---|
| Project .npmrc (no token) | Private repo / CI, registry scope only | Still names private registries if public | Never on the CDN; deny the name |
| npm token in server env | CI and app servers you control | A public /.env is a live leak | Keep off the origin; roast signatures .env |
| .npmrc on the marketing origin | Never | Same class as /.env or /package.json | Incident if it held a token; deny anyway |
| robots.txt Disallow | Crawl budget, not secrets | Publishes the path | Access control is the CDN deny |
When each option wins (never as a public object)
A token-free .npmrc wins in a private repository so CI hits the right registry. An npm token wins as a short-lived CI secret injected at runtime. Neither wins as a downloadable file on the production document root.
If the same publish also left /package.json or /.env, fix the pipeline once. Staging hostnames that are guessable get the same edge deny.
Common mistakes
The first mistake is committing a user-level .npmrc that still has an _authToken and then syncing the repo root to S3.
The second mistake is rotating the npm token but leaving the old .npmrc on the CDN 'until the next deploy.'
The third mistake is adding the filename to robots.txt Disallow and calling the leak closed.
What a URL roast can prove
RoastMyOpsec uses bounded GETs to well-known leftovers and checks file signatures. It signatures /.env, /.env.local, /.git/HEAD, /package.json, and some backup/.DS_Store class paths. It may not fetch /.npmrc today. A clean roast is not proof the file is absent under another prefix. Deny the name at the CDN anyway. No exploit payload, no token use.
Free audit the URL you own
RoastMyOpsec is a defensive public-surface roast: headers, cookies, sensitive paths, and more — no exploit payloads. Start with the free audit, then open the vault if the blurred findings look expensive.
Free audit nowFAQ
- Is a public .npmrc a vulnerability?
- It is an information leak and, if it held a registry token, a credential incident. Remove it from public objects, deny the name at the edge, and rotate anything that may have been inside.
- Does RoastMyOpsec fetch .npmrc?
- Not as a scored path today. The roast does probe /.env and /package.json. Still deny .npmrc at the CDN. It is the same class of miss.
- Should I put the npm token in a public .env instead?
- No. Server-only env on hosts you control. A reachable /.env is incident-class. The roast signatures that path.
Sources
Related guides
Vulnerabilities
Public package.json vs Lockfile Advisories on ProductionVulnerabilities
.env.example vs .env on Production OriginsVulnerabilities
Dockerfile vs package.json on Production Origins