Error message
verify error:num=18:self-signed certificate
Also printed as
- verify error:num=18:self signed certificate
- Verify return code: 18 (self-signed certificate)
- error 18 at 0 depth lookup: self-signed certificate
OpenSSL 3.x prints "self-signed", 1.1.1 "self signed". s_client shows "verify error:num=18:…" and "Verify return code: 18 (…)"; openssl verify shows "error 18 at 0 depth lookup: …".
OpenSSL CLI (openssl s_client / openssl verify) — X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
What it means
OpenSSL error 18 (X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT): the certificate at depth 0 is self-signed — its issuer is itself — and it is not in the trusted store. There is no CA above it, so no intermediate or bundle can help; the certificate must be trusted directly or replaced with a CA-issued one.
Why it happens
The server uses a self-signed certificate
commonDevelopment servers, appliances, admin interfaces and freshly installed services often start with a generated certificate.
A default certificate is served for an unknown name
occasionalReverse proxies and ingresses answer names they have no configuration for with a self-signed default; check SNI and routing.
openssl verify run on a root certificate
occasionalRunning openssl verify root.pem without -CAfile root.pem reports error 18 for any self-signed root, even a valid one.
How to fix it
- 1.
Confirm that subject and issuer are identical
If subject equals issuer, the certificate is self-signed; its fingerprint is what you compare with the expected value.
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \ | openssl x509 -noout -subject -issuer -fingerprint -sha256 # subject == issuer: self-signed - 2.
Trust the exact certificate for testing
Using the certificate itself as -CAfile makes OpenSSL accept exactly that certificate. Confirm the fingerprint through a trusted channel first.
bash # Trust this exact certificate for a check (after confirming the fingerprint out of band) echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null | openssl x509 -out api.pem echo | openssl s_client -connect api.example.com:443 -servername api.example.com -CAfile api.pem 2>&1 | grep 'Verify return code' - 3.
Verify a root against itself
A self-signed root only verifies when it is the trust anchor: pass it as -CAfile.
bash # Verifying a root CA certificate itself needs the root as its own trust anchor openssl verify -CAfile root.pem root.pem # root.pem: OK