Skip to content

chore: consolidate on one TLS stack, ship static musl binaries#79

Merged
bashandbone merged 2 commits into
mainfrom
chore/consolidate-tls-static-musl
Jul 26, 2026
Merged

chore: consolidate on one TLS stack, ship static musl binaries#79
bashandbone merged 2 commits into
mainfrom
chore/consolidate-tls-static-musl

Conversation

@bashandbone

Copy link
Copy Markdown
Owner

Two TLS stacks, one of them load-bearing for every ignored advisory

git2/libgit2-sys/libssh2-sys link openssl-sys. gix used blocking-http-transport-curl-rustls, which pulled a second, entirely separate stack:

gix[blocking-http-transport-curl-rustls]
  └─ curl-sys → rustls-ffi → ├─ rustls → aws-lc-rs → aws-lc-sys
                             └─ paste

Every advisory deny.toml was ignoring except one came from that subtree — RUSTSEC-2024-0436 (paste), RUSTSEC-2026-0044 and RUSTSEC-2026-0048 (aws-lc X.509). So did an unallowed OpenSSL license clause on aws-lc-sys that was failing cargo deny check licenses on main.

Switching to blocking-http-transport-curl-openssl makes curl share the openssl-sys that is already being linked. rustls, aws-lc-sys and paste leave the graph entirely: 368 → 294 crates.

The three ignores are deleted, not left dormant — if any of them reappears, the build fails rather than silently absorbing it. Only RUSTSEC-2024-0364 (gitoxide-core terminal escapes, no patched version) remains.

Note on the variant. This is the -openssl feature deliberately. Bare blocking-http-transport-curl enables no TLS crate at all and defers HTTPS to whatever system libcurl the host provides — I'd previously described that one as "TLS from OpenSSL," which was wrong.

Verified against a real remote

Dependency-graph reasoning isn't enough here, so this was checked end to end: an HTTPS submodule add against github.com, then update --verbose showing gix's curl transport completing the handshake and returning the full ref advertisement.

+refs/heads/*:refs/remotes/origin/*
	081721d0… refs/heads/main -> refs/remotes/origin/main [up-to-date]
	skipped 224 tags known to the remote without bearing on this commit-graph.

569/569 tests pass, cargo deny check advisories clean, cargo fmt --check clean.

Static musl binaries

The release matrix built no musl target at all — every Linux artifact linked glibc dynamically. Adds x86_64- and aarch64-unknown-linux-musl via cross.

The existing git2/vendored-libgit2,git2/vendored-openssl features now cover curl too, precisely because both consume the same openssl-sys — that only became true with this change.

LIBCURL_NO_PKG_CONFIG=1 forces curl-sys to build libcurl from source instead of probing pkg-config for the build image's copy. A release binary that dynamically links the builder's libcurl isn't portable, and a glibc-linked one wouldn't work on musl at all. It's set job-wide rather than per-target because the variable is presence-checked — a ${{ ... && '1' || '' }} expression evaluates to '', which still reads as set. It only affects Linux either way: curl-sys returns early with the system libcurl on Apple targets and uses vcpkg on Windows.

deny.toml's target list had drifted from reality — musl, x86_64-apple-darwin and x86_64-pc-windows-gnu were checked but never built, while aarch64-pc-windows-msvc was built but never checked. Both lists now match.

Release safety

workflow_dispatch only gated the create-release step. publish and github_release had no condition, so a manual dispatch ran cargo publish --allow-dirty against crates.io and cut a real GitHub release — while the build job treated that same event as a dry run. Both are now gated, so dispatch is an actual dry run.

Not verified locally

There's no Docker/cross on this machine, so the musl builds themselves are unproven. Now that dispatch is safe, a workflow_dispatch run on this branch will exercise all seven targets without publishing — worth doing before merge.

Flagged, not fixed

cargo deny check also surfaces RUSTSEC-2026-0184git2 0.20.4 Blame::blame_buffer() null-pointer deref, fixed in 0.21.0. It doesn't fail CI (the advisories step allows unsound) and submod never calls blame, but it wants a follow-up bump. I left it out to keep a dependency-graph change from also carrying a git2 major bump.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XocU6NjgZricrRWMLyLXDn

submod linked two TLS stacks. git2/libgit2-sys/libssh2-sys use openssl-sys;
gix used blocking-http-transport-curl-rustls, which pulled curl-sys ->
rustls-ffi -> {rustls -> aws-lc-rs -> aws-lc-sys, paste}. That second stack
was the sole source of three ignored RUSTSEC advisories (2024-0436 paste,
2026-0044 and 2026-0048 aws-lc X.509) and of an unallowed OpenSSL license
clause on aws-lc-sys that was failing `cargo deny check licenses`.

Switching gix to blocking-http-transport-curl-openssl makes curl share the
openssl-sys that is already linked, removing rustls, aws-lc-sys and paste
from the graph entirely: 368 -> 294 crates. The three ignores are deleted
rather than left in place, so a re-entry of any of them fails the build
instead of being silently absorbed.

This is the -openssl variant deliberately. Bare blocking-http-transport-curl
enables no TLS crate at all and defers HTTPS to whatever system libcurl the
host happens to provide.

Verified against a real remote, not just the dependency graph: an HTTPS
submodule add against github.com and a subsequent `update --verbose` showing
gix's curl transport completing the TLS handshake and returning the full ref
advertisement. 569/569 tests pass.

Static musl binaries
--------------------
The release matrix built no musl target, so every Linux artifact linked
glibc dynamically. Adds x86_64- and aarch64-unknown-linux-musl via cross.
The existing git2/vendored-libgit2,vendored-openssl features now cover curl
too, since both consume the same openssl-sys.

LIBCURL_NO_PKG_CONFIG=1 forces curl-sys to build libcurl from source rather
than probing pkg-config for the build image's copy — a release binary that
dynamically links the builder's libcurl is not portable, and a glibc-linked
one would not work on musl at all. It is set for the whole job rather than
per-target because the variable is presence-checked: a
`${{ ... && '1' || '' }}` expression would still read as set everywhere. It
only affects Linux regardless, as curl-sys returns early with the system
libcurl on Apple targets and uses vcpkg on Windows.

deny.toml's target list had drifted from what is actually built: musl,
x86_64-apple-darwin and x86_64-pc-windows-gnu were checked but never built,
while aarch64-pc-windows-msvc was built but never checked. Both lists now
match.

Release safety
--------------
workflow_dispatch only gated the create-release step. `publish` and
`github_release` had no condition, so a manual dispatch ran
`cargo publish --allow-dirty` against crates.io and cut a real GitHub
release, while the build job treated the same event as a dry run. Both jobs
are now gated, making dispatch an actual dry run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XocU6NjgZricrRWMLyLXDn
@bashandbone
bashandbone force-pushed the chore/consolidate-tls-static-musl branch from 134c120 to 2343beb Compare July 26, 2026 03:11
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XocU6NjgZricrRWMLyLXDn
@bashandbone
bashandbone merged commit 1256c3e into main Jul 26, 2026
8 checks passed
@bashandbone
bashandbone deleted the chore/consolidate-tls-static-musl branch July 26, 2026 03:19
@codecov

codecov Bot commented Jul 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

1 participant