List internal packages like any other component: a name, an exact version, a supplier of your own organisation, and a package URL that points to your private repository through a qualifier. Do not hide them, and do not let a vulnerability matcher confuse them with a public package that shares the name.
Why internal packages cause trouble
Most SBOM tooling assumes every component can be found in a public registry. Internal packages break that assumption in two ways.
- They may be unknown to the tool. With no public record, a scanner may skip them or list them with empty fields.
- They may collide with a public name. If your internal package is called "billing-utils" and a public package has the same name, a matcher can attach the public package's advisories to your code. That produces false alarms, or worse, a false sense that a name has been checked.
The second point is also a security issue. Substituting a public package for an internal name is a known attack pattern, so an SBOM that is clear about where each package comes from helps reviewers spot it.
Use the identifier to say where it came from
The Package URL specification defines seven parts: scheme, type, namespace, name, version, qualifiers and subpath. Qualifiers carry extra data such as the operating system, architecture or repository. Namespaces are type specific, for example a Maven group id.
For an internal package, aim for these properties:
| Field | What to put | Why |
|---|---|---|
| Name | Your real package name | Humans can find it |
| Version | The exact released version | Needed to reason about fixes |
| Namespace | Your organisation or group id | Reduces collision with public names |
| Qualifier | The private repository location, where the type allows it | Shows it did not come from the public index |
| Supplier | Your organisation | Marks it as first party |
| Hash | A digest of the artifact | Lets a reader verify it |
Not every package type defines a repository qualifier, so check what the specification says for your type rather than assuming.
A checklist for your own tooling
- Inventory your private registries and list which package types they host.
- Generate an SBOM and filter for components whose source is a private registry.
- Confirm each one has a version, a supplier and an identifier that cannot be read as a public package.
- Check that no advisory has been attached to an internal component by name alone.
- Check that your build is configured so that internal names resolve to the private registry first, or only there.
Should you share internal component names?
Sometimes an internal name reveals more than you want to disclose, such as a project code name. If you share an SBOM externally, decide in advance whether to keep real names, use stable aliases, or group internal code under one parent component. Whatever you choose, say so in the document or a cover note so the reader does not mistake the omission for an error.
Where Safeguard fits
Safeguard's dependency scanning and SBOM views separate first party and third party components so internal packages are not lost in the list. Try the free scan at gold.safeguard.sh/scan on a repository that uses a private registry to see how your internal packages appear.
Quick check
Should internal packages be in a customer SBOM?
Usually yes, at least as first party components. If names are sensitive, agree an aliasing approach and document it.
What is the main risk with internal package names?
A matcher or a build resolving the name against a public registry, which can attach the wrong advisories or pull the wrong code.
Sources
Last reviewed: 19 October 2026.