Verify TLS certificates for rediss:// queue URLs by default - #434
Merged
Merged
Conversation
CI::Queue::Redis::Base passed `ssl_params: { verify_mode: VERIFY_NONE }`
for every connection on redis-rb 5.x, so a `rediss://` queue URL was
encrypted but never authenticated the server. Anyone able to intercept
traffic between a worker and Redis could impersonate the server, read
the credentials in the queue URL, and tamper with queue and result data.
Connections now use OpenSSL's default peer and hostname verification.
Deployments that trust a private CA can point OpenSSL at it (for example
with SSL_CERT_FILE). Deployments whose hosted Redis only offers an
unverifiable self-signed certificate can explicitly opt out with
CI_QUEUE_REDIS_SSL_VERIFY=0 or `Configuration#redis_ssl_verify = false`.
The setting is also forwarded to the heartbeat monitor subprocess, which
previously always verified, so opted-out deployments no longer fail there.
Co-authored-by: Mike Wilson <mike.wilson@shopify.com>
The previous tests only inspected the ssl_params hash handed to redis-client. That missed hostname verification and never exercised the heartbeat monitor, which gets the setting through an environment variable across a process boundary; a break there is silent because the monitor only logs connection failures. Add TLSRedisStub, an in-process TLS listener with a self-signed certificate, and test the actual handshake: workers and the monitor reject it by default and connect when opted out. Hostname verification is asserted on the effective SSL context. Drop test_redis_ssl_params, which only pinned the helper's return shape. Also add an upgrade note to the README, since 0.99.0 and earlier skipped verification and affected workers otherwise report "Ran 0 tests" and exit successfully, and correct the monitor comment: the reason for the env var is that it doesn't load ci-queue, not --disable-gems (RubyGems is loaded when spawned as `ruby monitor.rb`).
mdwn
marked this pull request as ready for review
September 30, 2026 13:52
collin-miller
approved these changes
Sep 30, 2026
This branch was successfully deployed
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.
Why
On redis-rb 5.x,
CI::Queue::Redis::Basepassedssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE }for every connection. So arediss://queue URL was encrypted, but ci-queue never checked the server's identity. Anyone who can intercept traffic between a worker and Redis could pose as the server, read the credentials in the queue URL, and tamper with queue and result data.What
rediss://connections now use OpenSSL's default peer and hostname verification (ssl_params: {}→ VERIFY_PEER,verify_hostname: true, system CA store).CI_QUEUE_REDIS_SSL_VERIFY=0/false, orCI::Queue::Configuration#redis_ssl_verify = false. Verification stays on if the variable is unset, empty, or set to anything else.ruby/README.md, with an upgrade note for users coming from 0.99.0 or earlier.TLSRedisStub(ruby/test/support/tls_redis_stub.rb), an in-process TLS listener that presents a self-signed cert. They check the real handshake: workers and the heartbeat monitor reject the cert by default and connect when opted out. Hostname verification is checked on the SSL context the client actually builds.This changes the default. VERIFY_NONE was added in 1f4e449 for hosted Redis providers such as Heroku Redis that present self-signed certificates. Those deployments will stop connecting after upgrading. What they will see:
minitest-queue runprintsRan 0 testsand exits 0, because connection errors are swallowed as they already are for an unreachable Redis.minitest-queue reportfails withRedis::CannotConnectError … certificate verify failed.How to fix it: trust the issuing CA (e.g.
SSL_CERT_FILE=/path/to/ca.pem), or accept the risk and setCI_QUEUE_REDIS_SSL_VERIFY=0. The release that ships this should call it out.Verification
Tested against a local
redis-server8.10.1 with TLS enabled and a cert signed by a throwaway CA (SANlocalhost):certificate verify failed (self-signed certificate in certificate chain)SSL_CERT_FILEPONG127.0.0.1certificate verify failed (hostname mismatch)redis_ssl_verify: falsePONGredis://PONG(ssl_paramshas no effect)minitest-queue runwithCI_QUEUE_REDIS_SSL_VERIFY=0Automated:
rake test): 323 tests, 0 failures.monitor did not honor the verification opt-out, if theCI_QUEUE_REDIS_SSL_VERIFYvalue passed toProcess.spawnis removed.