Homebrew / brew

🍺 The missing package manager for macOS (or Linux)
https://brew.sh
BSD 2-Clause "Simplified" License
40.99k stars 9.62k forks source link

SBOMs break bottle reproducibility #17281

Closed carlocab closed 4 months ago

carlocab commented 4 months ago

brew doctor output

❯ brew dr
Your system is ready to brew.

Verification

brew config output

❯ brew config
HOMEBREW_VERSION: 4.2.21-109-g71c4bfa
ORIGIN: https://github.com/Homebrew/brew
HEAD: 71c4bfae79852b28d299de51a3007149bfe44073
Last commit: 4 hours ago
Core tap HEAD: 70912b0a1127e1b4fb3f50298b6f843b495a19fb
Core tap last commit: 18 minutes ago
Core tap JSON: 10 May 16:11 UTC
Core cask tap HEAD: 5be9a58d025d2db4fe8dd96089c9bd65600cba24
Core cask tap last commit: 34 minutes ago
Core cask tap JSON: 10 May 16:11 UTC
HOMEBREW_PREFIX: /opt/homebrew
HOMEBREW_BAT: set
HOMEBREW_BOOTSNAP: set
HOMEBREW_CASK_OPTS: []
HOMEBREW_COLOR: set
HOMEBREW_DEVELOPER: set
HOMEBREW_EDITOR: nvim
HOMEBREW_FORCE_BREWED_CURL: set
HOMEBREW_FORCE_BREWED_GIT: set
HOMEBREW_GIT_EMAIL: 30379873+carlocab@users.noreply.github.com
HOMEBREW_GIT_NAME: Carlo Cabrera
HOMEBREW_MAKE_JOBS: 16
HOMEBREW_NO_AUTO_UPDATE: set
HOMEBREW_NO_CLEANUP_FORMULAE: zsh
HOMEBREW_NO_INSTALL_FROM_API: set
HOMEBREW_PRY: set
HOMEBREW_SORBET_RUNTIME: set
Homebrew Ruby: 3.1.4 => /opt/homebrew/Library/Homebrew/vendor/portable-ruby/3.1.4/bin/ruby
CPU: 16-core 64-bit arm_palma
Clang: 15.0.0 build 1500
Git: 2.45.0 => /opt/homebrew/opt/git/bin/git
Curl: 8.7.1 => /opt/homebrew/opt/curl/bin/curl
macOS: 14.4.1-arm64
CLT: 15.3.0.0.1.1708646388
Xcode: 15.3
Rosetta 2: false

What were you trying to do (and why)?

Figure out why we don't have an :all bottle at https://github.com/Homebrew/homebrew-core/commit/0894397822dcdba3facaf90055f450b2dc741647 (because :all bottles are nice).

To examine the differences between the bottles, I used diffoscope.

What happened (include all command output)?

diffoscope showed that the bottles have differing sbom.spdx.json files.

diffoscope output ```diff --- bottles_ubuntu-22.04/osinfo-db--20240510.x86_64_linux.bottle.tar.gz +++ bottles_14-arm64-9046359873/osinfo-db--20240510.arm64_sonoma.bottle.tar.gz │ --- osinfo-db--20240510.x86_64_linux.bottle.tar ├── +++ osinfo-db--20240510.arm64_sonoma.bottle.tar │ ├── file list │ │ @@ -1,12 +1,12 @@ │ │ drwxr-xr-x 0 0 0 0 2024-05-10 10:31:02.000000 osinfo-db/20240510/ │ │ drwxr-xr-x 0 0 0 0 2024-05-10 10:31:02.000000 osinfo-db/20240510/.brew/ │ │ -rw-r--r-- 0 0 0 667 2024-05-10 10:31:02.000000 osinfo-db/20240510/.brew/osinfo-db.rb │ │ -rw-r--r-- 0 0 0 17987 2024-05-10 10:31:02.000000 osinfo-db/20240510/LICENSE │ │ --rw-r--r-- 0 0 0 2727 2024-05-10 10:31:02.000000 osinfo-db/20240510/sbom.spdx.json │ │ +-rw-r--r-- 0 0 0 2719 2024-05-10 10:31:02.000000 osinfo-db/20240510/sbom.spdx.json │ │ drwxr-xr-x 0 0 0 0 2024-05-10 10:31:02.000000 osinfo-db/20240510/share/ │ │ drwxr-xr-x 0 0 0 0 2024-05-10 10:31:02.000000 osinfo-db/20240510/share/osinfo/ │ │ -rw-r--r-- 0 0 0 17987 2024-05-10 10:31:02.000000 osinfo-db/20240510/share/osinfo/LICENSE │ │ -rw-r--r-- 0 0 0 8 2024-05-10 10:31:02.000000 osinfo-db/20240510/share/osinfo/VERSION │ │ drwxr-xr-x 0 0 0 0 2024-05-10 10:31:02.000000 osinfo-db/20240510/share/osinfo/datamap/ │ │ drwxr-xr-x 0 0 0 0 2024-05-10 10:31:02.000000 osinfo-db/20240510/share/osinfo/datamap/microsoft.com/ │ │ -rw-r--r-- 0 0 0 1691 2024-05-10 10:31:02.000000 osinfo-db/20240510/share/osinfo/datamap/microsoft.com/win-7-l10n-language.xml │ ├── osinfo-db/20240510/sbom.spdx.json │ │ ├── Pretty-printed │ │ │ @@ -1,11 +1,11 @@ │ │ │ { │ │ │ "SPDXID": "SPDXRef-DOCUMENT", │ │ │ "creationInfo": { │ │ │ - "created": "2024-05-11T20:59:00+00:00", │ │ │ + "created": "2024-05-11T17:00:13-04:00", │ │ │ "creators": [ │ │ │ "Tool: https://github.com/homebrew/brew@4.2.21-109-g71c4bfa" │ │ │ ] │ │ │ }, │ │ │ "dataLicense": "CC0-1.0", │ │ │ "documentDescribes": [ │ │ │ "SPDXRef-Archive-osinfo-db-src", │ │ │ @@ -14,15 +14,15 @@ │ │ │ ], │ │ │ "documentNamespace": "https://formulae.brew.sh/spdx/osinfo-db-20240510.json", │ │ │ "files": [], │ │ │ "name": "SBOM-SPDX-osinfo-db-20240510", │ │ │ "packages": [ │ │ │ { │ │ │ "SPDXID": "SPDXRef-Archive-osinfo-db-src", │ │ │ - "builtDate": "2024-05-10 10:31:02 +0000", │ │ │ + "builtDate": "2024-05-10 06:31:02 -0400", │ │ │ "checksums": [ │ │ │ { │ │ │ "algorithm": "SHA256", │ │ │ "checksumValue": "08a2d521c485687f6be39940d5b3f61bc0f583bb7e3655a131c658385eb7e5ca" │ │ │ } │ │ │ ], │ │ │ "copyrightText": "NOASSERTION", │ │ │ @@ -39,20 +39,20 @@ │ │ │ "checksums": [], │ │ │ "copyrightText": "NOASSERTION", │ │ │ "downloadLocation": "NOASSERTION", │ │ │ "externalRefs": [], │ │ │ "filesAnalyzed": false, │ │ │ "licenseConcluded": "NOASSERTION", │ │ │ "licenseDeclared": "NOASSERTION", │ │ │ - "name": "gcc-11", │ │ │ - "versionInfo": "NOASSERTION" │ │ │ + "name": "clang", │ │ │ + "versionInfo": "15.3" │ │ │ }, │ │ │ { │ │ │ "SPDXID": "SPDXRef-Bottle-osinfo-db", │ │ │ - "builtDate": "2024-05-10 10:31:02 +0000", │ │ │ + "builtDate": "2024-05-10 06:31:02 -0400", │ │ │ "checksums": [ │ │ │ { │ │ │ "algorithm": "SHA256", │ │ │ "checksumValue": "a8c86aee5fd157554d85aa0a28d4c12bc5bdf03ccb5e67ac5c8c524d78bd1971" │ │ │ } │ │ │ ], │ │ │ "copyrightText": "NOASSERTION", ```

