SSL Certificate Checker
A skill that teaches an LLM agent how to inspect and evaluate SSL/TLS certificates on remote hosts using openssl s_client.
Purpose
Check the SSL/TLS certificate of any remote host and produce a clear, actionable report covering: certificate validity, expiry, issuer, subject, Subject Alternative Names (SANs), and chain of trust status.
Prerequisites
- •
opensslmust be available on the system PATH (ships with macOS and most Linux distributions) - •Network access to the target host on the specified port (default: 443)
Usage
When the user asks you to check an SSL certificate, follow the steps below. The user may provide:
- •A hostname (e.g.,
example.com) - •A hostname with port (e.g.,
example.com:8443) - •A URL (e.g.,
https://example.com/some/path) -- extract just the hostname
If a URL is provided, extract the hostname. If no port is specified, default to 443.
Step 1: Fetch the Certificate
Run the following command to connect to the host and retrieve the full certificate and chain:
echo | openssl s_client -connect HOST:PORT -servername HOST 2>/dev/null
Important flags:
- •
-servername HOSTenables SNI (Server Name Indication), which is required for hosts that serve multiple certificates on the same IP address. Without this, you may get the wrong certificate or a connection failure. - •
echo |sends an empty input so that openssl exits cleanly after the handshake instead of waiting for interactive input. - •
2>/dev/nullsuppresses stderr diagnostic output (connection info, verification codes) so you get clean certificate data on stdout.
Capture the full output into a variable or temp file. You will parse multiple sections from it.
Step 2: Extract and Decode the Certificate
From the output of Step 1, extract the PEM-encoded certificate (the block between -----BEGIN CERTIFICATE----- and -----END CERTIFICATE-----, inclusive) and decode it:
echo | openssl s_client -connect HOST:PORT -servername HOST 2>/dev/null | \ openssl x509 -noout -text -dates -issuer -subject -ext subjectAltName
This single pipeline fetches the certificate and decodes it in one pass. The flags:
- •
-nooutsuppresses printing the raw PEM block - •
-textprints the full human-readable certificate details - •
-datesprintsnotBeforeandnotAfteron their own lines (easy to parse) - •
-issuerprints the issuer distinguished name - •
-subjectprints the subject distinguished name - •
-ext subjectAltNameprints the SAN extension entries
Step 3: Check Days Until Expiry
To get a machine-readable check of whether the certificate expires within N days:
echo | openssl s_client -connect HOST:PORT -servername HOST 2>/dev/null | \ openssl x509 -noout -checkend SECONDS
Where SECONDS is the number of seconds from now. Common values:
- •0 = is it expired right now?
- •2592000 = expires within 30 days?
- •604800 = expires within 7 days?
The exit code tells you the result:
- •Exit code 0: certificate will NOT expire within that period (good)
- •Exit code 1: certificate WILL expire within that period (warning/critical)
To calculate exact days remaining, extract notAfter and compute:
EXPIRY_DATE=$(echo | openssl s_client -connect HOST:PORT -servername HOST 2>/dev/null | \ openssl x509 -noout -enddate | cut -d= -f2) EXPIRY_EPOCH=$(date -j -f "%b %d %H:%M:%S %Y %Z" "$EXPIRY_DATE" "+%s" 2>/dev/null || \ date -d "$EXPIRY_DATE" "+%s" 2>/dev/null) NOW_EPOCH=$(date "+%s") DAYS_LEFT=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 )) echo "$DAYS_LEFT days until expiry"
Note: The date command syntax differs between macOS (date -j -f) and GNU/Linux (date -d). The command above tries macOS first, then falls back to Linux.
Step 4: Verify the Chain of Trust
To check whether the certificate chain is valid and trusted by the system's CA bundle:
echo | openssl s_client -connect HOST:PORT -servername HOST 2>&1 | head -20
Look for the Verify return code: line in the output. Key values:
- •
Verify return code: 0 (ok)-- chain is valid and trusted - •
Verify return code: 10 (certificate has expired)-- certificate or a chain certificate has expired - •
Verify return code: 18 (self-signed certificate)-- the leaf certificate is self-signed - •
Verify return code: 19 (self-signed certificate in certificate chain)-- an intermediate or root in the chain is self-signed and not in the trust store - •
Verify return code: 20 (unable to get local issuer certificate)-- the chain is incomplete; a required intermediate or root CA is missing - •
Verify return code: 21 (unable to verify the first certificate)-- similar to 20; the issuer of the leaf certificate is not available
Also note the depth=N lines in the certificate chain section of the output. Each line represents one certificate in the chain from leaf (depth 0) to root.
Step 5: Produce the Report
Compile findings into a structured report with these sections:
Report Format
SSL Certificate Report: HOST:PORT ==================================== Subject: CN=example.com, O=Example Inc, ... Issuer: CN=R11, O=Let's Encrypt, C=US Serial: 0A:1B:2C:... Valid From: Jan 1 00:00:00 2026 GMT Valid Until: Apr 1 00:00:00 2026 GMT Days Left: 46 SANs: example.com, www.example.com, api.example.com Chain Status: Valid (Verify return code: 0 (ok)) Chain Depth: 3 (leaf -> intermediate -> root) Overall: PASS | WARN | FAIL
Decision Logic
- •PASS: Chain is valid (code 0), certificate is not expired, more than 30 days until expiry
- •WARN: Chain is valid but certificate expires within 30 days, OR minor issues detected (e.g., weak signature algorithm)
- •FAIL: Certificate is expired, chain verification failed, self-signed (unless the user is explicitly expecting self-signed), connection refused, or hostname mismatch
Handling Edge Cases
Connection Failure
If openssl s_client returns an error or cannot connect:
SSL Certificate Report: HOST:PORT
====================================
Status: FAIL
Error: Connection failed -- unable to reach HOST on port PORT.
Possible causes: host is down, port is blocked by firewall,
or the service does not support TLS on this port.
Verify the host is reachable before blaming the certificate:
echo | openssl s_client -connect HOST:PORT -servername HOST 2>&1 | head -5
If you see connect: Connection refused or connect: Operation timed out, the issue is network/service level, not certificate level.
Self-Signed Certificates
Self-signed certificates will show Verify return code: 18 or 19. Report as FAIL by default, but note:
Note: This is a self-signed certificate. This is expected for development/internal environments but should not be used in production. The certificate's integrity can still be evaluated -- only chain trust is absent.
Expired Certificates
If notAfter is in the past or checkend 0 returns exit code 1:
Overall: FAIL Reason: Certificate expired on [DATE] ([N] days ago) Action: Certificate must be renewed immediately.
Hostname Mismatch
If the hostname the user asked about does not appear in the Subject CN or SANs list, flag it:
WARNING: Hostname "HOST" does not appear in the certificate's Subject CN or Subject Alternative Names. This will cause browser and client TLS errors.
STARTTLS Services
For services that use STARTTLS (SMTP, IMAP, FTP, etc.) rather than direct TLS, use the -starttls flag:
echo | openssl s_client -connect HOST:PORT -servername HOST -starttls smtp 2>/dev/null
Supported protocols: smtp, pop3, imap, ftp, xmpp, lmtp, nntp, sieve, ldap.
Common ports and their STARTTLS protocols:
- •Port 25 or 587:
-starttls smtp - •Port 143:
-starttls imap - •Port 110:
-starttls pop3 - •Port 21:
-starttls ftp
Checking Multiple Hosts
If the user provides a list of hosts, check each one sequentially and produce a summary table at the end:
Host Status Days Left Issuer --------------------- ------ --------- ---------------------- example.com:443 PASS 46 Let's Encrypt api.example.com:443 WARN 12 Let's Encrypt old.example.com:443 FAIL expired DigiCert internal.dev:8443 FAIL self-signed (none)
Security Notes
- •This skill only performs read-only inspection of remote certificates. It does not modify any system state, install certificates, or change trust stores.
- •The
openssl s_clientcommand establishes a TLS connection to the target host. This is normal TLS handshake traffic and is not intrusive. - •Do not use this skill to scan hosts you are not authorized to inspect. Certificate checking is generally benign, but respect the user's scope of authorization.
- •If a certificate check reveals security issues (expired cert, weak key, etc.), recommend remediation but do not take automated action on remote systems.