Chapter 07Lesson 01135–175 min

npm Repositories, Scoped Packages, Metadata, Tokens, Proxying, and JavaScript Supply Chains: Concepts, Architecture, and Mental Model

Model npm registry behavior through Nexus: package and scope identity, metadata documents and tarballs, dist-tags, hosted/proxy/group routing, scoped authentication, and dependency-confusion boundaries.

npm registryScopesMetadataTarballsdist-tags

Learning objectives

  • Explain npm package identity, scopes, versions, dist-tags, metadata documents, and tarball assets without treating them as one object.
  • Map npm client requests onto Nexus hosted, proxy, and group repositories and identify which state is authoritative versus cached.
  • Explain registry and credential scoping in .npmrc, including why authentication must be bound to a registry host/path.
  • Recognize dependency-confusion risk when internal namespaces can fall through to a public upstream.
  • Inspect current Nexus/npm state before publishing or changing repository configuration.

Current lab baseline. Nexus Repository Community Edition 3.95.0, Java 21 on the Nexus side, a current npm 12 client, and loopback Nexus URL http://127.0.0.1:8081. npm group publication through a configured writable member is a Nexus Repository Pro feature; the mandatory Community path publishes directly to hosted and reads through the group.

1. The practical problem: npm has more than “a package file”

Chapter 06 used Maven coordinates and repository metadata. npm has the same broad producer → repository → consumer shape, but its protocol is different. A client first asks a registry for a package metadata document. That document describes versions, distribution tags, tarball URLs, integrity values, dependencies, and other package fields. The client then fetches the selected tarball asset. If you diagnose only the tarball, you can miss a stale or misrouted metadata document; if you inspect only a package page in the UI, you can miss the registry URL or credential path the client actually used.

The operating model therefore separates package identity, registry metadata, immutable package-version tarballs, mutable dist-tags, Nexus database records, blob content, proxy cache, npm's local cache, and authentication state. These are related, but none is a synonym for “the npm package.”

2. Package identity: unscoped and scoped names

An unscoped package is identified by a name such as left-pad. A scoped package adds a namespace prefix such as @learner-example/ch07-demo. The scope is part of the package name, not merely a UI folder. npm can map a scope to a specific registry, so every request for @learner-example/* can be forced toward an internal Nexus endpoint while unrelated public packages use another controlled endpoint.

Concept Example Operational meaning
Package name @learner-example/ch07-demo Logical package identity; the scope is part of the name.
Version 1.0.0 Published version identity. npm publication rejects reusing an existing name/version combination.
dist-tag latest, candidate Mutable label that points to a version; it is not artifact identity.
Metadata document Registry JSON for the package Lists versions, dist-tags, tarball URLs, integrity and package metadata.
Tarball ch07-demo-1.0.0.tgz Compressed package bytes selected by metadata.
Integrity typically SHA-512 SRI data Detects byte changes against expected registry metadata; not proof of trusted provenance.

3. npm request flow through Nexus

npm metadata and tarball flow
flowchart LR
C[npm client] -->|metadata request| G[npm group]
G --> H[internal npm hosted]
G --> P[npm proxy]
P --> U[registry.npmjs.org]
H --> D[(Nexus database records)]
P --> D
H --> B[(blob store tarballs/metadata assets)]
P --> B
D --> G
B --> G
G -->|package metadata + tarball| C

The client uses the group as one read endpoint. The group searches its members in configured order. Internal packages should normally be found in the internal hosted member before a public proxy is allowed to satisfy the same namespace. The proxy is a managed cache of the public upstream; it is not the authoritative place to publish internal packages. The hosted repository is organization-controlled origin storage.

On current Nexus releases, npm groups can optionally route writes to a designated hosted member, but Sonatype documents that capability as Pro-only. That exception does not change the underlying ownership model: the selected hosted member stores the package.

4. Metadata, tarballs, and dist-tags are different state

Publishing @learner-example/ch07-demo@1.0.0 creates/updates the package metadata and stores a tarball. A later npm dist-tag add @learner-example/ch07-demo@1.0.0 candidate changes a pointer in package metadata; it does not rewrite the 1.0.0 tarball. If the tag moves to 1.1.0 tomorrow, @candidate resolves differently while @1.0.0 remains the same version identity.

This distinction is critical in CI/CD. Deployment records should capture the immutable package version and tarball integrity/digest. A dist-tag is useful for channels such as candidate or latest, but it should not be the only evidence of what was tested or released.

5. Registry selection and credential scoping

npm chooses a registry from configuration. Unscoped packages use the default registry. A scope can have its own registry mapping. Authentication settings such as _authToken must be scoped to a registry host/path; current npm documentation explicitly warns against unscoped auth because credentials could be sent to the wrong registry.

registry=http://127.0.0.1:8081/repository/academy-ch07-group/
@learner-example:registry=http://127.0.0.1:8081/repository/academy-ch07-group/

; Authentication, when needed, must be scoped to the exact registry path.
; Do not commit a real token.
//127.0.0.1:8081/repository/academy-ch07-hosted/:_authToken=${NPM_TOKEN}

The example demonstrates structure only. In the mandatory lab, npm writes a transient bearer credential to a private, disposable .npmrc after interactive login. That file lives under the lab directory rather than in the user's normal home directory, and it is never printed into evidence.

6. Three things people call “npm tokens”

Terminology matters. npmjs.com has its own access-token models. Nexus can use the npm Bearer Token Realm so npm login --auth-type=legacy authenticates an existing Nexus user and stores a registry-scoped bearer credential for the npm client. Separately, Nexus Repository Pro has a User Token feature that substitutes token credentials for a Nexus user across tools. Do not conflate those mechanisms or assume a public npm token works against Nexus.

For Community Edition training, use the npm Bearer Token Realm with a disposable local user or a carefully scoped basic-auth fallback. Pro User Tokens are optional architecture material, not a mandatory lab prerequisite.

7. Dependency confusion is a routing and namespace problem

Suppose your application depends on @learner-example/payments and your internal group searches a public proxy before the internal hosted repository, or your client bypasses Nexus and sends that scope to the public registry. An attacker-controlled public package with a colliding name can become a candidate. A strong design combines scope ownership, group member order, Nexus routing rules where appropriate, and network/client policy that prevents uncontrolled public fallback.

Important: a scope name alone is not a security boundary. It becomes meaningful only when client configuration, repository ordering, authorization, and egress policy consistently enforce where that scope may resolve from.

8. Read-only inspection before mutation

Before creating Chapter 07 repositories, record the current instance and client state. In Nexus, inspect Settings → Repository → Repositories and note existing npm hosted/proxy/group repositories, their URLs, member order, blob stores, remote URL, and online status. In npm, inspect configuration without exposing secrets.

set -eu
LAB="${TMPDIR:-/tmp}/nexus-ch07-inspect"
mkdir -p "$LAB/cache"
chmod 700 "$LAB"
export NPM_CONFIG_USERCONFIG="$LAB/npmrc"
export NPM_CONFIG_CACHE="$LAB/cache"

printf 'node: '; node --version
printf 'npm:  '; npm --version
npm config get registry
npm config get @learner-example:registry || true

# Show effective keys carefully; do not capture real auth lines in shared evidence.
npm config ls --location=user | sed -E '/(_auth|_authToken|password|token)/Id'

On Windows PowerShell, use a directory under $env:TEMP, set $env:NPM_CONFIG_USERCONFIG and $env:NPM_CONFIG_CACHE, and remove credential-bearing lines before sharing output. The goal is to prove which configuration file and registry are active, not to dump secrets.

9. Why this matters in DevOps

npm is frequently used by both humans and automated builds, and package installation can execute lifecycle scripts. A production-grade repository path must therefore make identity, registry selection, authentication, public-upstream mediation, cache state, and package integrity observable. “npm install succeeded” is only a transport outcome; it is not proof that the intended namespace, version, provenance, vulnerability policy, or lifecycle-script policy was correct.

Knowledge check

What is the difference between a package version and a dist-tag?

Why should authentication in .npmrc be scoped to a registry URL?

Does a Nexus npm proxy own an internally published package?

Can a scope by itself prevent dependency confusion?

Is the Nexus Pro User Token feature the same thing as the npm Bearer Token Realm?

Next lesson

Build the disposable npm topology

Create hosted, proxy, and group repositories, isolate npm client state, publish a synthetic scoped package, and trace metadata plus tarball bytes through Nexus.

Official references and version notes

Version-sensitive statements were rechecked against Sonatype and npm primary documentation on 2026-08-26. The mandatory lab assumes Nexus Repository Community Edition 3.95.0 and a current npm 12 client; record npm --version and node --version locally because npm/Node compatibility evolves independently of Nexus. Nexus 3.87+ requires Java 21 for supported self-hosted deployments. Re-check current release/support pages before executing the lab.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.