Self-hosted service
testssl/testssl.sh avatar
testssl/testssl.sh

testssl.sh: a TLS checker you clone instead of install

Testing TLS/SSL encryption anywhere on any port

9,278 stars1,157 forksShellGPL-2.0

At a glance

What is it?
testssl.sh is a single Bash script that probes a server's service on any port for TLS/SSL cipher support, protocols and some cryptographic flaws. Cloning the 3.3dev branch is the whole install, output arrives as CSV, two JSON formats or HTML, and the project states plainly that it is meant to be a standalone command line tool rather than a web service.
Who is it for?
Adopt testssl.sh when you control the host, want machine readable TLS output for a specific port, and are willing to track a development branch. Stay on the 3.2 release if unripe changes are a problem for your pipeline.
Can I use it commercially?
Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Shell, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • testssl/testssl.sh9,278 ★ · +70
Star history
Repository2026-09-222026-11-13
testssl/testssl.sh9.2k9.3k

70 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Bash-socket checks let any port be a target

Most of the limits that used to shape this tool came from whatever the local openssl client could and could not do. Those limits are gone because the checks now run over bash sockets. The practical consequence is that the scan target is described by port rather than by protocol: any SSL or TLS enabled service and any STARTTLS service will do, not only a web server on 443. You are not asked to build a target list or pick a service mode for each host. An old openssl binary still ships inside the repository, and the Readme.md also says you can use any LibreSSL or OpenSSL version, which means the version sitting next to the script is a starting point rather than a constraint you inherit.

The cost of that portability is worth naming. Because behaviour is decided by what bash sockets and the bundled tools can reach, a result depends on the host you ran from as much as on the server you aimed at.

Cloning 3.3dev is the entire installation step

There is no package manager anywhere in this project: no gems, no CPAN, no pip. You fetch a branch and run the script from the directory it lands in.

bash
git clone --depth 1 https://github.com/testssl/testssl.sh.git --branch 3.3dev

The requirements are narrow and the Readme.md names them: /bin/bash at version 3.2 or newer, plus standard tools like sed and awk. Linux, MacOS, FreeBSD, NetBSD, WSL2 and MSYS2 or Cygwin are listed as working out of the box. OpenBSD needs bash, and System V Unix probably needs GNU grep installed. Windows support is real but arrives through MSYS2, Cygwin or WSL/WSL2 rather than through a native build, so a Windows user ends up in a POSIX shell running the clone anyway.

An implicit and silent check for binaries runs when the script starts, which means a missing dependency shows up as the first thing that happens instead of as an install time error you can catch before starting work.

The GHCR image skips the clone, the dockerhub route is not live on 3.3dev

Two container routes are described and they are not in the same state of readiness.

bash
docker run --rm -it ghcr.io/testssl/testssl.sh <your_cmd_line>
bash
docker build . -t imagefoo && docker run --rm -t imagefoo testssl.net

The first pulls from GHCR, which the Readme.md says covers linux/amd64, linux/386, linux/arm64, linux/arm/v7, linux/arm/v6 and linux/ppc64le. The second builds from the directory you already cloned.

What you cannot do on this branch is use the dockerhub route. That command line sits inside an HTML comment in the Readme.md, under a note that 3.3dev still has to be created on dockerhub. A reader who copies the older drwetter/testssl.sh invocation from a blog post is running an image that was not rebuilt for this branch. For anyone who needs a repeatable build, the clone plus the second command is the route that has a visible version behind it: the branch you fetch is the version you run.

The image starts from Leap 16.0 and ends on a scratch filesystem

The Dockerfile builds into a throwaway root filesystem and then assembles the final image from nothing. Three details decide what you end up with.

dockerfile
ARG LEAP_VERSION=16.0
dockerfile
FROM scratch AS base-leap
bash
zypper "${ZYPPER_OPTIONS[@]}" --non-interactive install --download-in-advance --no-recommends \
  bash procps grep gawk sed coreutils busybox ldns libidn2-0 socat openssl curl

The package list is the real dependency contract of the container: bash and coreutils for the script, gawk and sed for its text handling, openssl and ldns for the network side, socat and curl for talking to the target, busybox for the commands coreutils does not provide. The build drops the openh264 and non-oss repositories first to shorten sync time, and it deletes licenses, man pages, locale and doc directories afterwards to reclaim roughly 13 MiB. It also notes that busybox --install -s is not supported through the leap package, so hexdump and tar are symlinked by hand.

A second build file, Dockerfile.alpine, sits next to the main one, and the Readme.md sends image builders to Dockerfile.md rather than describing any of this in prose. The consequence for you is that a container build failure is a bug in a shell script that runs zypper, not a configuration mistake on your side.

CSV, two JSON formats and HTML decide what your pipeline can consume

Output shape is the clearest design decision in this project. The Readme.md lists machine readable output as CSV and two JSON formats, plus HTML, and it makes clear output something you configure rather than something you accept. Several command line options exist for running your test and configuring your output, so the format is a choice made at invocation time rather than at build time.

That choice has consequences once the tool is inside a pipeline. A JSON consumer and a CSV consumer parse the same run very differently.

