Pular para o conteúdo
ecdsa.com
curl (OpenSSL backend)curl

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

Como corrigir

  1. 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. 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. 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. 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

Ver toda a base de erros de assinatura