Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add spec for brew package URLs #281

Open
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

woodruffw
Copy link

This adds the brew purl type.

Closes #254.

Signed-off-by: William Woodruff <william@trailofbits.com>
@woodruffw woodruffw mentioned this pull request Dec 4, 2023
@woodruffw
Copy link
Author

CC @p-linnane @SMillerDev @colindean for thoughts as well 🙂

Copy link

@colindean colindean left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One major nit and a few non-blocking questions and suggestions

PURL-TYPES.rst Outdated Show resolved Hide resolved
PURL-TYPES.rst Outdated Show resolved Hide resolved
PURL-TYPES.rst Outdated Show resolved Hide resolved
- The tap syntax is ``https://github.com/{org}/Homebrew-{tap}``, so
``homebrew/core`` corresponds to the URL ``https://github.com/homebrew/homebrew-core``.
- The ``name`` is the formula name.
- The ``version`` is the formula version.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question (non-blocking): When thinking about the examples below, I think you should clarify how purl spec should handle version-in-formula formulae.

As in, if I want PostgreSQL 12.17 (current release as of this posting), should the purl be

pkg:brew/postgresql@12@12.17

or

pkg:brew/postgresql@12.17

and let whatever's reading the purl — Homebrew, ostensibly — figure out how that version maps to our major-version formulae?

I speculate only the latter is a valid purl, a safe assumption because I don't think it's a good idea to allow two @ in the purl.

Copy link
Author

@woodruffw woodruffw Dec 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for calling this out -- my read of the purl spec is that the name and other components are always URL-escaped, e.g. pkg:brew/postgresql@12@12.17 would actually be encoded as pkg:brew/postgresql%4012@12.17 in a "wire format" context. So the purl should always unambiguously map to a package, without the end client having to do additional disambiguation work.

This is a readability sacrifice, but my (potentially wrong) understanding is that purls are mostly meant to show up only in machine-readable contexts anyways.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sigh, it's not pretty, but if that's the way it needs to be, so be it. If that's the case, I'd recommend adding an example with that…

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Looks like the other examples for other ecosystem purls also contain URL-escaping examples, so we're in-line here 🙂

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pkg:brew/postgresql@12@12.17 is incorrect. The instructions for parsing a PURL (which not all implementations follow) say to split on @ from the right, so it should parse as you expect for Homebrew, but the spec says that @ must always be escaped when it's not being used as the delimiter before the version number. It'd definitely be good to have an example and maybe even call this out since it's common for people to install packages with names like this.

giterlizzi/perl-URI-PackageURL has name "postgresql" version "12" (and discards the "12.17")

maenchen/purl, sonatype/package-url-java have name "postgresql" version "12@12.17"

package-url/packageurl-js throws an error (I thought I saw a fix for this, but maybe the PR hasn't merged)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I added @colindean's example below. Adding an explicit callout also makes sense to me; I'll add some language for that.

PURL-TYPES.rst Outdated Show resolved Hide resolved
PURL-TYPES.rst Outdated
Comment on lines 100 to 101
- Qualifier ``tap_url``: for taps that are not on GitHub or otherwise require an explicit URL,
this is the full URL to the tap.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question (non-blocking): Should there be another parameter to name the tap? We use the named tap at work, e.g.

brew tap myco/brewhouse git@git.myco.com:brew/house.git

and the formula, uh, myco-ctl could have a purl

pkg:brew/myco/brewhouse/myco-ctl?tap_url=git@git.myco.com:brew/house.git

and brew would know how to name the tap if it needed to be tapped, or perhaps

pkg:brew/myco/brewhouse/myco-ctl?tap_url=git@git.myco.com:brew/house.git&tap_name=myco/brewhouse

or more simply

pkg:brew/myco-ctl?tap_url=git@git.myco.com:brew/house.git&tap_name=myco/brewhouse

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My 0.02c would be for your first form:

pkg:brew/myco/brewhouse/myco-ctl?tap_url=git@git.myco.com:brew/house.git

I think that's unambiguous: the github.com/{org}/homebrew-{tap} logic only applies when a tap_url isn't present, so I think this is the shortest form that conveys all needed information. But maybe I've overlooked something?

PURL-TYPES.rst Outdated Show resolved Hide resolved
woodruffw and others added 3 commits December 8, 2023 16:32
Co-authored-by: Colin Dean <colindean@users.noreply.github.com>
Co-authored-by: Colin Dean <colindean@users.noreply.github.com>
Signed-off-by: William Woodruff <william@trailofbits.com>
- The tap syntax is ``https://github.com/{org}/Homebrew-{tap}``, so
``homebrew/core`` corresponds to the URL ``https://github.com/homebrew/homebrew-core``.
- The ``name`` is the formula name.
- The ``version`` is the formula version.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sigh, it's not pretty, but if that's the way it needs to be, so be it. If that's the case, I'd recommend adding an example with that…

PURL-TYPES.rst Show resolved Hide resolved
woodruffw and others added 2 commits December 8, 2023 16:44
Co-authored-by: Colin Dean <colindean@users.noreply.github.com>
Signed-off-by: William Woodruff <william@trailofbits.com>
@pombredanne
Copy link
Member

@MikeMcQuaid 👋 A quick review or ack from you would awesome!

@pombredanne
Copy link
Member

Thanks!
LGTM overall, though the double @ in postgres@16@16.1 name seems a bit weird. Is it possible to run brew install postgres@16@16.1 or instead brew install postgres@16.1 or instead brew install postgres%4016@16.1

@matt-phylum
Copy link
Contributor

According to Stack Overflow, you cannot install a specific version. pkg:brew/postgresql%4016@16.1 means version 16.1 of Postgres from the postgresql@16 package, which is useful for answering "what's installed?", but apparently not useful for trying to install the same package. The repository apparently doesn't keep old versions: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/p/postgresql@16.rb

@woodruffw
Copy link
Author

LGTM overall, though the double @ in postgres@16@16.1 name seems a bit weird. Is it possible to run brew install postgres@16@16.1 or instead brew install postgres@16.1 or instead brew install postgres%4016@16.1

Both brew install postgres and brew install postgres@16 are supported, but the others aren't. Homebrew doesn't really support multiple versions of the same package (per what @matt-phylum said) -- the @X syntax is a hack that Homebrew does to allow multiple versions of the same package to exist in a tap when the ecosystem can't all exist on a single version (e.g. OpenSSL, Python, etc.).

TL;DR yes, there is no way to install a specific minor version, e.g. postgres 16.1. postgres@16 is the full name of a formula, referring specifically to whatever latest version of postgres 16 is packaged by Homebrew.

Link for reference: https://github.com/Homebrew/homebrew-core/blob/master/Formula/p/postgresql%4016.rb

Copy link

@MikeMcQuaid MikeMcQuaid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

@woodruffw
Copy link
Author

Gentle ping for review+approval here: this is no longer a blocker in Homebrew's attestation work, but I'd like to get it in so that we can consider it for any future attestation changes, if necessary 🙂

@woodruffw
Copy link
Author

Another gentle ping for review here!

Copy link
Contributor

@captn3m0 captn3m0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for merging this.

@matt-phylum
Copy link
Contributor

I think it's important for this PR to add entries to the test suite. Package names can contain the @ character and this is not handled correctly by maennchen/purl (maennchen/purl#10) or anchore/packageurl-go (does not accept bug reports). Both fail to handle pkg:brew/postgres%4016.

There's also a common misimplementation of the parsing spec which can cause problems here. The spec says "Split the remainder once from the right on '@'. The left side is the remainder. Percent-decode the right side. This is the version." However, some implementations split once from the left on '@'. If somebody writes pkg:brew/postgres@16@16.1 (non-canonical. the test should ensure the correct canonicalization):

  • anchore/packageurl-go, maennchen/purl, sonatype/package-url-java parse it as postgres version 16@16.1 (split from the left instead of the right)
  • giterlizzi/perl-URI-PackageURL parse it as version 16 (somehow discarding the 16.1)
  • package-url/packageurl-js throws an exception (Incorrect validation of version encoding packageurl-js#57)
{
  "description": "brew names may contain at signs",
  "purl": "pkg:brew/postgres%4016",
  "canonical_purl": "pkg:brew/postgres%4016",
  "type": "brew",
  "namespace": null,
  "name": "postgres@16",
  "version": null,
  "qualifiers": null,
  "subpath": null,
  "is_invalid": false
},
{
  "description": "brew may contain multiple at signs",
  "purl": "pkg:brew/postgres@16@16.1",
  "canonical_purl": "pkg:brew/postgres%4016@16.1",
  "type": "brew",
  "namespace": null,
  "name": "postgres@16",
  "version": "16.1",
  "qualifiers": null,
  "subpath": null,
  "is_invalid": false
}

@woodruffw
Copy link
Author

woodruffw commented Jun 17, 2024

Makes sense, although the ship has since sailed on the main backing feature that I needed this for (Homebrew's build provenance feature, which instead uses Homebrew's own wheel filename format for its subject).

As such, I don't have any time allocated for this in the immediate future. I'll try and get back to it when I do have some slack time, but if it's a pressing feature for anyone in the next 1-3 months I have no objection to someone else taking ownership here.

Edit: @colindean has graciously done this 🙂

@colindean
Copy link

💪 I like this test case setup.

Copy link

@colindean colindean left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@woodruffw I got one wrong upon reviewing the unresolved comments. Please merge this suggestion.

@matt-phylum I think the rest of the comments can be resolved.

test-suite-data.json Outdated Show resolved Hide resolved
Co-authored-by: Colin Dean <colindean@users.noreply.github.com>
@tonylturner
Copy link

Is there an update on this issue? I came here to submit a similar issue and was glad to see this but it's been open for 9 months now. Any ETA on review?

@woodruffw
Copy link
Author

From the perspective of the Homebrew upstream, this has been done and is ready for final review/merge since June. It'd be nice to have a repository owner to shepherd this, although I'm not exactly sure who that'd be (@pombredanne perhaps? 🙂)

Copy link
Member

@jkowalleck jkowalleck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please also remove brew from the list "Other candidate types to define"

Signed-off-by: William Woodruff <william@trailofbits.com>
@woodruffw
Copy link
Author

please also remove bre from the list "Other candidate types to define"

Done with f8fd63e; PTAL.

@johnmhoran
Copy link
Member

Thank you for your PR @woodruffw. When you have the chance, could you please resolve the conflicts referred to below?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Proposed new type PURL type definition Non-core definitions that describe and standardize PURL types type: brew Proposed new type
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Proposal: brew type