What did you expect to happen?

These bottles are identical, so they should not have different contents.

Step-by-step reproduction instructions (by running brew commands)

gh run download 9046359873 -p 'bottles*' -R Homebrew/homebrew-core
diffoscope bottles_ubuntu-22.04/osinfo-db--20240510.x86_64_linux.bottle.tar.gz bottles_14-arm64-9046359873/osinfo-db--20240510.arm64_sonoma.bottle.tar.gz
carlocab commented 4 months ago

CC @SMillerDev

SMillerDev commented 4 months ago

I'll have to find where this is ignored for tabs since we can't really make sure it's the same. I can probably fix the build date though

carlocab commented 4 months ago

I'll have to find where this is ignored for tabs since we can't really make sure it's the same.

Yup, they will indeed be different. It isn't ignored for tabs -- they're just not stored in the bottle, so they don't affect the bottle checksum.

Bo98 commented 4 months ago

Yes, for tabs we don't store this stuff in the bottles - we store them in GitHub Packages manifest annotations instead.

MikeMcQuaid commented 4 months ago

Yes, for tabs we don't store this stuff in the bottles - we store them in GitHub Packages manifest annotations instead.

We should do the same thing for SBOMs dates/times as we do for Tab runtime dependencies: update them after installation (based on the dates/times from the tab): https://github.com/Homebrew/brew/blob/1e4d119f6bf08b782d5f5cea5feedee556258e99/Library/Homebrew/formula_installer.rb#L825-L830

SMillerDev commented 4 months ago

Not sure how to resolve this. We could not write the field if the compiler is the system one maybe? Or, which affects the usefulness iyam, we could drop the bottle inclusion of the file and only write it on install.

MikeMcQuaid commented 4 months ago

I think in an ideal world we'd detect if the compiler was actually used somehow e.g. write a temporary file on first usage of one of the compiler shims.

In cases like this, it's pretty clear that the compiler isn't actually used or a dependency.

Bo98 commented 4 months ago

If compiler information needs to be available in the bottle archive via brew fetch (though this archive isn't necessarily representative of a complete install as it's pre-relocation): avoiding system compiler makes sense

If compiler information only needs to be available in the Cellar after brew install: SBOM already fetches the compiler from the tab, so we can exclude it and attach it back again on install.

MikeMcQuaid commented 4 months ago

If compiler information only needs to be available in the Cellar after brew install: SBOM already fetches the compiler from the tab, so we can exclude it and attach it back again on install.

Yes, this seems best for now.

carlocab commented 4 months ago

If compiler information only needs to be available in the Cellar after brew install: SBOM already fetches the compiler from the tab, so we can exclude it and attach it back again on install.

Yes, this seems best for now.

This is fine, but it might not be enough. The sbom.spdx.json files also reference bottle checksum of dependencies, which in general be different across OS versions even for existing :all bottles. Unless this information is generated during brew fetch?

carlocab commented 4 months ago

Confusingly, the SBOM also seems to contain this snippet:

    {
      "SPDXID": "SPDXRef-Bottle-node@20",
      "name": "node@20",
      "versionInfo": "20.13.1",
      "filesAnalyzed": false,
      "licenseDeclared": "NOASSERTION",
      "builtDate": "2024-05-09 05:20:38 -0400",
      "licenseConcluded": "MIT",
      "downloadLocation": "https://ghcr.io/v2/homebrew/core/node/20/blobs/sha256:a865d16c32d50cdffe26e341fb6a8d52b7c3f95daf10e2a390fb988c4fba0ab3",
      "copyrightText": "NOASSERTION",
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE-MANAGER",
          "referenceLocator": "pkg:brew/homebrew/core/node@20@20.13.1",
          "referenceType": "purl"
        }
      ],
      "checksums": [
        {
          "algorithm": "SHA256",
          "checksumValue": "a865d16c32d50cdffe26e341fb6a8d52b7c3f95daf10e2a390fb988c4fba0ab3"
        }
      ]
    }

Except that the download location (and checksum) is not for the version indicated (20.13.1). Instead, it points to the location and checksum of 20.13.0. Which kinda makes sense, because you can't really write a file containing the checksum of the bottle inside the bottle. (Or I could just be very confused about what's going on here, which is also a possibility.)

MikeMcQuaid commented 4 months ago

Except that the download location (and checksum) is not for the version indicated (20.13.1). Instead, it points to the location and checksum of 20.13.0. Which kinda makes sense, because you can't really write a file containing the checksum of the bottle inside the bottle. (Or I could just be very confused about what's going on here, which is also a possibility.)

This also should be removed at bottling time and restored at install time.

MikeMcQuaid commented 4 months ago

Confirmed rebottling in https://github.com/Homebrew/homebrew-core/pull/171540 post https://github.com/Homebrew/brew/pull/17284 fixes the bottles 🎉

carlocab commented 4 months ago

Thanks @MikeMcQuaid :heart:

carlocab commented 4 months ago

This is still happening. See https://github.com/Homebrew/homebrew-core/commit/fd1c80d8a7955be8aa8d787a045efb3ec9eaa076.

Diffoscope Output ``` --- ~/Library/Caches/Homebrew/downloads/10141ca57ddfafa18b2a0efeaac4f8206739805a36d435c886951987fb4ccaa8--ruby-build--20240517.arm64_ventura.bottle.tar.gz +++ ~/Library/Caches/Homebrew/downloads/aa750a673b84ed5679172e6c6b4a944dce68ee6f7dc6e1b310c5d63c4df83e0a--ruby-build--20240517.arm64_sonoma.bottle.tar.gz │ --- 10141ca57ddfafa18b2a0efeaac4f8206739805a36d435c886951987fb4ccaa8--ruby-build--20240517.arm64_ventura.bottle.tar ├── +++ aa750a673b84ed5679172e6c6b4a944dce68ee6f7dc6e1b310c5d63c4df83e0a--ruby-build--20240517.arm64_sonoma.bottle.tar │ ├── ruby-build/20240517/sbom.spdx.json │ │ ├── Pretty-printed │ │ │ @@ -40,19 +40,19 @@ │ │ │ "versionInfo": "20240517" │ │ │ }, │ │ │ { │ │ │ "SPDXID": "SPDXRef-Package-SPDXRef-m4-1.4.19", │ │ │ "checksums": [ │ │ │ { │ │ │ "algorithm": "SHA256", │ │ │ - "checksumValue": "11308abe8d607be35da9e88a1d789f191914bf043bca4fdde2b50a6cbf1713cc" │ │ │ + "checksumValue": "f42d89db519a07d67bcaead6c8dfb2da45e8266bebb996dd8b3f19b1ca13b8a0" │ │ │ } │ │ │ ], │ │ │ "copyrightText": "NOASSERTION", │ │ │ - "downloadLocation": "https://ghcr.io/v2/homebrew/core/m4/blobs/sha256:11308abe8d607be35da9e88a1d789f191914bf043bca4fdde2b50a6cbf1713cc", │ │ │ + "downloadLocation": "https://ghcr.io/v2/homebrew/core/m4/blobs/sha256:f42d89db519a07d67bcaead6c8dfb2da45e8266bebb996dd8b3f19b1ca13b8a0", │ │ │ "externalRefs": [ │ │ │ { │ │ │ "referenceCategory": "PACKAGE-MANAGER", │ │ │ "referenceLocator": "pkg:brew/m4@1.4.19", │ │ │ "referenceType": "purl" │ │ │ } │ │ │ ], │ │ │ @@ -86,19 +86,19 @@ │ │ │ "versionInfo": "2.72" │ │ │ }, │ │ │ { │ │ │ "SPDXID": "SPDXRef-Package-SPDXRef-libyaml-0.2.5", │ │ │ "checksums": [ │ │ │ { │ │ │ "algorithm": "SHA256", │ │ │ - "checksumValue": "11239e8f5066c6d0d0718208d4eab518da00c7289f33c9c76c0a09ba5c0417c9" │ │ │ + "checksumValue": "98c0cf81bcdf7577d5fdc8cc18732970b9ae7e0e7423a733f88f0f566ba483ad" │ │ │ } │ │ │ ], │ │ │ "copyrightText": "NOASSERTION", │ │ │ - "downloadLocation": "https://ghcr.io/v2/homebrew/core/libyaml/blobs/sha256:11239e8f5066c6d0d0718208d4eab518da00c7289f33c9c76c0a09ba5c0417c9", │ │ │ + "downloadLocation": "https://ghcr.io/v2/homebrew/core/libyaml/blobs/sha256:98c0cf81bcdf7577d5fdc8cc18732970b9ae7e0e7423a733f88f0f566ba483ad", │ │ │ "externalRefs": [ │ │ │ { │ │ │ "referenceCategory": "PACKAGE-MANAGER", │ │ │ "referenceLocator": "pkg:brew/libyaml@0.2.5", │ │ │ "referenceType": "purl" │ │ │ } │ │ │ ], │ │ │ @@ -109,19 +109,19 @@ │ │ │ "versionInfo": "0.2.5" │ │ │ }, │ │ │ { │ │ │ "SPDXID": "SPDXRef-Package-SPDXRef-pkg-config-0.29.2_3", │ │ │ "checksums": [ │ │ │ { │ │ │ "algorithm": "SHA256", │ │ │ - "checksumValue": "3ff612c5e44b945c8c0cc6df7d3edb407ca67cddad9c89f9ab99ced494b7a8c2" │ │ │ + "checksumValue": "7b59abc0b5381065b1eab174217307af9324e0d02edf903171b29250ae58aeaf" │ │ │ } │ │ │ ], │ │ │ "copyrightText": "NOASSERTION", │ │ │ - "downloadLocation": "https://ghcr.io/v2/homebrew/core/pkg-config/blobs/sha256:3ff612c5e44b945c8c0cc6df7d3edb407ca67cddad9c89f9ab99ced494b7a8c2", │ │ │ + "downloadLocation": "https://ghcr.io/v2/homebrew/core/pkg-config/blobs/sha256:7b59abc0b5381065b1eab174217307af9324e0d02edf903171b29250ae58aeaf", │ │ │ "externalRefs": [ │ │ │ { │ │ │ "referenceCategory": "PACKAGE-MANAGER", │ │ │ "referenceLocator": "pkg:brew/pkg-config@0.29.2_3", │ │ │ "referenceType": "purl" │ │ │ } │ │ │ ], │ │ │ @@ -132,19 +132,19 @@ │ │ │ "versionInfo": "0.29.2_3" │ │ │ }, │ │ │ { │ │ │ "SPDXID": "SPDXRef-Package-SPDXRef-readline-8.2.10", │ │ │ "checksums": [ │ │ │ { │ │ │ "algorithm": "SHA256", │ │ │ - "checksumValue": "90351660d5ceca72a4c0a287555f2045db95f78aa5f65011b94213429f729cde" │ │ │ + "checksumValue": "713fd1fa8544426b7e97eb21d13153195fea4c407db8a174bd183777b81c9192" │ │ │ } │ │ │ ], │ │ │ "copyrightText": "NOASSERTION", │ │ │ - "downloadLocation": "https://ghcr.io/v2/homebrew/core/readline/blobs/sha256:90351660d5ceca72a4c0a287555f2045db95f78aa5f65011b94213429f729cde", │ │ │ + "downloadLocation": "https://ghcr.io/v2/homebrew/core/readline/blobs/sha256:713fd1fa8544426b7e97eb21d13153195fea4c407db8a174bd183777b81c9192", │ │ │ "externalRefs": [ │ │ │ { │ │ │ "referenceCategory": "PACKAGE-MANAGER", │ │ │ "referenceLocator": "pkg:brew/readline@8.2.10", │ │ │ "referenceType": "purl" │ │ │ } │ │ │ ], │ │ │ @@ -178,19 +178,19 @@ │ │ │ "versionInfo": "2024-03-11" │ │ │ }, │ │ │ { │ │ │ "SPDXID": "SPDXRef-Package-SPDXRef-openssl@3-3.3.0", │ │ │ "checksums": [ │ │ │ { │ │ │ "algorithm": "SHA256", │ │ │ - "checksumValue": "58665ec9e2873dba2799be5992eab3973f230acc352d09bd4a69131ac3ccd2d4" │ │ │ + "checksumValue": "ec6f9daf8e32d96f4a2f4cd56d18533ee47bb8d9e7cb3d832ac64115d8a1a4ca" │ │ │ } │ │ │ ], │ │ │ "copyrightText": "NOASSERTION", │ │ │ - "downloadLocation": "https://ghcr.io/v2/homebrew/core/openssl/3/blobs/sha256:58665ec9e2873dba2799be5992eab3973f230acc352d09bd4a69131ac3ccd2d4", │ │ │ + "downloadLocation": "https://ghcr.io/v2/homebrew/core/openssl/3/blobs/sha256:ec6f9daf8e32d96f4a2f4cd56d18533ee47bb8d9e7cb3d832ac64115d8a1a4ca", │ │ │ "externalRefs": [ │ │ │ { │ │ │ "referenceCategory": "PACKAGE-MANAGER", │ │ │ "referenceLocator": "pkg:brew/openssl@3@3.3.0", │ │ │ "referenceType": "purl" │ │ │ } │ │ │ ], ```

