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.shlines 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) andfatal_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 pipefailin 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →