How to Integrate testssl.sh into CI/CD Pipelines for Automated TLS/SSL Testing

Integrate testssl.sh into CI/CD pipelines by adding a single shell step that executes the Bash scanner with --fast --json flags, either by checking out the drwetter/testssl.sh repository directly or running its official Docker image.

The drwetter/testssl.sh repository provides a pure-Bash TLS/SSL scanner designed for command-line automation. Because it requires only standard Unix tools and OpenSSL, you can integrate testssl.sh into CI/CD pipelines without installing heavyweight agents or persistent services. Its single-file entry point and pluggable JSON output make it ideal for security gates in GitHub Actions, GitLab CI, and Jenkins.

Why testssl.sh Fits Modern CI/CD Workflows

The scanner’s architecture is intentionally lightweight for containerized environments. The main testssl.sh script serves as the sole entry point, parsing arguments and orchestrating tests through helper scripts located in the utils/ directory (written in Bash, Perl, and Java). Output modules support CSV, JSON-v1, JSON-v2, and HTML formats, selectable via --output flags or convenience options like --json. Because the tool runs entirely in user-space with no persistent service, it integrates seamlessly into ephemeral CI runners.

GitHub Actions Integration

The repository ships production-ready workflows in .github/workflows/unit_tests_ubuntu.yml and .github/workflows/unit_tests_macos.yml that demonstrate dependency installation and test execution. You can adapt these patterns to scan your own services.

name: TLS Scan

on:
  push:
    branches: [ main ]
  pull_request:

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          repository: drwetter/testssl.sh
          ref: 3.3dev
          path: testssl

      - name: Run testssl.sh
        run: |
          cd testssl
          ./testssl.sh --fast --json result.json example.com:443

      - uses: actions/upload-artifact@v4
        with:
          name: tls-report
          path: testssl/result.json

For a ready-made wrapper, leverage the official testssl-sh-scan GitHub Action available in the marketplace, which encapsulates the same logic shown above.

Docker-Based Integration for GitLab and Jenkins

The Dockerfile in the repository root builds a multi-stage image bundling the scanner and a recent OpenSSL binary. This eliminates version skew when your CI runner’s host OpenSSL is outdated.

GitLab CI Example

tls_scan:
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t testssl:dev .
    - docker run --rm -v $CI_PROJECT_DIR:/output testssl:dev ./testssl.sh --fast --json /output/result.json example.com:443
  artifacts:
    paths:
      - result.json

Jenkins Declarative Pipeline

pipeline {
  agent any
  stages {
    stage('Checkout') {
      steps {
        git url: 'https://github.com/drwetter/testssl.sh.git', branch: '3.3dev'
      }
    }
    stage('Build') {
      steps {
        sh 'docker build -t testssl:dev .'
      }
    }
    stage('Scan') {
      steps {
        sh '''
          docker run --rm \
            -v $WORKSPACE:/work \
            testssl:dev \
            ./testssl.sh --fast --json /work/result.json example.com:443
        '''
        archiveArtifacts artifacts: 'result.json', fingerprint: true
      }
    }
  }
}

If your runner lacks Docker, execute ./testssl.sh directly after checking out the repository; the script requires only Bash, OpenSSL (or LibreSSL), and standard Unix tools.

Implementing Security Gates with JSON Output

Use the --json flag to generate machine-readable output, then parse results with jq to enforce quality gates. The --fast flag disables time-consuming checks while retaining protocol and cipher suite validation, keeping CI execution times minimal.

./testssl.sh --fast --json result.json example.com:443

if jq -e '.[] | select(.severity == "HIGH")' result.json > /dev/null 2>&1; then
  echo "Critical TLS vulnerabilities detected"
  exit 1
fi

To use a custom OpenSSL binary—such as the one bundled in the repository—set the OPENSSL_BIN environment variable before invocation:

export OPENSSL_BIN=$PWD/bin/openssl.Linux.x86_64
./testssl.sh --fast --json result.json example.com:443

Summary

  • Single entry point: The testssl.sh script at the repository root drives all scanning logic, with helper utilities in utils/ handling specific tests like Heartbleed or TLS-FALLBACK.
  • Native CI templates: Reference .github/workflows/unit_tests_ubuntu.yml and .github/workflows/unit_tests_macos.yml for official dependency installation and testing patterns.
  • Containerized consistency: The Dockerfile ensures reproducible results across GitHub Actions, GitLab CI, and Jenkins by bundling a specific OpenSSL version.
  • Automated enforcement: Combine --json output with jq parsing to fail pipelines on high-severity findings without manual review.

Frequently Asked Questions

Can I run testssl.sh without Docker in CI?

Yes. Because testssl.sh is a pure Bash script with dependencies limited to OpenSSL and standard Unix tools, you can execute it directly on Ubuntu, macOS, or Alpine runners. Simply check out the drwetter/testssl.sh repository and run ./testssl.sh from the working directory.

How do I fail a CI pipeline when testssl.sh finds critical vulnerabilities?

Run the scanner with the --json flag to generate structured output, then use a JSON parser like jq to check for high-severity entries. If the query returns matches, exit the shell step with a non-zero status code to mark the pipeline stage as failed.

Does testssl.sh support parallel scanning in CI environments?

While the script itself runs single-threaded per target, you can parallelize execution by launching multiple CI jobs or container instances simultaneously. Each instance should write to a unique output file to avoid collisions, and you can aggregate results in a final pipeline stage.

Which output format is best for programmatic CI integration?

JSON is the recommended format for CI/CD automation because it provides structured severity ratings and finding identifiers that your pipeline can parse with standard tools. Use --json for the standard JSON format or consult doc/testssl.1.md for additional output options including CSV and HTML.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →