Understanding the Limitations of Wildcard Certificates in mkcert
Wildcard certificates in mkcert are limited to single-level DNS labels and trigger warnings for second-level patterns, while asterisks in filenames are automatically sanitized to _wildcard to ensure filesystem compatibility.
Wildcard certificates in mkcert provide convenient TLS coverage for subdomains, but they inherit strict constraints from the X.509 standard. When using FiloSottile/mkcert to generate local development certificates, understanding these limitations prevents subdomain mismatch errors and browser compatibility issues.
How Wildcard Certificates Work in mkcert
mkcert generates X.509-compliant certificates that follow standard wildcard semantics. The tool validates hostnames and issues warnings based on the printHosts function in cert.go, ensuring users understand the constraints before deploying certificates to local trust stores.
Key Limitations of Wildcard Certificates in mkcert
One-Level Depth Restriction
The X.509 standard permits wildcards to match exactly one DNS label. In cert.go (lines 58-62), mkcert explicitly reminds users that *.example.com matches foo.example.com but does not match a.b.example.com:
"Reminder: X.509 wildcards only go one level deep, so this won't match a.b.*"
This restriction is fundamental to the certificate structure and cannot be bypassed through mkcert configuration.
Second-Level Wildcard Compatibility Issues
While mkcert accepts second-level wildcard patterns such as *.*.example.com or *.12345 via the CLI, most browsers reject these certificates as invalid. The printHosts function in cert.go (lines 52-55) detects these patterns and issues a warning:
"Warning: many browsers don't support second-level wildcards like
*.*.example.com"
Generating these certificates may result in TLS handshake failures in Chrome, Firefox, and Safari despite the certificate being technically valid according to X.509 specifications.
Filename Sanitization Constraints
Because asterisks (*) are invalid characters in most filesystems, mkcert sanitizes output filenames by replacing * with _wildcard. The fileNames function in cert.go (lines 76-80) implements this transformation:
defaultName = strings.Replace(defaultName, "*", "_wildcard", -1)
This substitution affects only the output filename (e.g., _wildcard.example.com+1.pem) and does not alter the certificate's Subject Alternative Name (SAN) entries. Users must reference the sanitized filenames when configuring web servers.
Practical Examples and Warnings
Generating a Standard One-Level Wildcard
mkcert "*.example.com"
Output:
Created a new certificate valid for the following names 📜
- "*.example.com"
The certificate is at "./_wildcard.example.com+1.pem" ✅
Attempting a Second-Level Wildcard (Triggers Warning)
mkcert "*.*.example.com"
Output:
Created a new certificate valid for the following names 📜
- "*.*.example.com"
Warning: many browsers don't support second-level wildcards like "*.*.example.com" ⚠️
Reminder: X.509 wildcards only go one level deep, so this won't match a.b.* ℹ️
Using the Certificate in a Node.js Server
const https = require('https');
const fs = require('fs');
https.createServer({
key: fs.readFileSync('_wildcard.example.com-key.pem'),
cert: fs.readFileSync('_wildcard.example.com+1.pem')
}, (req, res) => {
res.writeHead(200);
res.end('Hello Secure World\n');
}).listen(443);
Summary
- Single-level restriction: Wildcards in mkcert match only one DNS label (e.g.,
*.example.comcoversfoo.example.combut nota.b.example.com), as enforced by X.509 standards and reminded incert.go. - Browser compatibility warnings: Second-level wildcards like
*.*.example.comgenerate certificates that most browsers reject, triggering explicit warnings from theprintHostsfunction. - Filename sanitization: Asterisks are converted to
_wildcardin output filenames via thefileNamesfunction incert.goto ensure cross-platform filesystem compatibility without affecting certificate SAN entries.
Frequently Asked Questions
Can mkcert generate wildcards that match multiple subdomain levels?
No. mkcert follows the X.509 standard, which restricts wildcards to exactly one DNS label. A certificate for *.example.com will match foo.example.com but will not match a.b.example.com. The tool explicitly prints a reminder about this limitation when generating wildcard certificates.
Why does mkcert rename my wildcard certificate files to use "_wildcard"?
Filesystems do not allow asterisks (*) in filenames. The fileNames function in cert.go sanitizes the default output name by replacing * with _wildcard using strings.Replace. This affects only the filename (e.g., _wildcard.example.com+1.pem) and does not modify the certificate's internal DNS names.
Are second-level wildcards like ..example.com valid in mkcert?
While mkcert will generate a certificate for *.*.example.com and the CLI accepts the pattern, the resulting certificate is not widely supported. The printHosts function in cert.go issues a warning that many browsers reject second-level wildcards. These certificates may cause TLS handshake failures in Chrome, Firefox, and Safari.
Does mkcert support wildcard certificates for IP addresses?
No. Wildcard patterns such as *.192.168.1.1 are not valid because wildcards apply only to DNS names (domain labels), not to IP addresses. mkcert validates hostnames according to X.509 rules and will not generate certificates with wildcard patterns for IP addresses.
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 →