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

> Automate TLS SSL testing by integrating testssl.sh into your CI CD pipelines. Learn how to add simple shell steps for continuous security checks.

- Repository: [Dirk Wetter/testssl.sh](https://github.com/drwetter/testssl.sh)
- Tags: how-to-guide
- Published: 2026-02-28

---

**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`](https://github.com/drwetter/testssl.sh/blob/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`](https://github.com/drwetter/testssl.sh/blob/main/.github/workflows/unit_tests_ubuntu.yml) and [`.github/workflows/unit_tests_macos.yml`](https://github.com/drwetter/testssl.sh/blob/main/.github/workflows/unit_tests_macos.yml) that demonstrate dependency installation and test execution. You can adapt these patterns to scan your own services.

```yaml
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

```yaml
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

```groovy
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`](https://github.com/drwetter/testssl.sh/blob/main/./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.

```bash
./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:

```bash
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`](https://github.com/drwetter/testssl.sh/blob/main/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`](https://github.com/drwetter/testssl.sh/blob/main/.github/workflows/unit_tests_ubuntu.yml) and [`.github/workflows/unit_tests_macos.yml`](https://github.com/drwetter/testssl.sh/blob/main/.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`](https://github.com/drwetter/testssl.sh/blob/main/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`](https://github.com/drwetter/testssl.sh/blob/main/./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`](https://github.com/drwetter/testssl.sh/blob/main/doc/testssl.1.md) for additional output options including CSV and HTML.