Skip to content

libsodium source is downloaded without integrity verification or retry #1071

Description

@boorad

Found while triaging an unrelated CI failure on #1070. Two separate problems in the same code path, one reliability and one security.

What happened

The iOS e2e job failed at pod install:

[QuickCrypto] ⬇️  Downloading libsodium source...
curl: (6) Could not resolve host: download.libsodium.org
[!] Invalid `QuickCrypto.podspec` file: Failed to download libsodium.

A single DNS blip on a GitHub runner red-lights the whole build. The host was fine again minutes later, so it was transient — but there's no retry, so any hiccup at download.libsodium.org fails every pod install with SODIUM_ENABLED=1.

The security part

QuickCrypto.podspec:77 downloads the libsodium source tarball and compiles it, with no checksum, no signature check, and no pinned hash:

system("curl -sSfL ... -o ios/libsodium.tar.gz https://download.libsodium.org/libsodium/releases/libsodium-#{sodium_version}-stable.tar.gz") || raise(...)
system("tar -xzf ios/libsodium.tar.gz -C ios") || raise(...)

Whatever that host returns gets extracted and built into a cryptography library. TLS covers the transport, but nothing pins what we expect to receive — a compromised mirror, a hijacked domain, or a maintainer-side republish under the same URL would be compiled silently.

We already do this correctly for OpenSSL in the same file — download, verify a pinned SHA-256, fail loudly on mismatch. libsodium should meet the same bar, since it's the one we build from source rather than consume as a verified binary.

A second, weaker copy

prepare_command (line 95) downloads the same tarball again with:

curl -L -o ios/libsodium.tar.gz https://download.libsodium.org/...

Note -L without -f: on an HTTP error, curl writes the error page to libsodium.tar.gz and exits 0, so the failure surfaces later as a confusing tar error instead of a download error.

The version is also hardcoded as a literal 1.0.22 here while line 68 uses sodium_version, so the two can drift.

Suggested fix

  1. Pin a SHA-256 for the libsodium tarball and verify it, mirroring the OpenSSL block.
  2. Add --retry 3 --retry-all-errors to both fetches.
  3. Add -f to the prepare_command curl.
  4. Use a single version constant in both places.

Optionally verify libsodium's minisign signature instead of a pinned hash, though a pinned hash is simpler and stronger against republishing.

Scope

Only affects SODIUM_ENABLED=1 builds. Not a regression — this predates #1070, which doesn't touch these lines.

Metadata

Metadata

Assignees

No one assigned

    Labels

    buildIssue building libraryrubyPull requests that update ruby codesecuritySecurity-related issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions