Skip to content

SHA256 from PACKAGES is not checked against the downloaded file #145

Description

@nbenn

The sha256 that pkgdepends passes to async_copy_or_add() is never compared with the download. After download_one_of() returns, it is replaced by the hash of whatever arrived:

pkgcache/R/package-cache.R

Lines 275 to 282 in cd17b44

download_one_of(
urls,
target,
on_progress = on_progress,
headers = http_headers
)$then(function(d) {
headers <- curl::parse_headers(d$response$headers, multiple = TRUE)
sha256 <- shasum256(target)

For CRAN macOS binaries, download_one_of() races the CRAN mirror against mac.cran.dev and keeps the first to finish, so a stale file on mac.cran.dev gets installed even if it does not match PACKAGES:

pkgcache/R/packages-gz.R

Lines 466 to 470 in cd17b44

macurl <- paste0("https://mac.cran.dev/", target)
os <- parse_platform(platform)$os
macbin <- type == "cran" & !is.na(os) & grepl("^darwin", os)
result[macbin] <- zip_vecs(url[macbin], macurl[macbin])

This is currently the case for adbcdrivermanager 0.24.0-3 on macOS with R 4.6. Since the zstd mix-up (r-lib/pkgdepends#485, r-lib/pak#915), the file on cran.rstudio.com is gzip again and matches PACKAGES (3b73522a…), while mac.cran.dev still serves the zstd file (2bd7d854…). Our CI got the mac.cran.dev copy and failed with "unknown archive type".

A check would also need the hash parsed correctly. The SHA256sum: field in CRAN's macOS PACKAGES is folded onto a continuation line. Base R's read.dcf() returns the bare hash, but the parsed value here keeps the line break and indentation:

pak::pkg_download(
  "adbcdrivermanager",
  dest_dir = tempfile(),
  platforms = "aarch64-apple-darwin23",
  r_versions = "4.6",
  dependencies = FALSE
)$sha256
#> [1] "\n        3b73522a5d65d7dad8ddcbfed2045da6d61ae25458d3c973f55928d937166ed5"

Could a download that does not match the expected hash be rejected, so the other source is used instead? If that sounds reasonable, I'm happy to propose a PR.

Activity

  1. gaborcsardi commented on Sep 23, 2026

    @gaborcsardi
    Member

    I hope at some point all CRAN repos will have secure hashes and they will be in sync with the package files as well, and then we can actually check the downloaded files, but I think we are not there yet.

    For this particular issue a workaround is to switch to PPM, see the cited issues.

    Or just wait a bit, since the issue is apparently already fixed on mac.r-project.org, only the mac.cran.dev front needs to invalidate its cache.

  2. nbenn commented on Sep 23, 2026

    @nbenn
    Author

    For this particular issue a workaround is to switch to PPM, see the cited issues.

    Our macOS job already uses PPM (the setup-r@v2 default since r-lib/actions#1110), but PPM has no macOS binaries of adbcdrivermanager 0.24.0-3 and adbcsqlite 0.24.0-2, so pak still takes them from CRAN.

    I hope at some point all CRAN repos will have secure hashes and they will be in sync with the package files as well, and then we can actually check the downloaded files, but I think we are not there yet.

    The check wouldn't need to reject anything. Instead of keeping whichever download finishes first, download_one_of() could keep the first one whose hash matches, discard mismatches and cancel the rest; if none matches, it would keep the first one, as today. A missing or out-of-date hash then costs at most the wait for the slower copy.

    For us this is transient, so if you think the check isn't worth it for the few cases it would catch, I'm happy to close this.

  3. gaborcsardi commented on Sep 23, 2026

    @gaborcsardi
    Member

    For us this is transient, so if you think the check isn't worth it for the few cases it would catch, I'm happy to close this.

    No, my problem is that I am not convinced that it is doing more good than harm, because I don't trust the CRAN repos having consistent metadata. The whole reason for the fallback to the alternate server is that they have inconsistent metadata.

    OTOH I don't mind making the fallback serial, i.e. first try CRAN, then mac.cran.dev. That'll solve this. Of course by the time I publish that in pak devel, the caching issue will be probably solved.....

  4. gaborcsardi commented on Sep 23, 2026

    @gaborcsardi
    Member

    Should be good now.

  5. nbenn commented on Sep 24, 2026

    @nbenn
    Author

    Yup, all good now (via refreshed cache). I'll keep this open in case you want to move to a fixed ordering. If not, we can close here. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions