Skip to content

Verify every OCI digest and Helm charts before caching - #583

Merged
andrew merged 2 commits into
git-pkgs:mainfrom
simonchrz:fix/verify-all-digests
Oct 24, 2026
Merged

andrew merged 2 commits into
git-pkgs:mainfrom
simonchrz:fix/verify-all-digests

Conversation

@simonchrz

Copy link
Copy Markdown
Contributor

Two places where fetched content could be cached before it was verified.

OCI digests other than sha256. Manifests and digest-addressed artifacts were only checked when the digest was sha256:. A sha512: digest, which the OCI spec also allows, or one with any other algorithm was fetched and cached unchecked: a manifest requested as sha512:<hex>, or a tag whose Docker-Content-Digest header named a sha512 digest, was stored under that digest whatever the body was.

  • Manifests are checked against any digest in the reference or Docker-Content-Digest with that digest's algorithm. A digest the proxy can't compute gets DIGEST_INVALID (502) and nothing is cached.
  • GetOrFetchArtifactFromURLWithDigest verifies sha512 (and sha384) through the existing declared-integrity check, so a mismatch is never committed, and refuses other algorithms with ErrUnsupportedDigest instead of fetching unverified. sha256 handling is unchanged. Blob routes still accept only sha256, as before.

Helm charts. Without stream_artifacts, a chart was fetched with no expected digest, committed to the cache, and only then compared with the index digest by serveChart, which cleared it again. The index digest is now always passed to the fetch, so a mismatching chart is discarded before it is committed, as already happened when streaming.

Tests: TestContainerHandler_ManifestDigestsAreVerified (replaces TestContainerHandler_ManifestNonSHA256DigestReferenceIsProxied, which asserted the old pass-through), TestFetchWithDigestVerifiesEveryAlgorithm (stored and streamed), and TestHelmHandler_RejectsChartDigestMismatch now expects nothing left in storage.

Manifests and digest-addressed artifacts were only checked against
sha256 digests. A sha512 digest, which the OCI spec also allows, or a
digest with any other algorithm was fetched and cached unchecked: a
manifest requested as sha512:<hex>, or a tag whose Docker-Content-Digest
header named one, was stored under that digest whatever the body was.

Manifests are now checked against any digest in the reference or the
Docker-Content-Digest header with the digest's own algorithm, and one
the proxy can't compute is answered with DIGEST_INVALID and not cached.
GetOrFetchArtifactFromURLWithDigest verifies sha512 (and sha384)
digests through the declared-integrity check, so a mismatch is never
committed, and refuses other algorithms with ErrUnsupportedDigest
instead of fetching unverified. Blob routes still only accept sha256.
Without artifact streaming, a chart was fetched with no expected
digest, committed to the cache, and only then compared with the
index's digest by serveChart, which cleared it again. Until then the
unverified chart was a cache entry like any other.

The index digest is now always passed to the fetch, so a mismatching
chart is discarded before it is committed, as it already was when
streaming. serveChart's check stays for charts that were cached before.
@andrew
andrew merged commit 1c3f1aa into git-pkgs:main Oct 24, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants