SourceAnt

Supply chain naming

Anyone can publish a package called acme-auth. Your build might install it.

This is how dependency confusion works, and it ends with a stranger's code running inside your build. The names at risk are the ones written in your own manifests, and SourceAnt has already graded every one of them.

How it happens

No exploit and no clever trick. Just a name that nobody owns.

  1. 01

    They read a name

    Your internal package is called acme-auth. The name is in a lockfile in a public repository, in a stack trace, in a job log, or in a blog post one of your engineers wrote.

  2. 02

    They publish it

    Anyone can register acme-auth on the public registry. It costs nothing and takes a minute. They set the version higher than yours.

  3. 03

    Your build takes theirs

    Depending on how your installer is configured, a public package can win over the private one. Now their install script runs where your build runs, with whatever your build can reach.

The fix is well known: own the name, or pin the source it must come from. The hard part is knowing which of your names are exposed, and that list is not written down anywhere.

Why SourceAnt knows

It had to decide how far to trust the name

When SourceAnt reads a manifest and sees a dependency on a name one of your own repositories publishes, it proposes the relationship. First it asks whether the name carries its owner.

A name that carries its owner resolves to you and to nobody else, so the proposal comes back at full confidence. A bare word gets a lower grade, because the public registry can answer for that word too. The number is not a hedge. It is the shape of the exposure.

So the list you want is a filter you can already run.

the grade, as it runs
1.0

The name carries its owner. Nobody else can publish it.

0.6

A bare word. It probably resolves to you, and a stranger could take it tomorrow.

none

Two of your repositories publish the same name. That is ambiguous, so nothing is proposed rather than a coin toss.

Three of these cannot be hijacked. One can.

Most ecosystems put the owner in the name. Python does not.

Ecosystem A name of yours Who can publish it
Composer acme/auth Only you The vendor is part of the name. Nobody else can publish it.
Go github.com/acme/auth Only you The module path is a host you control.
npm @acme/auth Only you Owned when scoped. A bare name is not.
PyPI acme-auth Anyone PyPI names carry no owner. There is no scoped form to move to.

If your internal packages are Python, every one of them is in the second group. That is not a fault in the inference. It is what PyPI names are.

Then you have a list, and two ways to close it

Take the name, or stop the registry answering for it

Register it publicly so nobody else can, move the package behind a scope you own, or pin the source your installer is allowed to resolve it from.

Write down the ones you decide to live with

Record it as a constraint with your reasoning attached. The next person who finds it, or the next agent, reads the decision instead of reopening it.

Put your system on the record

Run the open core on your own infrastructure, or start on the hosted workspace. The graph is portable either way.

All use cases