Understanding the testssl.sh Rating System: How Grades Are Calculated and What They Mean

The testssl.sh rating system is an experimental implementation of the SSL Labs SSL Server Rating Guide that calculates a weighted score across protocol support (30%), key exchange (30%), and cipher strength (40%), then maps the result to letter grades A through F with possible caps for critical vulnerabilities or trust issues.

The drwetter/testssl.sh repository includes an automated grading feature that benchmarks TLS/SSL configurations against industry standards. This testssl.sh rating system enables rapid comparative assessment of server security by assigning letter grades from A+ to F based on cryptographic strength, protocol versions, and certificate validity.

How the testssl.sh Rating Algorithm Works

The rating logic is centralized in the run_rating() function within the main testssl.sh script (lines 24119–24130). This implementation follows the SSL Labs SSL Server Rating Guide (version 2009r, dated 2025‑05‑16) as specified in the project documentation.

Initial Caps and Preconditions

Before calculating scores, the function checks for conditions that immediately limit the maximum possible grade:

  • STARTTLS penalty: If the scan uses STARTTLS, the script applies an automatic "T" cap at lines 24131–24136 because STARTTLS is considered downgrade‑prone.
  • Hard caps: If a cap of F, T, or M was previously set (e.g., due to Heartbleed, certificate name mismatches, or revoked certificates), the function exits early at lines 24153–24166, reporting a score of 0 with the capped grade.

The Three Weighted Scoring Categories

When no hard cap exists, the algorithm evaluates three independent categories with specific weightings:

Protocol Support (30% Weight)

The script inspects the best and worst supported TLS/SSL protocols using the has_server_protocol check (lines 24176–24202). Each protocol maps to a baseline score:

  • TLS 1.2 or 1.3: 100 points
  • TLS 1.1: 95 points
  • TLS 1.0: 90 points
  • SSL 3.0: 80 points
  • SSL 2.0: 0 points

The average of the best and worst protocol scores becomes c1_score, which is multiplied by 30% to produce c1_wscore.

Key Exchange (30% Weight)

The rating system uses the pre‑computed KEY_EXCH_SCORE variable (lines 24111–24124) as c2_score. This score triggers automatic grade caps:

  • ≤ 40 points: Sets an F cap
  • ≤ 80 points: Sets a B cap

The weighted contribution is c2_wscore = c2_score × 30%.

Cipher Strength (40% Weight)

This category analyzes the bit‑size of the strongest (CIPH_STR_BEST) and weakest (CIPH_STR_WORST) ciphers offered by the server (lines 24226–24253):

Best cipher scoring:

  • ≥ 256 bits: 100 points
  • ≥ 128 bits: 80 points
  • ≥ 0 bits: 20 points
  • Else: 0 points

Worst cipher scoring:

  • 0–127 bits: 20 points
  • 128–255 bits: 80 points
  • ≥ 256 bits: 100 points
  • Else: 0 points

The average yields c3_score, weighted at 40% for c3_wscore.

Calculating the Final Grade

Score Aggregation

The script sums the three weighted contributions at lines 24266–24271:

final_score = c1_wscore + c2_wscore + c3_wscore

If any category scored 0, the final score is forced to 0 regardless of other values.

Grade Mapping Thresholds

The pre‑cap grade derives from the final score using these thresholds (lines 24276–24289):

Final Score Grade
≥ 80 A
≥ 65 B
≥ 50 C
≥ 35 D
≥ 20 E
< 20 F

Grade Cap Application

At lines 24291–24296, the script applies the lowest grade between the calculated pre‑cap grade and any existing GRADE_CAP:

  • If the pre‑cap grade is A with no warnings and no caps exist, the output is A+
  • If the pre‑cap grade is A but warnings exist, the output is A-
  • Any active cap (F, T, or M) overrides higher grades

The final scores, grade, cap reasons, and warnings are written to JSON output via fileout calls (lines 24260–24274, 24300–24304).

