From d4f1b31f0de8127172133581a3676e55debf837e Mon Sep 17 00:00:00 2001 From: Raymond Huygen Date: Thu, 21 May 2026 15:29:50 +0200 Subject: [PATCH 1/2] Fix DNS CAA check for IP scans and subdomains - Skip CAA lookup entirely when NODE is an IP address; show "not checked (IP address scan)" instead of spuriously querying IP octets as domain labels and reporting "not offered" - Force FQDN (trailing dot) on the initial caa_node before the walk loop so dig does not apply the resolv.conf search domain to the first query, which could return a false result - Add a visible warning in the scan header when scanning by IP address, noting that trust/CAA and other domain-specific checks may be unreliable and the user should rescan with the hostname --- testssl.sh | 73 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/testssl.sh b/testssl.sh index b022a19..fd6399b 100755 --- a/testssl.sh +++ b/testssl.sh @@ -10268,39 +10268,44 @@ certificate_info() { out "$indent"; pr_bold " DNS CAA RR"; out " (experimental) " jsonID="DNS_CAArecord" - caa_node="$NODE" - caa="" - while [[ -z "$caa" ]] && [[ -n "$caa_node" ]]; do - caa="$(get_caa_rr_record $caa_node)" - tmp=${PIPESTATUS[@]} - [[ $DEBUG -ge 4 ]] && echo "get_caa_rr_record: $tmp" - [[ $caa_node =~ '.'$ ]] || caa_node+="." - caa_node=${caa_node#*.} - done - if [[ -n "$caa" ]]; then - pr_svrty_good "available"; out " - please check for match with \"Issuer\" below" - if [[ $(count_lines "$caa") -eq 1 ]]; then - out ": " - else - outln; out "$spaces" - fi - while read caa; do - if [[ -n "$caa" ]]; then - all_caa+="$caa, " - fi - done <<< "$caa" - all_caa=${all_caa%, } # strip trailing comma - pr_italic "$(out_row_aligned_max_width "$all_caa" "$indent " $TERM_WIDTH)" - fileout "${jsonID}${json_postfix}" "OK" "$all_caa" - elif [[ -n "$NODNS" ]]; then - out "(instructed to minimize/skip DNS queries)" - fileout "${jsonID}${json_postfix}" "INFO" "check skipped as instructed" - elif "$DNS_VIA_PROXY"; then - out "(instructed to use the proxy for DNS only)" - fileout "${jsonID}${json_postfix}" "INFO" "check skipped as instructed (proxy)" + if is_ipv4addr "$NODE" || is_ipv6addr "$NODE"; then + out "not checked (IP address scan -- no domain to query)" + fileout "${jsonID}${json_postfix}" "INFO" "not checked (IP address scan)" else - pr_svrty_low "not offered" - fileout "${jsonID}${json_postfix}" "LOW" "--" + caa_node="$NODE" + [[ $caa_node =~ '.'$ ]] || caa_node+="." # force FQDN to prevent dig search-domain expansion + caa="" + while [[ -z "$caa" ]] && [[ -n "$caa_node" ]]; do + caa="$(get_caa_rr_record $caa_node)" + tmp=${PIPESTATUS[@]} + [[ $DEBUG -ge 4 ]] && echo "get_caa_rr_record: $tmp" + caa_node=${caa_node#*.} + done + if [[ -n "$caa" ]]; then + pr_svrty_good "available"; out " - please check for match with \"Issuer\" below" + if [[ $(count_lines "$caa") -eq 1 ]]; then + out ": " + else + outln; out "$spaces" + fi + while read caa; do + if [[ -n "$caa" ]]; then + all_caa+="$caa, " + fi + done <<< "$caa" + all_caa=${all_caa%, } # strip trailing comma + pr_italic "$(out_row_aligned_max_width "$all_caa" "$indent " $TERM_WIDTH)" + fileout "${jsonID}${json_postfix}" "OK" "$all_caa" + elif [[ -n "$NODNS" ]]; then + out "(instructed to minimize/skip DNS queries)" + fileout "${jsonID}${json_postfix}" "INFO" "check skipped as instructed" + elif "$DNS_VIA_PROXY"; then + out "(instructed to use the proxy for DNS only)" + fileout "${jsonID}${json_postfix}" "INFO" "check skipped as instructed (proxy)" + else + pr_svrty_low "not offered" + fileout "${jsonID}${json_postfix}" "LOW" "--" + fi fi outln @@ -23606,6 +23611,10 @@ display_rdns_etc() { outln " A record via: $CORRECT_SPACES supplied IP \"$CMDLINE_IP\"" fi fi + if is_ipv4addr "$NODE" || is_ipv6addr "$NODE"; then + prln_warning " Warning: IP scan -- Trust, CAA and SNI-dependent checks may be unreliable. Rescan with hostname for accurate results." + fileout "ip_scan_warning" "WARN" "Scanning by IP address: Trust, CAA and SNI-dependent checks may be unreliable" + fi if [[ "$rDNS" =~ instructed ]]; then out "$(printf " %-23s " "rDNS ($nodeip):")" out "$rDNS" From f8af511952d2e81cee5953c96fa67c56964323c0 Mon Sep 17 00:00:00 2001 From: Dirk Wetter Date: Wed, 27 May 2026 16:53:06 +0200 Subject: [PATCH 2/2] Improve PR #3041 * move message when scanning IP address to the very beginning, inside parse_cmd_line() * improve message * just check whether there are no chars a-zA-Z * move [[ $caa_node =~ '.'$ ]] || caa_node+="." into the while loop --- testssl.sh | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/testssl.sh b/testssl.sh index fd6399b..06d422c 100755 --- a/testssl.sh +++ b/testssl.sh @@ -10273,9 +10273,9 @@ certificate_info() { fileout "${jsonID}${json_postfix}" "INFO" "not checked (IP address scan)" else caa_node="$NODE" - [[ $caa_node =~ '.'$ ]] || caa_node+="." # force FQDN to prevent dig search-domain expansion caa="" while [[ -z "$caa" ]] && [[ -n "$caa_node" ]]; do + [[ $caa_node =~ '.'$ ]] || caa_node+="." # force FQDN to prevent dig search-domain expansion caa="$(get_caa_rr_record $caa_node)" tmp=${PIPESTATUS[@]} [[ $DEBUG -ge 4 ]] && echo "get_caa_rr_record: $tmp" @@ -23611,10 +23611,6 @@ display_rdns_etc() { outln " A record via: $CORRECT_SPACES supplied IP \"$CMDLINE_IP\"" fi fi - if is_ipv4addr "$NODE" || is_ipv6addr "$NODE"; then - prln_warning " Warning: IP scan -- Trust, CAA and SNI-dependent checks may be unreliable. Rescan with hostname for accurate results." - fileout "ip_scan_warning" "WARN" "Scanning by IP address: Trust, CAA and SNI-dependent checks may be unreliable" - fi if [[ "$rDNS" =~ instructed ]]; then out "$(printf " %-23s " "rDNS ($nodeip):")" out "$rDNS" @@ -24682,6 +24678,7 @@ parse_cmd_line() { local outfile_arg="" local cipher_mapping local -i subret=0 + local tmp="" CMDLINE="$(create_cmd_line_string "${CMDLINE_ARRAY[@]}")" CMDLINE_PARSED=false @@ -25361,6 +25358,14 @@ parse_cmd_line() { set_rating_state fi + tmp=${URI#*//} # remove https:// + if [[ ! $tmp =~ [a-zA-Z] ]]; then + # No letters indicate it's not a name + outln + pr_warning " Warning: Target is not a server name: results may be completely wrong, at minimum trust may show false results." + fileout "ip_scan_warning" "WARN" "Target is not a server name: results may be completely wrong, at minimum trust may show false results." + fi + CMDLINE_PARSED=true }