This is basically the problem I describe at https://github.com/Homebrew/brew/issues/17281#issuecomment-2106243956.

MikeMcQuaid commented 4 months ago

This is still happening. See Homebrew/homebrew-core@fd1c80d.

This is basically the problem I describe at #17281 (comment).

That problem was fixed. I cannot reproduce this locally. If I run brew bottle ack --json --only-json-tab I get:

This was not the case before that was fixed.

This is because we're passing bottling: to skip these at brew bottle time: https://github.com/Homebrew/brew/blob/cb168dfe6df49b3dbf5261265d6838c48141ca52/Library/Homebrew/dev-cmd/bottle.rb#L511

These values are only being added at brew install time: https://github.com/Homebrew/brew/blob/610b80e6374cfa7f2e9b1409cd7272c158bbef4e/Library/Homebrew/formula_installer.rb#L835

So this is an issue with either brew test-bot or our homebrew-core CI workflows that is somehow resulting in attempting to double-bottle or use older/cached, broken SBOMs in bottles or something. An issue should probably be opened somewhere but I don't think it's this issue and I don't think (for now) it's Homebrew/brew.

carlocab commented 4 months ago

That problem was fixed. I cannot reproduce this locally. If I run brew bottle ack --json --only-json-tab

No, it is not fixed. You cannot reproduce this problem with ack because ack has no dependencies. You need to do it with something like ruby-build.

