Many developers assume a wildcard SSL certificate for *.example.com
automatically includes coverage for the root domain example.com
. While some Certificate Authorities (CAs) may include this by default, RFC 6125 specifically states that wildcard certificates only cover one level of subdomains unless explicitly specified otherwise.
// Example of proper SAN configuration in OpenSSL
openssl req -new -newkey rsa:2048 -nodes -keyout example.key -out example.csr \
-subj "/CN=*.example.com" \
-reqexts SAN \
-config <(cat /etc/ssl/openssl.cnf \
<(printf "[SAN]\nsubjectAltName=DNS:*.example.com,DNS:example.com"))
Modern browsers follow strict validation rules based on RFC 2818 and RFC 6125. When encountering a wildcard certificate:
- Chrome 93+ requires exact SAN matches
- Firefox 91+ follows the "Public Suffix List" rules
- Safari 15 enforces strict wildcard validation
Let's examine a properly configured certificate using OpenSSL:
openssl x509 -in certificate.crt -text -noout
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:*.example.com, DNS:example.com
Compare this to the problematic Comodo certificate you received:
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:*.example.com
Different CAs handle this differently:
CA | Includes Root Domain by Default | Requires Special Request |
---|---|---|
DigiCert | Yes | No |
Comodo/Sectigo | No | Must specify during order |
Let's Encrypt | No | Must use separate -d parameters |
For developers needing both coverage:
Option 1: Explicit SAN Request
# When generating CSR:
openssl req -new -sha256 \
-key domain.key \
-subj "/CN=*.example.com" \
-reqexts SAN \
-config <(printf "[req]\ndistinguished_name=req_distinguished_name\n[SAN]\nsubjectAltName=DNS:example.com,DNS:*.example.com") \
-out domain.csr
Option 2: ACME Clients (Let's Encrypt)
certbot certonly --manual --preferred-challenges=dns \
-d example.com \
-d *.example.com \
--server https://acme-v02.api.letsencrypt.org/directory
To programmatically verify certificate coverage:
# Python example
import ssl
import socket
from OpenSSL import SSL
def check_cert_coverage(hostname):
cert = ssl.get_server_certificate((hostname, 443))
x509 = SSL.load_certificate(SSL.FILETYPE_PEM, cert)
san = x509.get_extension(2).__str__()
return 'DNS:'+hostname in san
The technical reality is clear: while some CAs may include root domain coverage as a courtesy, RFC-compliant implementations require explicit SAN entries for both wildcard and root domains to guarantee full coverage across all browsers and clients.
Many developers assume a wildcard certificate for *.example.com
automatically secures both subdomains and the root domain. While Comodo claims this should work, real-world implementation often requires explicit SAN entries. Let's examine why.
A properly configured wildcard certificate should include:
Common Name: *.example.com
Subject Alternative Names:
DNS:*.example.com
DNS:example.com
When missing the root domain in SANs, browsers like Chrome will flag the root domain as insecure while accepting sub.example.com
.
Here's how to properly configure multiple domains with a wildcard cert:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/wildcard.crt;
ssl_certificate_key /path/to/wildcard.key;
# ... other config
}
server {
listen 443 ssl;
server_name *.example.com;
ssl_certificate /path/to/wildcard.crt;
ssl_certificate_key /path/to/wildcard.key;
# ... other config
}
When generating CSR with SANs:
openssl req -new -newkey rsa:2048 -nodes -keyout wildcard.key \
-out wildcard.csr -config san.cnf
Sample san.cnf:
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
countryName = Country
stateOrProvinceName = State
localityName = City
organizationName = Organization
commonName = *.example.com
[v3_req]
subjectAltName = @alt_names
[alt_names]
DNS.1 = *.example.com
DNS.2 = example.com
Check your certificate's SANs with:
openssl x509 -in certificate.crt -text -noout | grep -A 1 "Subject Alternative Name"
For web-based verification, use SSL Labs' tester to confirm coverage.
Different CAs handle wildcards differently:
- DigiCert: Includes root domain automatically
- Let's Encrypt: Requires separate certificate
- Comodo: Mixed reports (case-dependent)
To guarantee coverage for both root and subdomains:
- Always request explicit SAN inclusion during CSR generation
- Verify certificate contents before deployment
- Consider multi-domain certificates if using non-wildcard subdomains
- Test all domain variations before production rollout