skip to content

How would you audit who still holds publish rights across your organization's public packages?

level: seniorimportance: should knowfreq 44%

answer

  1. nothing expires on its own
  2. the inventory is built, not queried
  3. people and machines are separate lists
  4. removing a user leaves the token
  5. who could have published this version

basics

~20 s

Build an inventory of every namespace you publish to, list the humans and the machine credentials that can publish to each, then revoke on current need rather than past contribution. Nothing expires on its own.

solid answer

~50 s

Start with the inventory, because no single system holds it: each ecosystem has its own owner model, so reconcile what your repositories publish, what each registry says your organization and your people own, and what your builds resolve internally. For each namespace, enumerate two separate lists - humans with owner or publish rights, and machine credentials such as publishing tokens. The subtlety people miss is that removing a person does not invalidate a token they created: on several registries it keeps working, so tokens are rotated as their own step. Then cut: a right granted five years ago for one merged pull request goes by default, because the bar is a current need rather than a past contribution. Finally make it recurring, narrow the default set of publishing identities, and keep a dated record so you can later answer who could have published a given version.

go deeper

for a junior

Know that the right to publish a package is granted per package and never expires, and that leaving a company does not automatically remove it. Being able to say where you would look is enough at this level.

for a middle

Explain why the list is hard to assemble: each ecosystem records ownership differently, and machine credentials are stored apart from the human owner list. Describe how you would enumerate both for a single package.

for a senior

Show the method and the trap. Build the inventory, enumerate humans and tokens separately, revoke on current need rather than past contribution, and rotate credentials explicitly because they survive their creator's removal. Give the review a cadence.

for a principal

Own the policy: who is accountable for each published namespace, what the default publishing identity is across the estate, and how you get hundreds of packages reviewed without stalling delivery or relying on a heroic annual spreadsheet.

Publish rights are the most quietly accumulating privilege in an engineering organization. Nothing expires. A co-maintainer added five years ago for one merged pull request still holds the right to push a version of a package your build installs, and no system will ever bring it to your attention. An audit is the only thing that finds it. ## Step 1 - the inventory is the hard part There is no single place that lists "everything we publish". Each ecosystem carries its own owner model and they do not agree with each other: a scope with organization roles on npm, per-project owner and maintainer roles on PyPI, a Maven Central namespace tied to an account and a verified domain, crate owners including team owners on crates.io. Nothing joins them. So the inventory is built, not queried. Start from three sources and reconcile them: - what your repositories publish, since release configuration names the destination; - what each registry says your organization *and your individual people* own, including personal accounts of current employees; - what your own builds resolve internally, which surfaces names nobody remembers owning. The output is a list of namespaces with a named human accountable for each. Half the value of the exercise is discovering the packages that appear on nobody's list. ## Step 2 - enumerate principals, not just people For each namespace, two lists matter, and registries store them separately: - **humans** with owner or publish rights; - **machine credentials** - publishing tokens, automation accounts, release identities. The critical subtlety: **removing a person does not invalidate a token they created.** On several registries a publishing token is an independent credential that keeps working after its creator has been removed from the package or has left. An offboarding process that deletes accounts and calls it finished can leave live publishing credentials behind. Tokens have to be enumerated and rotated deliberately, as their own step. ## Step 3 - join against reality and cut For every human, ask two questions: is this person still here, and do they still need this? The second one is the question people skip. Rights granted for a reason that has ended - a migration, a single fix, a team you have left - should go by default. The bar for keeping a right is a current need, not a past contribution. In an open-source project the same rule applies with more courtesy: notify the dormant maintainer, offer triage or review access instead, and remove the publish right anyway. Publishing rights are not a thank-you note. For machine credentials, ask what each one can reach. A token that can publish every package in a scope should be replaced by one scoped to a single package, and better still by a short-lived credential issued to a specific release job instead of a long-lived secret sitting in a settings page. ## Step 4 - make the result durable A one-off audit decays back to where it started within a year. Three things keep it alive: - **a cadence** - annually at minimum, and always on a departure or a team change; - **a narrow default** - the smallest set of identities that can publish, so that "who could have published this version" has a short answer; - **a dated record** of what the rights were and what you revoked, which is what lets you answer a question about a release from six months ago. ## What this is really protecting The asset here is not customer data; it is **the answer to "was this release legitimate?"**. Every extra dormant principal widens the set of accounts an attacker can compromise in order to publish under your name, and at the same time destroys your ability to attribute a release when something goes wrong. A shared account is the extreme case: it makes every publish unattributable by construction, so the investigation starts with nothing. ## The senior signal Interviewers listen for three things here: that you build an inventory rather than assume one exists, that you know credentials survive the removal of their owner, and that you treat the review as recurring with a narrow default rather than as a one-time cleanup. A candidate who answers "offboarding removes their access" has described a process that misses the two cases that matter most - the dormant external co-maintainer, and the token.

  • You find a co-maintainer who has not published in five years. Remove, or ask first?
    Remove by default, and tell them you did. Publishing rights are not a reward for a past contribution, and a dormant account is an unmonitored path into the namespace. On an open-source project, notify them first as a courtesy and offer triage or review access instead, but do not let the courtesy hold the publish right open indefinitely.
  • After the audit, how do you make "who published version 3.2.1" reliably answerable?
    Narrow the set of identities that can publish, ideally to one automated release path per package, so the candidate list is short. Keep the registry's publish records and correlate them with your build records. A shared account defeats this by construction: every release is attributable only to the team, which is the same as nobody.
  • What makes this genuinely hard across four different registries?
    There is no common vocabulary or API for ownership. Roles differ, some registries have no per-package roles at all, and machine credentials are listed somewhere else again. That means the inventory has to be deliberately maintained as its own artifact rather than derived on demand, and it decays unless the review has a cadence.

saying these in an interview costs you the question

  • Assumes HR offboarding removes registry publish rights
  • Says an unexpected publish would obviously be noticed
  • Believes tokens die when their creator is removed
  • Keeps dormant maintainers because they contributed once
  • Audits humans only and never enumerates machine credentials

context