Doing brew bottle ruby-build --json --only-json-tab produces a ruby-build/20240517/sbom.spdx.json that contains fields like

    {
      "SPDXID": "SPDXRef-Package-SPDXRef-openssl@3-3.3.0",
      "name": "openssl@3",
      "versionInfo": "3.3.0",
      "filesAnalyzed": false,
      "licenseDeclared": "NOASSERTION",
      "licenseConcluded": "Apache-2.0",
      "downloadLocation": "https://ghcr.io/v2/homebrew/core/openssl/3/blobs/sha256:ec6f9daf8e32d96f4a2f4cd56d18533ee47bb8d9e7cb3d832ac64115d8a1a4ca",
      "copyrightText": "NOASSERTION",
      "checksums": [
        {
          "algorithm": "SHA256",
          "checksumValue": "ec6f9daf8e32d96f4a2f4cd56d18533ee47bb8d9e7cb3d832ac64115d8a1a4ca"
        }
      ],
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE-MANAGER",
          "referenceLocator": "pkg:brew/openssl@3@3.3.0",
          "referenceType": "purl"
        }
      ]
    }

which will, in general, prevent the creation of :all bottles.

MikeMcQuaid commented 4 months ago

Doing brew bottle ruby-build --json --only-json-tab

Ok, thanks for the reproduction command. It was not clear how to reproduce this before and not clear to me until rereading that this was an additional issue unrelated to reproducibility but related to :all bottles specifically.

https://github.com/Homebrew/brew/pull/17370 should address this.