[Bug] WebSocket transport hardcodes `webpki-roots`, causing `UnknownIssuer` while HTTP works with system trust store
- Dominant language
- Rust
- Stars
- 1.3k
- Forks
- 668
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 29
Description
### Component
transports
### What version of Alloy are you on?
Alloy version: 1.7.4
### Operating System
macOS (Apple Silicon)
### Describe the bug
Title: WebSocket transport hardcodes `webpki-roots`, causing `UnknownIssuer` while HTTP works with system trust store
## Summary
I ran into a TLS trust-store inconsistency between Alloy's HTTP and WebSocket transports.
In my environment, the same RPC provider works over HTTPS once HTTP is configured to use the system/native trust store, but WebSocket still
fails with:
```text
invalid peer certificate: UnknownIssuer
From code inspection, alloy-transport-ws currently uses tokio-tungstenite with rustls-tls-webpki-roots, which appears to hardcode the WS
trust source to WebPKI roots.
This makes ProviderBuilder::connect_ws(...) fail in environments where the certificate chain is trusted by the OS/system trust store but not
by the WebPKI root set.
## Current behavior
WebSocket connection fails with an error chain like:
IO error: invalid peer certificate: UnknownIssuer
Caused by [1]: IO error: invalid peer certificate: UnknownIssuer
Caused by [2]: invalid peer certificate: UnknownIssuer
In contrast, HTTP to the same provider works once using system/native TLS.
## Expected behavior
WebSocket transport should provide a way to use the system trust store as well, or expose TLS customization so users can align WS behavior
with HTTP behavior.
## Relevant implementation
In the current codebase, alloy-transport-ws depends on:
tokio-tungstenite = { workspace = true, features = ["rustls-tls-webpki-roots"] }
and WsConnect::connect() uses:
tokio_tungstenite::connect_async_with_config(...)
without exposing a custom TLS connector or root-store choice.
## Why this matters
This creates behavior differences between HTTP and WS against the same RPC endpoint:
- HTTP can be made to work with system/native trust
- WS remains pinned to WebPKI roots
- users have no hook to inject a custom TLS connector
This is especially problematic in enterprise/proxied environments or with providers whose cert chain is accepted by the system trust store
but not by WebPKI roots.
## Suggested fixes
Any of these would help:
1. Switch WS transport to native/system roots
2. Expose a custom tokio_tungstenite::Connector
3. Add a configurable TLS/root-store strategy for WS transport
## Environment
- Alloy version: 1.7.4
- Commit: 4e6ff5a6
- OS: macOS
Contributor guide
Assessment
This issue has not been assessed yet.