OpenSSL s_client - ssl error - TLS security

OpenSSL s_client Showed My TLS Was Broken: Diagnosing SSL Errors in CI

When you push a commit, your CI/CD pipeline runs, tests pass, and deployment is just a click away. Then suddenly, your build fails with a cryptic TLS message.
No code changes to blame, yet the pipeline is red. What happened? For many teams, the culprit is often a TLS security issue, such as an expired certificate, a weak cipher, or a misconfigured server. The good news? These problems are easy to detect before they break your builds if you know how to use OpenSSL s_client.

This article will walk you through diagnosing and preventing SSL errors in CI/CD pipelines using openssl s_client. We’ll cover real examples, automation techniques, and guardrails that keep your deployments safe.

When Your Pipeline Screams: A Real TLS Failure

Here’s a familiar sight for many DevOps engineers:

bash
$ openssl s_client -connect example.com:443
CONNECTED(00000003)
depth=0 CN = example.com
Verify error:num=10:certificate has expired

That SSL error means the endpoint’s certificate has expired. In CI/CD, this halts deployments, breaks integration tests, and can block your entire release.

Worse still, if ignored, this same TLS security gap could expose production systems to man-in-the-middle attacks or cause service downtime.

Why OpenSSL s_client is the Developer’s TLS Debug Knife

Unlike browser warnings, which are vague and manual, OpenSSL’s s_client gives a raw, detailed view of the TLS handshake.
It’s ideal for:

  • Checking which TLS version and cipher an endpoint uses
  • Validating that certificates are valid and trusted
  • Debugging connections directly in a CI/CD job

Example handshake check:

bash
openssl s_client -connect service.internal:443 -servername service.internal -tls1_2

You get immediate visibility into certificate details, supported ciphers, and any SSL errors during negotiation. That’s why many DevSecOps teams treat it as a go-to TLS security tool.

Common TLS/SSL Errors That Break CI Pipelines

Let’s break down the failures most likely to appear in CI/CD, with short examples and impacts.

1 Expired or Not-Yet-Valid Certificates

bash
$ openssl s_client -connect example.com:443
Verify error:num=10:certificate has expired

Impact: Automated tests fail when a dependency uses an outdated certificate. In microservice architectures, one expired cert in an internal service can stop the whole deployment chain.

2 Weak Ciphers or Deprecated Protocols

bash
openssl s_client -connect app.dev:443 -cipher LOW

Impact: Security gates fail when a service supports TLS 1.0/1.1 or weak ciphers. This often appears during compliance scans in regulated environments.

3 Hostname Mismatches & Self-Signed Certificates

Example: An internal staging service uses a certificate issued for the service.local, but the pipeline calls service.dev. Alternatively, the certificate might be self-signed and not trusted by the runner’s trust store.

Impact: The handshake verification fails unless explicitly bypassed, dangerous in production. This is common in internal API calls, local testing setups, or misconfigured dev environments.

4 Incomplete Certificate Chains

Example: Staging cert missing an intermediate CA.
Impact: Runners with stricter trust stores will fail connections, causing intermittent build failures.

Want to Go Deeper into CI/CD Threats?

CI/CD pipelines play a pivotal role in facilitating streamlined software development. Yet, as these pipelines become increasingly crucial, the imperative to protect them from vulnerabilities becomes more pronounced. Dive into an in-depth investigation that focuses on addressing a prominent risk identified in the OWASP Top-10 CI/CD Security Risks!

Related read:

Diagnosing TLS Failures in CI/CD with OpenSSL s_client

First step: reproduce the failure in your CI/CD environment.

yaml
- name: Check TLS
  run: |
    openssl s_client -connect api.prod:443 -servername api.prod </dev/null

This gives you a full TLS handshake transcript,  protocol, cipher, certificate chain, and any validation errors.

Look for:

  • Verify error messages
  • Old TLS protocol versions
  • Missing intermediates in the chain

Transition to Automation:

Once you can isolate the root cause, the next move is to make these checks automatic. Manual diagnosis is fine once, but without automation, you’ll see the same SSL error in another pipeline weeks later.

Automating TLS Checks as Security Guardrails

You can embed TLS checks into your CI/CD so that bad configs fail early:

  • Alert if a cert expires in less than 30 days
  • Block weak ciphers and deprecated TLS versions
  • Require complete certificate chains

Example guardrail:

bash
if openssl s_client -connect $HOST:$PORT </dev/null 2>/dev/null | grep -q "Protocol  : TLSv1"; then
  echo "❌ Weak protocol detected"
  exit 1
fi

Tip: Run this in a pre-deploy stage so you catch issues before merging code.

Preventing TLS Surprises in Production

TLS issues don’t just happen during deployments. Certificates expire at any time. That’s why continuous monitoring is essential in DevSecOps.

Example scheduled check with GitHub Actions:

yaml
name: TLS Monitor
on:
  schedule:
    - cron: "0 6 * * *"
jobs:
  check-tls:
    runs-on: ubuntu-latest
    steps:
      - name: Check TLS expiration
        run: |
          EXP_DATE=$(echo | openssl s_client -connect example.com:443 2>/dev/null \
            | openssl x509 -noout -enddate | cut -d= -f2)
          echo "Certificate expires on: $EXP_DATE"

You can adapt this to cron jobs, Jenkins, or Kubernetes CronJobs to continuously scan endpoints for TLS security issues.

Real AppSec Risks from Broken TLS

Broken TLS configurations aren’t just build problems; they’re security liabilities:

  • MITM attacks if encryption is weak or missing
  • Downgrade attacks if older protocols are allowed
  • Supply chain risks if package downloads occur over insecure connections

Putting It All Together with Guardrails

Think of this process as: Diagnose → Automate → Enforce.

Why Guardrails Matter: In CI/CD, guardrails stop insecure TLS configurations before they go live. They can block a deployment if:

  • A cert is about to expire
  • A weak cipher is enabled
  • An obsolete protocol is used

Example: In GitLab CI, a job fails instantly if an endpoint responds with TLS 1.0,  forcing the fix before merge.

Tools like Xygeni can extend these guardrails to scan your entire software supply chain for TLS security gaps.

Handy OpenSSL s_client One-Liners for CI

Check expiration:

bash
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate

List ciphers:

bash
openssl ciphers -v 'ALL:eNULL' | column -t

Final takeaway

OpenSSL s_client is more than a troubleshooting command; it’s a DevSecOps tool for proactive TLS security. Use it to catch SSL errors before they break your builds, and automate it so you’re never surprised by a certificate expiration or weak cipher again.

sca-tools-software-composition-analysis-tools
Prioritize, remediate, and secure your software risks
7-day free trial
No credit card required

Secure your Software Development and Delivery

with Xygeni Product Suite