The Readme.md claims that unit tests check consistency, whether the JSON is valid, and that they run under Linux and MacOS. That is a narrower promise than a schema guarantee. Treat the JSON as a snapshot of one run against one port, and keep your own copy of the field names your tooling depends on.

Support covers n-1 versions, so the branch choice decides your upgrade path

The Readme.md states that current manpower supports n-1 versions, and it names where each one sits. You are looking at the 3.3dev branch, where development takes place before 3.4 becomes stable and 3.2 becomes old-stable. If you are hesitant about changes, the project's own instruction is to use 3.2. The 3.0 line is closed: version 3.0.10 was the last one and there will be no more updates.

The releases make that split visible. v3.2.4, named as a bugfix, was published on 2026-07-12, and snapshot 2607 from 3.3dev was published the same day. The earlier snapshot 2602 from 3.3dev is dated 2026-02-13. The last push to the repository was on 2026-10-28.

A workflow pinned to the development branch can change underneath you, which the Readme.md acknowledges when it says changes might need a bit time to mature. If you need a stable target to schedule against, pin the branch you clone rather than tracking the repository default.

A clean run says nothing about the service behind the port

The scope fits in one sentence: the tool checks a server's service on any port for the support of TLS/SSL ciphers, protocols as well as some cryptographic flaws. Some cryptographic flaws is the project's own wording, and that qualifier is the limit that matters when you read a report.

There is no host or application testing in that sentence, and the repository layout does not suggest otherwise. The top level holds the testssl.sh script plus bin/, etc/, utils/, t/, doc/, Dockerfile, Dockerfile.alpine, Dockerfile.md, FAQ.md, CHANGELOG.md, SECURITY.md, CREDITS.md and Coding_Convention.md. That reads as a scanner codebase, not a broader assessment tool, and t/ is where the unit tests live.

So a clean report tells you about ciphers, protocols and some cryptographic flaws on the port you aimed at. It does not tell you what is running there, or what the situation looks like on the other ports.

The README asks you not to hang it behind a web service

The warning section is unusually direct. Usage is without any warranty and at your own risk. The Readme.md says the tool is intended to be used as a standalone CLI tool, that security measures and input sanitization were applied but cannot be guaranteed to leave it free of vulnerabilities, that running as a web service may pose security risks, and that you should validate input from the user and from all services which are queried.

For a reader, the consequence is direct. Wrapping this script in an HTTP endpoint puts its parsing logic and your target selection behind whatever authentication you wrote, and the project has told you in advance that it does not stand behind that arrangement. Running it from a shell against hosts you already control is the supported shape.

The licensing carries a matching condition for a second group of users. It is GPLv2, and the Readme.md asks that anyone offering a scanner based on testssl.sh as a public or paid service mention that they are using the program and where to get it, so that bugfixes and feedback keep flowing back. The documentation side is settled: the man page ships in groff, html and markdown format under doc/, the site at testssl.sh helps you get started, and the longer description linked from the documentation section was written for version 2.8 and still carries background reading.

Editorial conclusion

Adopt testssl.sh when you control the host, want machine readable TLS output for a specific port, and are willing to track a development branch. Stay on the 3.2 release if unripe changes are a problem for your pipeline. Do not put it behind a web endpoint: the Readme.md says running as a web service may pose security risks, that usage carries no warranty, and that you must validate input from users and from every service queried. Before you trust a report, read its CSV or JSON yourself and compare it against a second tool, because a quiet run only speaks to ciphers, protocols and some cryptographic flaws on the one port you aimed at.

Frequently asked questions

what is testssl sh

testssl.sh is a free command line tool under GPLv2 that checks a server's service on any port for the support of TLS/SSL ciphers, protocols and some cryptographic flaws. It is written in Bash and needs no gems, CPAN or pip, because you run it from a cloned directory.

how to install testssl sh

Clone the branch you intend to run: `git clone --depth 1 https://github.com/testssl/testssl.sh.git --branch 3.3dev`. The script then runs from that directory. If you would rather not fetch the repository, the published container is `docker run --rm -it ghcr.io/testssl/testssl.sh <your_cmd_line>`.

how to use testssl sh on windows

Windows is supported through MSYS2, Cygwin or WSL/WSL2 rather than a native build, so you end up running the clone inside a POSIX shell. You need /bin/bash at version 3.2 or newer plus standard tools such as sed and awk.

is testssl sh safe

The Readme.md states that usage is without any warranty and at your own risk, that the tool is intended as a standalone CLI, and that running it as a web service may pose security risks. It asks you to validate input from the user and from all services which are queried.

testssl sh alternative

The Readme.md names no competing scanner. The nearest thing it points to for background reading is a longer description by Will Hunt that was written for version 2.8 and is linked from the documentation section, alongside the site at testssl.sh and a generated wiki.

Official sources

  1. License: GPL-2.0
  2. Project website
  3. README
  4. Releases
  5. testssl/testssl.sh on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/testssl-testssl-sh.svg)](https://hysenlabs.com/projects/testssl-testssl-sh)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/testssl-testssl-sh.svg)](https://hysenlabs.com/projects/testssl-testssl-sh)

Was this useful?