What Each Letter Grade Means

The testssl.sh rating system uses the following interpretations based on the SSL Labs specification:

  • A / A+: Strong configuration with modern protocols (TLS 1.2/1.3), robust key exchange, and high‑strength ciphers. A+ indicates zero warnings.
  • B: Minor weaknesses such as missing TLS 1.3 or marginal key‑exchange parameters triggering a B cap.
  • C: Noticeable deficiencies including lack of TLS 1.2 support or equivalent issues.
  • D: Significant protocol or cipher problems that reduce security margins substantially.
  • E: Very weak configuration with multiple low‑strength ciphers or outdated protocols.
  • F: Fatal security flaws including SSL v2/v3 support, Heartbleed vulnerability, or key‑exchange scores ≤ 40.
  • T: Trust issue—typically indicates STARTTLS downgrade susceptibility, certificate chain problems, or revocation status.
  • M: Name mismatch where the certificate subject does not match the scanned domain.

Using the Rating System in Practice

Run a Full Scan with Rating Output

By default, testssl.sh includes the rating in its standard output:

./testssl.sh https://example.com

Typical output format:

 Rating (experimental) 
  Rating specs (not complete)  SSL Labs's 'SSL Server Rating Guide' (version 2009r from 2025-05-16)
  Protocol Support (weighted)  95 (28)
  Key Exchange (weighted)      80 (24)
  Cipher Strength (weighted)   90 (36)
  Final Score                  88
  Overall Grade                A

Isolate Only the Rating Calculation

To skip all other checks and calculate only the grade:

./testssl.sh --rating-only https://example.com

Disable Rating Completely

For scans where the grading system is not required:

./testssl.sh --disable-rating https://example.com

Export Rating Data for CI Pipelines

Generate machine‑readable JSON output containing detailed scoring:

./testssl.sh -U --jsonfileout rating.json https://example.com

The resulting rating.json includes these fields:

{
  "overall_grade": "A",
  "final_score": 88,
  "protocol_support_score": 95,
  "key_exchange_score": 80,
  "cipher_strength_score": 90,
  "rating_cap_reasons": [],
  "rating_warnings": []
}

Summary

  • The testssl.sh rating system implements the SSL Labs SSL Server Rating Guide (version 2009r) through the run_rating() function in testssl.sh.
  • Three weighted categories determine the score: Protocol Support (30%), Key Exchange (30%), and Cipher Strength (40%).
  • Grade caps (F, T, M) immediately limit results based on critical vulnerabilities, trust issues, or STARTTLS usage.
  • Final grades map to A+ through F based on score thresholds, with A+ reserved for perfect A‑grade scores with zero warnings.
  • The system is experimental and intended for comparative benchmarking rather than formal security certification.

Frequently Asked Questions

How does testssl.sh calculate the difference between an A+ and A- grade?

According to the source code at lines 24291–24296, an A+ requires a pre‑cap grade of A with no warnings and no active caps. If warnings exist (such as minor protocol deprecations) or any cap is present, the grade becomes A- instead.

Why does my server get an automatic F grade even with strong ciphers?

The rating system applies hard caps that override calculated scores. If the scan detects SSL v2/v3 support, Heartbleed, or a key‑exchange score ≤ 40, the GRADE_CAP variable sets an F at lines 24153–24166, forcing the final output regardless of other category scores.

What does the "T" cap mean in testssl.sh ratings?

The T cap indicates a trust or transport‑layer issue. The script automatically applies this cap (lines 24131–24136) when scanning STARTTLS services because they are considered downgrade‑prone. It also appears for certificate chain validation failures or revocation status problems.

Can I rely on the testssl.sh rating for compliance reporting?

No. The documentation and source code explicitly label the rating system as experimental. While it follows the SSL Labs specification, it is designed for quick comparative assessments and diagnostics rather than formal security certification or compliance auditing.

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 →