Watch
1
0
Fork
You've already forked pkg-proxy
1
mirror of https://github.com/git-pkgs/proxy.git synced 2026-11-09 07:39:19 -05:00
pkg-proxy/internal/packageurl/handler.go
Simon Chrzanowski a288afab32 Match denylist entries for distro packages as handlers name them
The denylist kept the PURL namespace, but the Debian and RPM handlers
build pkg:deb/{name} and pkg:rpm/{name} without a vendor, while Alpine
and Arch build pkg:apk/alpine/{name} and pkg:alpm/arch/{name} with one.
So standard entries such as pkg:deb/debian/curl@... or
pkg:rpm/fedora/curl@..., and pkg:apk/busybox@... or pkg:alpm/glibc@...,
never matched. Drop the namespace of distro types on both sides, as
retention and the inventory already do, using packageurl's list of
those types.

Debian and RPM handlers read versions from filenames, which leave out
the epoch, so an entry such as pkg:deb/foo@1:2.3-1 never matched
foo_2.3-1_amd64.deb. An entry with an epoch now also covers the
version without it.
2026-11-08 08:04:09 +01:00

70 lines
2.5 KiB
Go

package packageurl
import (
"github.com/git-pkgs/purl"
)
// distroTypes are PURL types whose namespace names the distribution
// ("alpine", "debian"), not part of the package name the handlers store.
var distroTypes = map[string]bool{"alpm": true, "apk": true, "bsd": true, "deb": true, "rpm": true}
// DistroType reports whether a PURL type's namespace names the distribution,
// so that handlers ignore it.
func DistroType(purlType string) bool {
return distroTypes[purlType]
}
// HandlerEcosystem returns the ecosystem name the proxy's handlers store
// packages of a PURL type under. purl names gem and composer after their
// registries, rubygems and packagist; the handlers use the type.
func HandlerEcosystem(purlType string) string {
switch purlType {
case "gem", "composer":
return purlType
default:
return purl.PURLTypeToEcosystem(purlType)
}
}
// HandlerPackage returns the ecosystem and package name the proxy's handlers
// store p under, so a package named in a PURL, such as one from an SBOM,
// matches the package a client fetched through the proxy:
//
// - apk, alpm, bsd, deb and rpm: the namespace names the distribution and
// is dropped
// - conda: the channel, from the namespace or the channel qualifier, is
// part of the name ("conda-forge/numpy"); without either the name stays
// bare
// - pypi and nuget: the name in purl's comparison form, PEP 503 for PyPI
// and lowercased for NuGet, as the handlers store them
// - swift: namespace/name, the registry scope or the source repository
// with the package, which the Swift mirror resolves; purl's full name
// is the registry identity scope.name
//
// Other types use purl's full name, which keeps the namespace: "@babel/core",
// or "org.slf4j:slf4j-api" for Maven, as its handler stores it.
func HandlerPackage(p *purl.PURL) (ecosystem, name string) {
ecosystem = HandlerEcosystem(p.Type)
switch {
case distroTypes[p.Type]:
return ecosystem, p.Name
case p.Type == "conda":
return ecosystem, condaName(p.Namespace, p.Name, p.Qualifier("channel"))
case p.Type == "pypi" || p.Type == "nuget":
return ecosystem, p.ComparisonForm().FullName()
case p.Type == "swift" && p.Namespace != "":
return ecosystem, p.Namespace + "/" + p.Name
}
return ecosystem, p.FullName()
}
func condaName(namespace, name, channel string) string {
switch {
case namespace != "":
return namespace + "/" + name
case channel != "":
return channel + "/" + name
default:
return name
}
}