diff --git a/pkg/downloader/chart_downloader.go b/pkg/downloader/chart_downloader.go index 22c6c71a3..722cfdedc 100644 --- a/pkg/downloader/chart_downloader.go +++ b/pkg/downloader/chart_downloader.go @@ -85,6 +85,10 @@ type ChartDownloader struct { // Cache specifies the cache implementation to use. Cache Cache + + // ExpectedDigest is the digest from the repository index or OCI reference. + // When set, downloaded content is compared and a warning is emitted on mismatch. + ExpectedDigest string } // DownloadTo retrieves a chart. Depending on the settings, it may also download a provenance file. @@ -152,6 +156,10 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven if err != nil { return "", nil, err } + + if err := verifyDownloadedDigest(c.Out, ref, c.ExpectedDigest, hash, data); err != nil { + return "", nil, err + } } name := filepath.Base(u.Path) @@ -592,6 +600,27 @@ func loadRepoConfig(file string) (*repo.File, error) { return r, nil } +// verifyDownloadedDigest compares downloaded chart bytes against the digest from +// the repository index or OCI reference. A mismatch emits a warning to out. +func verifyDownloadedDigest(out io.Writer, ref, expectedDigest, resolvedDigest string, data *bytes.Buffer) error { + digest := expectedDigest + if digest == "" { + digest = resolvedDigest + } + if digest == "" || data == nil { + return nil + } + computed, err := provenance.Digest(bytes.NewReader(data.Bytes())) + if err != nil { + return err + } + if !digestEqual(digest, computed) { + fmt.Fprintf(out, "WARNING: digest mismatch for %s: repository index has sha256:%s, downloaded content has sha256:%s\n", + ref, stripDigestAlgorithm(digest), computed) + } + return nil +} + // stripDigestAlgorithm removes the algorithm prefix (e.g., "sha256:") from a digest string. // If no prefix is present, the original string is returned unchanged. func stripDigestAlgorithm(digest string) string {