Skip to content

fix(boot): install rustls CryptoProvider to prevent panic on first TLS call [0.7 backport]#144

Merged
claudio-michel[bot] merged 1 commit into
release/0.7from
fix/rustls-crypto-provider-panic-0.7
Jun 5, 2026
Merged

fix(boot): install rustls CryptoProvider to prevent panic on first TLS call [0.7 backport]#144
claudio-michel[bot] merged 1 commit into
release/0.7from
fix/rustls-crypto-provider-panic-0.7

Conversation

@claudio-michel

@claudio-michel claudio-michel Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Summary

0.7.x backport of #143 (the rustls CryptoProvider fix). v0.7.14 / v0.7.15 ship with the same dual-backend problem because the Sentry-feature expansion landed there too. Any 0.7.x binary built with `--features sentry` panics on its first TLS connection.

```
panic: Could not automatically determine the process-level
CryptoProvider from Rustls crate features. Call
CryptoProvider::install_default() before this point to select a
provider manually, or make sure exactly one of the 'aws-lc-rs' and
'ring' features is enabled.
```

The bug is latent on 0.7.14 / 0.7.15 — same dep graph as rc.8 (sentry 0.47 + rustls 0.23 + both `ring` and `aws-lc-rs` linked transitively). The fix is identical: `rustls::crypto::ring::default_provider().install_default()` at the very start of `logging::init()`.

Conflict resolution

Clean cherry-pick of `99533ca` (the main-branch fix). All three files (`Cargo.toml`, `Cargo.lock`, `src/core/logging.rs`) auto-merged.

Tests

```
cargo test → 977/977 green
cargo test --features sentry → 582 passed + 1 known-flake (test_cli_output_args_named_flag_captures_file passes serially; same parallel-test race noted on PR #141 — unrelated to this fix)
cargo clippy --features sentry --lib --tests -- -D warnings → clean
cargo fmt --all --check → clean
```

The cli_executor_test flake hits the exact same test that was flaky on PRs #138 and #141, and runs through --test-threads=1 cleanly. My fix only touches logging.rs + Cargo.toml; the flaky test exercises CLI executor file-handling and is unrelated.

After this lands

  • v0.7.16 bump PR + tag → final 0.7.x release (this displaces v0.7.15 as the sunset cut).
  • Demo / staging environments running v0.7.15 with the sentry binary should upgrade immediately — they're panicking today on every first TLS call.

Sister PR

  • #143 — same fix on the 0.8 main line. Cuts the next rc with it.

🤖 Generated with Claude Code

…anic

rc.8 ships with the --features sentry binary panicking at first TLS
connection:

  panic: Could not automatically determine the process-level
  CryptoProvider from Rustls crate features. Call
  CryptoProvider::install_default() before this point to select a
  provider manually, or make sure exactly one of the 'aws-lc-rs' and
  'ring' features is enabled.

  Sentry issue BACKEND-TEST-2RH, 2 events, release 0.8.0-rc.8.

Root cause is a dual-crypto-backend link in the dep graph that the
--features sentry build triggers:

  rustls 0.23.37 enables 'ring' AND 'aws-lc-rs' features
  ├── ring ← jsonwebtoken, reqwest 0.12 (our direct dep, rustls-tls)
  └── aws-lc-rs ← rustls-platform-verifier 0.6.2
                  └── reqwest 0.13.2
                      └── sentry 0.47 (via 'rustls' feature)

The 'rustls' feature on the sentry crate (which we enable in #137's
expanded feature list) routes to reqwest 0.13 internally, which pulls
rustls-platform-verifier → aws-lc-rs. Our own reqwest 0.12 pulls ring.
rustls 0.23 sees both, refuses to auto-pick, and panics on the first
handshake.

Fix:

  rustls::crypto::ring::default_provider().install_default()

Called once at the very start of `logging::init()`, before any TLS
client is built (sentry's transport, reqwest pools, the proxy's
auth_generator, MCP HTTP transport). Pinned to `ring` because that's
the backend the rest of the binary already uses (jsonwebtoken signs
with ring; reqwest's rustls-tls feature pulls ring). install_default()
returns Err if a provider was already installed — we discard that
result; first installer wins, both backends implement the same TLS
standards, what matters is consistency at the process level.

Verification:

End-to-end smoke against a live proxy built with --features sentry,
pointed at the same Sentry DSN that produced the rc.8 panic:

  ✓ Proxy boots clean (no panic, no CryptoProvider error in log)
  ✓ /health → 200 OK with rc.8 version
  ✓ /tools → 200 OK, manifest loaded
  ✓ /call → real TLS handshake to https://httpbin.org/get, 200 OK
  ✓ Sentry batcher flushed 8 log items + 3 events to
    o4506617108561920.ingest.us.sentry.io, all returned event IDs
  ✓ Proxy stayed alive across 4 TLS roundtrips + Sentry flushes
  ✓ Zero matches for panic|CryptoProvider|aws-lc|FATAL in proxy log

Full test suite under --features sentry: 1256 passed / 0 failed.
cargo clippy --features sentry --lib --tests -- -D warnings clean.
cargo fmt --all --check clean.

This bug was latent in v0.7.14 / v0.7.15 too (same sentry feature
set). Will be backported to release/0.7 in a separate PR if those
binaries are still in service.
@greptile-apps

greptile-apps Bot commented Jun 5, 2026

Copy link
Copy Markdown

Greptile Summary

This is a 0.7.x backport of the rustls CryptoProvider fix from the main branch. It resolves a boot-time panic that occurs in any binary built with --features sentry, caused by both the ring and aws-lc-rs rustls backends being transitively linked (reqwest 0.12 via ring, sentry's reqwest 0.13 via rustls-platform-verifier / aws-lc-rs). The canonical fix — explicitly calling rustls::crypto::ring::default_provider().install_default() before any TLS use — is applied early in logging::init().

  • Cargo.toml: Adds a direct rustls = \"0.23\" dependency (with ring and std features) so the ring-specific install_default() API is callable; includes a thorough inline comment explaining the dual-backend root cause.
  • src/core/logging.rs: Adds install_crypto_provider() helper and calls it at the very top of init(), before Sentry and the tracing subscriber are initialized, ensuring the provider is set before any TLS connection can fire.
  • Cargo.lock: Records the new direct rustls entry for the ati package (the crate itself was already in the lock file transitively).

Confidence Score: 4/5

Safe to merge — the fix correctly resolves the boot-time TLS panic that affects all sentry-enabled 0.7.x binaries today.

The core fix (pinning the rustls ring provider before any TLS use) is the canonical approach for this rustls 0.23 dual-backend problem and is applied at the right point in the boot sequence. The one open question is whether the direct rustls dep and the install call should be gated behind the sentry feature flag, since the conflict only arises in sentry builds — leaving them unconditional is harmless but slightly inflates the non-sentry dep surface. No logic errors or correctness issues in the changed code.

Cargo.toml — the unconditional rustls dep is worth a second look to confirm the team is happy with it being present in non-sentry builds.

Important Files Changed

Filename Overview
src/core/logging.rs Adds install_crypto_provider() helper and calls it unconditionally at the top of init(); fix is correct but runs even in non-sentry builds where the dual-backend conflict never occurs.
Cargo.toml Adds a direct, always-on rustls 0.23 dep with ring+std features; not gated behind the sentry feature even though the dual-backend panic only manifests with --features sentry.
Cargo.lock Lock file correctly updated to record the new direct rustls dependency for the ati package; no unexpected version changes.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[main] --> B[logging::init]
    B --> C[install_crypto_provider]
    C --> D[rustls ring default_provider install_default]
    D -->|Ok - first caller wins| E[Provider set to ring]
    D -->|Err - already installed| E
    E --> F[init_sentry]
    F -->|sentry feature on| G[sentry::init via reqwest 0.13]
    F -->|sentry feature off| H[None]
    G --> I[Build tracing subscriber]
    H --> I
    I --> J[Application TLS connections]
    J --> K[rustls reads ring provider - no panic]

    subgraph Without this fix
        L[First TLS call] --> M{Auto-detect provider}
        M -->|ring AND aws-lc-rs both linked| N[PANIC: Could not determine CryptoProvider]
    end
Loading

Reviews (1): Last reviewed commit: "fix(boot): install rustls CryptoProvider..." | Re-trigger Greptile

Comment thread Cargo.toml
# (matches the `ring` backend the rest of the binary uses via
# jsonwebtoken + reqwest's rustls-tls feature). Single-binary fix —
# no Cargo.lock surgery needed. rc.8 panic root cause.
rustls = { version = "0.23", default-features = false, features = ["ring", "std"] }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unconditional rustls dep widens the footprint of non-sentry builds

The dual-backend conflict (ring + aws-lc-rs) only materialises when --features sentry is used, because that's the only path that transitively pulls in aws-lc-rs (via sentry's reqwest 0.13 → rustls-platform-verifier). The direct rustls dep and the install_crypto_provider() call in logging.rs are therefore both added to every build regardless of the sentry feature flag.

In practice the impact is minimal — rustls is already compiled in transitively via reqwest's rustls-tls feature, so the added binary size is near-zero. But the intent is clearer and the dep graph is cleaner if both the dep and the call are gated behind sentry. That said, the unconditional approach is a valid defensive choice — if another future dependency ever pulls in aws-lc-rs in a non-sentry build, the provider will already be pinned. Worth a deliberate decision either way.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@claudio-michel claudio-michel Bot merged commit 63149a6 into release/0.7 Jun 5, 2026
6 checks passed
@claudio-michel claudio-michel Bot deleted the fix/rustls-crypto-provider-panic-0.7 branch June 5, 2026 15:57
@claudio-michel claudio-michel Bot mentioned this pull request Jun 5, 2026
4 tasks
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.

0 participants