Only the owning team's release process should publish a shared internal library, ideally from CI under a service identity, not from a laptop. For critical libraries, require a second approver before the publish step. This protects consumers from both mistakes and compromised accounts.
Why publish rights matter
A published version is trusted by every consumer who updates. If an attacker or a careless change reaches the internal registry under a trusted name, services pick it up in their next build. Publish rights are therefore as sensitive as production deploy rights.
Principles
- Least privilege. Publish rights belong to the owning team, not to every engineer in the company.
- No personal tokens in CI. Use a credential scoped to that library and held by a team or workload identity.
- Immutable versions. The Semantic Versioning specification says released contents must not be modified, so configure the registry to reject overwrites.
- Reviewed source. Only the protected main branch or release tags can trigger a publish.
- Audit trail. Log who triggered each release and from which commit.
Release path comparison
| Path | Risk | Use for |
|---|---|---|
| Manual publish from a laptop | Personal token exposure, unrepeatable | Avoid |
| CI publish on a tag, one approver | Moderate, repeatable | Standard tier |
| CI publish on a tag with required second approval | Lower | Critical tier |
Setting up two person release
- Protect release tags so only the owning team can create them.
- Use a CI environment with required reviewers before the publish job runs.
- Require that the approver is not the person who triggered the release.
- Record the approval in the release notes or an audit log.
GitHub documents that people with admin or owner permissions can require code owner approval before merges. Use this on the branch the release is cut from, so the code itself is also reviewed by the owning team.
When a release goes wrong
You cannot edit a published version, so publish a fixed one, then mark the bad one. npm documents that its deprecate command shows a warning to anyone installing a package or version range, which is the right tool for steering consumers away. Tell consumers through the announcement route.
Check periodically
Review the list of accounts with publish rights each quarter. Remove people who changed teams. Confirm tokens are rotated and scoped.
Safeguard can help with the inventory side: its SBOM and dependency scanning shows which services pull in a given internal library, and you can run a free scan at gold.safeguard.sh/scan.
Quick check
Is two person release overkill for small libraries?
For low tier libraries one reviewer on the code plus CI publish is usually enough. Keep two person release for critical tiers.
Can the registry enforce immutability?
Many can. Check your registry settings, and if it cannot, protect against overwrites in your publish script.
Sources
Last reviewed: 19 October 2026.