Repository navigation
Verify TLS peers by default - #144
Merged
dominicletz merged 3 commits intoOct 22, 2026
Merged
Conversation
OTP 29 no longer accepts a certificate whose only name is the CN, so the three TLS tests that verify the peer fail on master with hostname_check_failed / missing_subject_altnames. The server certificate now carries DNS:localhost.
Elixir 1.19 warns when a variable bound outside a match is used in size/1 without a pin, and mix lint runs with --warnings-as-errors.
wss:// connections now verify the server certificate and hostname unless `insecure: true` is passed. The trust store comes from :public_key.cacerts_get/0 on OTP 25+, or :castore when present; `cacerts:` and `ssl_options:` still override it. Fixes dominicletz#1
Closed
Contributor
Author
|
CI for this exact commit (b8f8604) on the latest OTP/Elixir, run on my fork since upstream Actions wait for approval: https://github.com/neilberkman/websockex/actions/runs/39855740601 (Lint and test: success). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1.
What changes
wss://connections now verify the server certificate and hostname by default.WebSockex.Conndefaultsinsecuretofalse, andssl_connection_options/1covers every case in this order:ssl_optionsgiven: unchanged, the caller controls the TLS options.insecure: true: unchanged,verify: :verify_none. This is the explicit opt-out.cacertsgiven:verify: :verify_peerwith those certificates, plus the:httpshostname match function so wildcard certificates match.verify: :verify_peerwith the OS trust store from:public_key.cacerts_get/0(OTP 25+), falling back to:castorewhen it is present. When neither is available,open_socket/1returns{:error, %WebSockex.ConnError{}}whose reason explains the options instead of raising.:castoreis added as an optional dependency. The:insecure,:cacerts, and:ssl_optionsdocs are rewritten, the README gets a short TLS section, and the changelog gets a breaking-change entry.Why now
The current default was set in 2017 when getting Erlang
sslverification right was hard (see the commit history around #1). Since then OTP 25 added:public_key.cacerts_get/0, OTP 26 madeverify_peerthesslclient default, and other Elixir HTTP and WebSocket clients verify by default. The library default is the remaining gap, and it has consequences downstream: req_llm shipped GHSA-6vww-5m28-f26v (CVSS 7.4) because it used WebSockex with the defaults, sending API keys and OAuth tokens over unverified TLS.Compatibility
This is a breaking default and suits a 0.6.0 release. Existing callers that pass
insecure: trueare unaffected. Callers on OTP 25+ get verification against the OS trust store with no change. Callers on older OTP without:castoreand withoutcacertsorssl_optionsget a connection error that names the fix. Callers who already passinsecure: falsewithcacertskeep working and gain hostname wildcard matching.Two preparatory commits
hostname_check_failed, missing_subject_altnames), so the three TLS tests that verify the peer already fail onmasterunder current OTP. The server certificate now carriesDNS:localhost;generate_certs.shis updated accordingly and subjects are unchanged.bytes-size(len)withlenbound outside the match, andmix lintruns with--warnings-as-errors, so CI onelixir-version: latestfails without this. This duplicates the open Pin operators added to matching inside the frame module #142 and Pin variables used in match (for elixir 1.20) #143; if either lands first I will drop this commit.Tests
New in
conn_test.exs: the default rejects the test CA withunknown_ca;insecure: falsealone takes the default trust-store path; suppliedcacertswith a host of127.0.0.1fails the hostname check withbad_certificate. Existing tests that relied on the insecure default now passcacerts: WebSockex.TestServer.cacerts().Verification
On Elixir 1.20.4 / OTP 29:
mix lint(compile with warnings as errors, format check, credo, dialyzer) passes andmix testreports 216 passed. The OTP < 25 and:castorefallback paths were reviewed but not run.🤖 Generated with Claude Code