Understanding testssl.sh Exit Codes and Error Handling

testssl.sh uses numeric exit codes from 0 (success) to 255 (fatal Bash error), defined as constants like ALLOK=0 and ERR_BASH=255 in the main script, to signal environmental failures, connectivity issues, and scan results to calling processes.

The drwetter/testssl.sh repository provides a single-file Bash solution for SSL/TLS testing that communicates execution status through a structured exit code system. Understanding these testssl.sh exit codes is essential for building robust automation, CI/CD pipelines, and error-handling logic around your security scanning workflows.

testssl.sh Exit Code Reference

In testssl.sh, exit codes are declared as constants between lines 73 and 88. The script reserves the upper range (250–255) for environmental and script-level failures, while lower values indicate specific runtime errors.

  • ALLOK=0 (line 88): Successful completion with no errors.
  • ERR_BASH=255: Bash version too old or script not executed with Bash.
  • ERR_CMDLINE=254: Invalid command-line arguments provided.
  • ERR_FCREATE=253: Could not create an output file.
  • ERR_FNAMEPARSE=252: Input file could not be parsed.
  • ERR_NOSUPPORT=251: Requested feature not supported by the current environment.
  • ERR_OSSLBIN=250: Problem locating or executing the OpenSSL binary.
  • ERR_DNSBIN=249: Missing DNS lookup binary.
  • ERR_OTHERCLIENT=248: Other client-related problem.
  • ERR_DNSLOOKUP=247: DNS resolution failure.
  • ERR_CONNECT=246: Network or connectivity problem.
  • ERR_CLUELESS=245: Unexpected internal state.
  • ERR_RESOURCE=244: Needed resource (file, binary, etc.) missing.
  • ERR_CHILD=242: Child process terminated by a signal.

Why Exit Codes Descend from 255 to 242

Bash treats any non-zero exit status as an error. By placing the most severe, script-wide problems in the 250–255 range and normal error cases below 250, downstream tools can distinguish between environmental failures (e.g., missing OpenSSL) and scan-specific problems (e.g., unreachable host).

How testssl.sh Reports Failures

When an error condition is detected, the script calls either fatal() (lines 69–81) or fatal_cmd_line() (lines 88–100). These functions print a colored diagnostic message to standard error, optionally write to a log file, and terminate execution with exit $ERR_CODE. The fatal() helper handles general runtime errors, while fatal_cmd_line() specifically manages invalid argument errors, often printing usage information before exiting.

Handling Exit Codes in Automation Scripts

Capture the exit status immediately after invocation using $?, then implement conditional logic to handle different failure categories. The following pattern separates environmental errors from connectivity issues:

#!/usr/bin/env bash
SCAN_OUTPUT=$(mktemp)

# Execute testssl.sh (example host)

./testssl.sh -p -U example.com >"$SCAN_OUTPUT"
RET=$?

# 0 – all fine

if [[ $RET -eq 0 ]]; then
    echo "✅ Scan completed successfully."

# 240–254 – script-level problems (environment, arguments, missing tools)

elif (( RET >= 240 && RET <= 254 )); then
    echo "❗ Critical failure (code $RET). Check the log for Bash version, missing binaries, or wrong arguments."

# 245–246 – connectivity or resource errors

elif (( RET >= 245 && RET <= 246 )); then
    echo "⚠️  Connectivity or resource issue (code $RET). Consider increasing timeout or fixing DNS."

# 242 – child process died (rare, e.g., signal from parallel worker)

elif [[ $RET -eq 242 ]]; then
    echo "⚡ A worker process was killed. Retry the scan or run in serial mode."

# Anything else – unexpected state

else
    echo "❓ Unknown exit code $RET – see testssl.sh documentation."
fi

rm -f "$SCAN_OUTPUT"

Pipeline Integration and Error Propagation

For CI/CD pipelines, use Bash’s strict mode to ensure that testssl.sh failures immediately halt the pipeline and propagate the correct exit code:

set -euo pipefail
./testssl.sh -U example.com | tee scan.log

# If testssl.sh exits with any non-zero code, the pipeline aborts immediately

The pipefail option ensures that errors from testssl.sh are not masked by the success of tee, preserving the original exit code for downstream processing.

Summary

  • Exit codes range from 0 (success) to 255 (fatal Bash error), with specific constants defined in testssl.sh lines 73–88.
  • Environmental failures (missing binaries, invalid arguments) use codes 250–255, while runtime errors (DNS, connectivity) use 242–249.
  • Internal error handling relies on fatal() (lines 69–81) and fatal_cmd_line() (lines 88–100) to report and exit.
  • Capture $? immediately after execution to ensure you read the correct status before running other commands.
  • Use set -euo pipefail in wrapper scripts to propagate testssl.sh failures correctly through pipelines.

Frequently Asked Questions

What is the difference between fatal() and fatal_cmd_line() in testssl.sh?

Both functions terminate the script with an error code, but fatal() (lines 69–81) handles general runtime errors, while fatal_cmd_line() (lines 88–100) specifically processes invalid command-line argument errors, printing usage information before exiting with ERR_CMDLINE (254).

How can I differentiate between environmental failures and network issues using exit codes?

Environmental and script-level problems (missing binaries, invalid arguments, Bash version issues) occupy the 250–255 range, while network-specific errors use ERR_CONNECT (246) and ERR_DNSLOOKUP (247).

What should I do if testssl.sh returns exit code 242?

Exit code 242 (ERR_CHILD) indicates a child process was terminated by a signal, often occurring during parallel scans. Retry the scan in serial mode or investigate resource limits and signal handling on your system.

Where are the exit code constants documented in the repository?

The constants are defined in testssl.sh (lines 73–88), with additional documentation available in doc/testssl.1.md (the man page source), README.md, and CHANGELOG.md which tracks historical changes to exit code semantics.

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 →