testssl.sh is a powerful bash-based SSL/TLS testing utility that performs comprehensive security assessments. It checks for protocol support, cipher vulnerabilities, certificate validity, and known TLS exploits more thoroughly than lighter tools like sslscan.
Installation
Clone from GitHub
git clone --depth 1 https://github.com/drwetter/testssl.sh.git
cd testssl.sh
chmod +x testssl.sh
Quick Install (macOS)
brew install testssl.sh
Docker
docker pull drwetter/testssl.sh
docker run --rm drwetter/testssl.sh https://example.com
Dependencies
# Most systems have these. testssl.sh may warn if missing:
apt-get install openssl curl dnsutils socat
# On Alpine/minimal systems: apk add openssl curl bind-tools socat
Basic Testing
Quick Test
./testssl.sh https://example.com
./testssl.sh --quick https://example.com
Test Specific Port
./testssl.sh https://example.com:8443
./testssl.sh example.com:443
testssl.sh -t smtp mail.example.com:587 # STARTTLS
| Command | Description |
|---|
./testssl.sh https://example.com | Full comprehensive scan |
./testssl.sh --quick https://example.com | Fast scan (essential checks only) |
./testssl.sh example.com:443 | Custom port |
./testssl.sh -t smtp mail.example.com:587 | SMTP with STARTTLS |
./testssl.sh -t xmpp example.com:5222 | XMPP STARTTLS |
Protocol Testing
Check Protocol Support
./testssl.sh --protocols https://example.com
./testssl.sh --ssl-v2 https://example.com # SSLv2 (deprecated)
./testssl.sh --ssl-v3 https://example.com # SSLv3 (deprecated)
./testssl.sh --tls1 https://example.com # TLS 1.0
./testssl.sh --tls1-1 https://example.com # TLS 1.1
./testssl.sh --tls1-2 https://example.com # TLS 1.2
./testssl.sh --tls1-3 https://example.com # TLS 1.3
| Command | Description |
|---|
--protocols | Test all supported protocols |
--ssl-v2 | Test SSLv2 support (should fail) |
--ssl-v3 | Test SSLv3 support (should fail) |
--tls1 | Test TLS 1.0 support (legacy) |
--tls1-1 | Test TLS 1.1 support (legacy) |
--tls1-2 | Test TLS 1.2 support (modern) |
--tls1-3 | Test TLS 1.3 support (latest) |
Cipher and Cryptography Testing
Cipher Suites
./testssl.sh --ciphers https://example.com
./testssl.sh --ciphers --strength https://example.com
./testssl.sh --weak https://example.com # Find weak ciphers
./testssl.sh --rc4 https://example.com # Check for RC4
| Command | Description |
|---|
--ciphers | List all supported ciphers |
--ciphers --strength | Show cipher strength ratings |
--weak | Highlight weak ciphers only |
--rc4 | Test specifically for RC4 support |
--null | Test for NULL ciphers |
--export | Test for export-grade ciphers |
Key Exchange and Hash Algorithms
./testssl.sh --sigalgs https://example.com
./testssl.sh --eccbrainpool https://example.com
./testssl.sh --curves https://example.com
| Command | Description |
|---|
--sigalgs | Show signature algorithms |
--eccbrainpool | Test ECC Brainpool curves |
--curves | List supported elliptic curves |
--dsa | Check DSA key support |
Vulnerability Testing
Heartbleed (CVE-2014-0160)
./testssl.sh --heartbleed https://example.com
| Command | Description |
|---|
--heartbleed | Test OpenSSL Heartbleed vulnerability |
CCS Injection (CVE-2014-0224)
./testssl.sh --ccs https://example.com
| Command | Description |
|---|
--ccs | Test CCS Injection vulnerability |
ROBOT (CVE-2017-13099)
./testssl.sh --robot https://example.com
| Command | Description |
|---|
--robot | Test ROBOT decryption vulnerability |
POODLE (CVE-2014-3566)
./testssl.sh --poodle https://example.com
| Command | Description |
|---|
--poodle | Test POODLE downgrade vulnerability |
BEAST (CVE-2011-3389)
./testssl.sh --beast https://example.com
| Command | Description |
|---|
--beast | Test BEAST cipher block chaining issue |
CRIME (CVE-2012-4929)
./testssl.sh --crime https://example.com
| Command | Description |
|---|
--crime | Test CRIME compression attack |
BREACH (CVE-2013-3566)
./testssl.sh --breach https://example.com
| Command | Description |
|---|
--breach | Test HTTP compression vulnerability |
Lucky13 (CVE-2013-0169)
./testssl.sh --lucky13 https://example.com
| Command | Description |
|---|
--lucky13 | Test Lucky13 timing attack |
FREAK (CVE-2015-0204)
./testssl.sh --freak https://example.com
| Command | Description |
|---|
--freak | Test FREAK export key vulnerability |
Logjam (CVE-2015-4000)
./testssl.sh --logjam https://example.com
| Command | Description |
|---|
--logjam | Test Logjam DHE downgrade attack |
DROWN (CVE-2016-0800)
./testssl.sh --drown https://example.com
| Command | Description |
|---|
--drown | Test DROWN SSLv2 attack |
Sweet32 (CVE-2016-2183)
./testssl.sh --sweet32 https://example.com
| Command | Description |
|---|
--sweet32 | Test 64-bit block cipher vulnerability |
OpenSSL Padding Oracle (CVE-2016-2107)
./testssl.sh --padding-oracle https://example.com
| Command | Description |
|---|
--padding-oracle | Test padding oracle vulnerability |
Ticketbleed (CVE-2016-9244)
./testssl.sh --ticketbleed https://example.com
| Command | Description |
|---|
--ticketbleed | Test TLS session ticket vulnerability |
Certificate Analysis
Check Certificate Details
./testssl.sh --cert https://example.com
./testssl.sh --cert-validity https://example.com
./testssl.sh --cert-chain https://example.com
| Command | Description |
|---|
--cert | Display full certificate information |
--cert-validity | Check certificate expiration and validity |
--cert-chain | Show certificate chain (CA hierarchy) |
--cert-signalg | Display signature algorithm |
--cert-extensions | Show certificate extensions |
Certificate Issues
./testssl.sh --cert-info https://example.com # Full analysis
./testssl.sh --self-signed https://example.com
./testssl.sh --verify-hostname https://example.com
| Command | Description |
|---|
--cert-info | Detailed certificate information |
--self-signed | Check if certificate is self-signed |
--verify-hostname | Verify hostname matches certificate |
--wildcard | Check for wildcard certificate |
./testssl.sh --hsts https://example.com
./testssl.sh --headers https://example.com
| Command | Description |
|---|
--hsts | Check HSTS header |
--headers | Check security-related HTTP headers |
--hpkp | Check HTTP Public Key Pinning |
STARTTLS Testing
Test STARTTLS Services
./testssl.sh -t smtp mail.example.com:587
./testssl.sh -t pop3 mail.example.com:110
./testssl.sh -t imap mail.example.com:143
./testssl.sh -t xmpp example.com:5222
./testssl.sh -t ldap ldap.example.com:389
| Command | Description |
|---|
-t smtp host:587 | Test SMTP with STARTTLS |
-t pop3 host:110 | Test POP3 with STARTTLS |
-t imap host:143 | Test IMAP with STARTTLS |
-t xmpp host:5222 | Test XMPP with STARTTLS |
-t ldap host:389 | Test LDAP with STARTTLS |
-t ftp host:21 | Test FTP with STARTTLS |
JSON Output
./testssl.sh --json https://example.com > results.json
./testssl.sh --json --outfile results.json https://example.com
| Command | Description |
|---|
--json | Output results in JSON format |
--json --outfile file.json | Save JSON output to file |
CSV Output
./testssl.sh --csv https://example.com > results.csv
./testssl.sh --csv --outfile results.csv https://example.com
| Command | Description |
|---|
--csv | Output results in CSV format |
--csv --outfile file.csv | Save CSV to file |
HTML Output
./testssl.sh --html https://example.com > results.html
./testssl.sh --html --outfile results.html https://example.com
| Command | Description |
|---|
--html | Generate HTML report |
--html --outfile file.html | Save HTML report to file |
Logging
./testssl.sh --logfile results.log https://example.com
./testssl.sh --append https://example.com # Append to existing log
| Command | Description |
|---|
--logfile file.log | Save output to log file |
--append | Append to log instead of overwriting |
Batch and Mass Testing
Test Multiple Hosts
./testssl.sh --file hosts.txt
| Command | Description |
|---|
--file hosts.txt | Test list of hosts (one per line) |
Batch Testing Script
while IFS= read -r host; do
./testssl.sh --json --outfile "${host//\//_}.json" "https://$host"
done < hosts.txt
Parallel Testing
cat hosts.txt | parallel ./testssl.sh --json --outfile {}.json https://{}
CI/CD Integration
GitHub Actions Example
name: SSL/TLS Testing
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Clone testssl.sh
run: git clone --depth 1 https://github.com/drwetter/testssl.sh.git
- name: Run testssl
run: |
./testssl.sh/testssl.sh --json \
--outfile results.json \
https://example.com
- name: Upload results
uses: actions/upload-artifact@v2
with:
name: ssl-test-results
path: results.json
Jenkins Integration
stage('SSL/TLS Security Scan') {
steps {
sh '''
git clone --depth 1 https://github.com/drwetter/testssl.sh.git
./testssl.sh/testssl.sh --json \
--outfile results.json \
https://example.com
'''
archiveArtifacts artifacts: 'results.json'
}
}
GitLab CI
ssl_tls_scan:
stage: security
script:
- git clone --depth 1 https://github.com/drwetter/testssl.sh.git
- ./testssl.sh/testssl.sh --json --outfile results.json https://example.com
artifacts:
paths:
- results.json
./testssl.sh --fast https://example.com # Skip slow tests
./testssl.sh --slow https://example.com # Run additional slow tests
./testssl.sh --nofallback https://example.com # Skip fallback checks
| Command | Description |
|---|
--fast | Faster scan, skip slower vulnerability tests |
--slow | Include additional slow/thorough tests |
--nofallback | Disable protocol fallback testing |
--servername name | TLS SNI (needed for shared hosting) |
Severity Levels
./testssl.sh --severity HIGH https://example.com
./testssl.sh --severity CRITICAL https://example.com
| Command | Description |
|---|
--severity HIGH | Show only high/critical findings |
--severity CRITICAL | Show only critical findings |
| Feature | testssl.sh | sslscan | sslyze |
|---|
| Protocol vulnerability checks | Comprehensive | Basic | Good |
| Cipher analysis | Detailed | Detailed | Detailed |
| Certificate analysis | Full | Limited | Moderate |
| Speed | Slower | Fast | Fast |
| Language | Bash | C | Python |
| STARTTLS support | Yes | Yes | Yes |
| Output formats | JSON/CSV/HTML | XML | JSON/CSV |
| Automation friendly | Very | Moderate | Good |
| CVE detection | Yes (Heartbleed, POODLE, etc.) | Limited | Moderate |
When to Use What
# Quick scan for major issues
./testssl.sh --quick https://example.com
# Detailed compliance audit
./testssl.sh --severity HIGH https://example.com
# Integration with monitoring
./testssl.sh --json --outfile scan.json https://example.com
# Compare against baseline
./testssl.sh --json https://example.com | jq .findings[]
# Check certificate renewal alerts
./testssl.sh --cert-validity https://example.com
Common Workflows
Full Security Audit
#!/bin/bash
host=$1
./testssl.sh --html --outfile "${host}_report.html" "https://$host"
./testssl.sh --json --outfile "${host}_data.json" "https://$host"
echo "Report saved: ${host}_report.html"
Monitor Certificate Expiry
#!/bin/bash
for host in $(cat hosts.txt); do
days_left=$(./testssl.sh --cert-validity "https://$host" | grep -oP '\d+(?= days)')
if [ "$days_left" -lt 30 ]; then
echo "ALERT: $host expires in $days_left days"
fi
done
Track Cipher Strength Over Time
#!/bin/bash
host=$1
timestamp=$(date +%s)
./testssl.sh --ciphers --strength "https://$host" > "ciphers_${timestamp}.txt"
# Compare with previous runs
diff ciphers_*.txt
Interpreting Results
| Finding | Severity | Action |
|---|
| SSLv2/v3 enabled | CRITICAL | Disable immediately |
| TLS 1.0/1.1 enabled | HIGH | Disable or plan removal |
| Weak ciphers (RC4, DES) | HIGH | Remove from supported ciphers |
| Self-signed certificate | MEDIUM | Use CA-signed certificate |
| Expired certificate | CRITICAL | Renew certificate |
| Certificate chain issues | MEDIUM | Complete chain configuration |
| Missing HSTS header | MEDIUM | Add HSTS header |
| Known vulnerabilities | CRITICAL | Patch immediately |
Tips and Best Practices
# Test with SNI for multi-domain hosting
./testssl.sh --servername example.com https://shared-ip.com
# Save baseline for comparison
./testssl.sh --json https://example.com > baseline.json
# Test only without certificate validation (dev environments)
./testssl.sh --noverify https://test.internal:8443
# Enable verbose logging for debugging
./testssl.sh -v https://example.com
# Run specific test only
./testssl.sh --heartbleed https://example.com
./testssl.sh --drown https://example.com
Resources and Documentation