Mensagem de erro
curl: (60) SSL certificate problem: self-signed certificate
Também aparece como
- curl: (60) SSL certificate problem: self signed certificate
- curl: (60) SSL certificate OpenSSL verify result: self-signed certificate (18)
O OpenSSL 3.0 e posteriores imprimem “self-signed certificate”; o OpenSSL 1.1.1 imprime “self signed certificate”. Versões mais novas do curl (8.22.0 no nosso teste) formulam assim: “SSL certificate OpenSSL verify result: self-signed certificate (18)”. Não confunda com “self-signed certificate in certificate chain”, em que existe uma cadeia de CAs que termina em uma raiz não confiável.
curl (OpenSSL backend) — CURLE_PEER_FAILED_VERIFICATION, X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT (18)
O que significa
O servidor apresentou um único certificado assinado pela própria chave (emissor igual ao titular), e o curl não tem exatamente esse certificado no trust store. Não há nenhuma CA por trás dele que o curl possa consultar, então a verificação para na profundidade 0. Isso é normal em servidores de desenvolvimento e appliances, e nunca se resolve instalando um intermediário.
Por que acontece
Um servidor de desenvolvimento ou de testes com um certificado gerado
comumServidores HTTPS locais, stacks do docker-compose e fixtures de teste costumam gerar um certificado autoassinado na inicialização (por exemplo, com openssl req -x509). Cada nova geração produz um certificado novo, então uma cópia em que você confiava ontem pode não corresponder ao certificado de hoje.
Um dispositivo ou produto ainda usa o certificado de fábrica
comumRoteadores, dispositivos NAS, impressoras, interfaces iDRAC/iLO e instalações de Proxmox, Jenkins ou Elasticsearch vêm com um certificado autoassinado até que alguém instale um certificado adequado.
Um proxy ou ingress serve o certificado padrão
ocasionalQuando nenhum certificado corresponde ao nome solicitado, o ingress-nginx serve “Kubernetes Ingress Controller Fake Certificate” e o Traefik serve “TRAEFIK DEFAULT CERT”, ambos autoassinados. Nesse caso, o problema real é o roteamento ou o SNI, e não a confiança.
O servidor aponta para o arquivo errado
raraUma configuração que referencia um certificado autoassinado temporário (snakeoil.pem no Debian, localhost.crt de um pacote) em vez do certificado emitido produz este erro mesmo que exista um certificado real no disco.
Como corrigir
- 1.
Confiar exatamente neste certificado, depois de verificá-lo
Para um único endpoint interno, salve o certificado, confirme a impressão digital SHA-256 dele por um canal confiável (o console do dispositivo, o administrador que o criou) e passe-o com --cacert. O curl então aceita esse certificado e nenhum outro nessa chamada.
bash # Fetch the certificate once, compare its fingerprint out of band, then trust exactly that file openssl s_client -connect api.example.com:8443 -servername api.example.com </dev/null 2>/dev/null \ | openssl x509 -out api.example.com.pem openssl x509 -in api.example.com.pem -noout -fingerprint -sha256 curl --cacert api.example.com.pem https://api.example.com:8443/ - 2.
Desenvolvimento: emitir certificados de uma CA local
Uma CA local (mkcert, step-ca ou uma raiz feita à mão) permite confiar uma única vez em uma raiz e emitir certificados para quantos hosts de desenvolvimento forem necessários. Os certificados deixam de ser autoassinados, então o erro desaparece em todo lugar onde a raiz estiver instalada.
bash # mkcert creates a local CA, installs it into the system and browser stores, # and issues certificates signed by it (no longer self-signed) mkcert -install mkcert api.example.test localhost 127.0.0.1 - 3.
Hosts públicos: instalar um certificado de uma CA pública
Tudo o que é acessado por outras pessoas ou por clientes de terceiros deveria apresentar um certificado de uma CA publicamente confiável; clientes ACME como certbot, lego ou Caddy obtêm e renovam esse certificado automaticamente.
bash # Public names: get a certificate from a public CA, e.g. with certbot (ACME) sudo certbot certonly --nginx -d api.example.com - 4.
Diagnóstico temporário: testar o serviço com a verificação desligada
A opção -k faz o curl pular as verificações de certificado, então uma resposta 200 confirma que só falta a confiança. Não a mantenha: um certificado autoassinado aceito sem verificação pode ser trocado pelo de um atacante a qualquer momento, e o curl não perceberia.
bash # Diagnostic only: confirms the service answers when certificate checks are skipped curl -sS -k -o /dev/null -w '%{http_code}\n' https://api.example.com:8443/
Erros relacionados
curl: (60) SSL certificate problem: self-signed certificate in certificate chaincurl (OpenSSL backend)curl: (60) SSL certificate problem: unable to get local issuer certificatecurl (OpenSSL backend)verify error:num=18:self-signed certificateOpenSSL CLI (openssl s_client / openssl verify)code: 'DEPTH_ZERO_SELF_SIGNED_CERT'Node.js tls / https / fetch