Skip to content

[BUG] ComparablePackageURL omits the name, so purls differing only by name compare equal #1021

Closed

Description

@arpitjain099

Description

ComparablePackageURL in cyclonedx/_internal/compare.py builds its comparison tuple from type, namespace, version, qualifiers and subpath, but not name:

return super().__new__(cls, (
    p.type,
    p.namespace,
    p.version,
    ComparableDict(p.qualifiers) if isinstance(p.qualifiers, dict) else p.qualifiers,
    p.subpath
))

So two different packages compare equal whenever everything except the name matches:

>>> ComparablePackageURL(PackageURL(type="pypi", name="foo", version="1.0.0")) \
...     == ComparablePackageURL(PackageURL(type="pypi", name="bar", version="1.0.0"))
True

Both produce the tuple ("pypi", None, "1.0.0", (), None).

name is a required component of a purl and is the main thing that distinguishes one package from another, so leaving it out makes the comparison much weaker than intended. Anything that sorts or compares components by purl treats unrelated packages as interchangeable, and ordering between them is then decided by whatever the sort algorithm happens to do, which is not stable across inputs.

Expected

name participates in the comparison, in its canonical purl position between namespace and version.

I have a fix and a regression test ready and will open a PR referencing this issue.

Activity

  1. linked a pull request that will close this issuefix: ComparablePackageURL includes `name` #1022on Jul 31, 2026
  2. added theissue type on Jul 31, 2026
  3. changed the title [-]ComparablePackageURL omits the name, so purls differing only by name compare equal[/-] [+][BUG] ComparablePackageURL omits the name, so purls differing only by name compare equal[/+] on Jul 31, 2026
  4. jkowalleck commented on Aug 10, 2026

    @jkowalleck
    Member
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions