NextPDF Gotenberg: segurança e operação
Em resumo
Seção intitulada “Em resumo”Esta ponte envia documentos da aplicação para um serviço externo pela rede. Isso faz dela, ao mesmo tempo, uma superfície de requisições do lado do servidor e uma superfície de segurança de transporte. O pacote implementa controles específicos e verificáveis para as duas. Ele não protege todo o sistema por si só. Esses controles só funcionam quando você implanta e opera o Gotenberg com as proteções correspondentes. Esta página explica os controles implementados pelo pacote e as responsabilidades operacionais que os complementam.
Nada aqui é garantia. Cada controle é um comportamento definido, coberto por testes e com limites declarados.
As duas camadas de política
Seção intitulada “As duas camadas de política”A ponte aplica duas políticas de segurança distintas em camadas diferentes:
- Política de transporte (
GotenbergSecurityPolicy) — imposição do esquema de URL, triagem de server-side request forgery (SSRF), defesa contra rebinding de Domain Name System (DNS), limites de tamanho da entrada e triagem de nomes de arquivo. Esta é a camada documentada em detalhes a seguir. - Política de análise de HTML — uma política de conteúdo na camada de análise, que adota por padrão a política padrão do core do NextPDF e é executada antes de o conteúdo chegar a um renderizador. Ela complementa a política de transporte, mas continua independente dela. Esta página trata da política de transporte.
Triagem de server-side request forgery (SSRF)
Seção intitulada “Triagem de server-side request forgery (SSRF)”A ponte faz a triagem da URL de API configurada antes que qualquer byte saia do processo. O controle é composto por três partes.
Imposição do esquema. Apenas https é aceito (sem distinção entre maiúsculas e minúsculas). Uma URL http:// simples é rejeitada. Portanto, o Transport Layer Security (TLS) é obrigatório em toda conversão e na sondagem de integridade.
Triagem de endereços. Se o host for um IP literal, a ponte o rejeita quando ele estiver em uma faixa privada ou reservada. Se o host for um nome, a ponte o resolve para todos os seus registros A e AAAA e rejeita a requisição se qualquer endereço resolvido for privado ou reservado. Resolver o conjunto completo de registros, em vez de um único endereço, é o controle que impede um atacante de esconder um endereço privado atrás de um nome que também retorna um endereço público. Isso segue a abordagem das orientações de prevenção de SSRF da OWASP: obter todos os endereços IP por trás do nome de domínio (registros A e AAAA, para IPv4 e IPv6) e validar cada um deles contra uma allowlist (OWASP Cheat Sheet Series, prevenção de SSRF, defesa na camada de aplicação; fixado no sidecar de retrieval-augmented generation (RAG) da página).
Reverificação time-of-check/time-of-use (TOCTOU). A ponte resolve novamente e compara, imediatamente antes da requisição, o conjunto de endereços capturado durante a validação. Se um novo endereço aparecer, a requisição é abortada com um erro de rebinding de DNS. Isso fecha a janela entre validação e conexão que, de outra forma, um ataque de rebinding exploraria.
Quando a ponte usa seu transporte com pinning baseado em cURL, o conjunto de endereços validado é vinculado à conexão com CURLOPT_RESOLVE, de modo que o kernel se conecta ao endereço verificado, e não ao endereço que uma nova consulta de DNS no momento da conexão poderia retornar. O seguimento de redirecionamentos está desativado nesse transporte (CURLOPT_FOLLOWLOCATION desligado, CURLOPT_MAXREDIRS zero), de modo que um 3xx não pode enviar silenciosamente a requisição para um host não verificado. Em vez disso, a camada de política recebe a resposta.
Consequência operacional. A proteção contra SSRF rejeita endereços privados e reservados por design. Se o Gotenberg roda em uma rede privada, você não pode apontar a ponte para o endereço privado dele. Exponha-o por meio de um endereço aceito pela proteção e proteja esse caminho com segmentação de rede e autenticação, conforme descrito na seção de implantação abaixo.
Segurança de transporte e pinning de chave pública
Seção intitulada “Segurança de transporte e pinning de chave pública”A verificação de peer e de host do TLS está sempre ativada no transporte com pinning baseado em cURL (CURLOPT_SSL_VERIFYPEER true, CURLOPT_SSL_VERIFYHOST 2). Além da validação padrão da cadeia, a ponte oferece suporte a pinning de SubjectPublicKeyInfo (SPKI).
Cada pin é um hash SHA-256 do SubjectPublicKeyInfo do servidor, expresso como sha256/<base64>. A ponte aceita um certificado quando o hash do seu SPKI corresponde a qualquer pin do conjunto combinado de primários e backups. Esse modelo de pin de backup segue a RFC 7469 §4.3, que identifica um pin de backup — uma impressão digital de um par de chaves secundário e ainda não implantado — como o caminho de recuperação primário para uma falha inadvertida de validação de pin, e a §2.5, que exige que o conjunto de pins inclua ao menos um pin não presente na cadeia de certificados atual (RFC 7469 §4.3 e §2.5; fixado no sidecar de RAG da página). O código da ponte declara a RFC 7469 §2.1 e §2.6 para a semântica de ao-menos-um-pin-de-backup e de interseção do conjunto combinado. O pinning é opcional: sem pins configurados, aplica-se a validação padrão da cadeia, e o pinning não é imposto.
Um pin que não possa ser analisado corretamente gera um erro de configuração antes de qualquer requisição. Um certificado ativo cujo SPKI não corresponda a nenhum pin configurado faz o transporte reprovar a requisição — por design.
Procedimento de rotação de pins
Seção intitulada “Procedimento de rotação de pins”Uma rotação incorreta deixa a ponte sem acesso ao serviço. Faça a rotação sem indisponibilidade:
- Antes de trocar a chave do servidor, gere o pin de SPKI para a nova chave e adicione-o à lista de pins de backup. Implante essa configuração. A ponte agora aceita tanto a chave atual quanto a futura.
- Faça a transição do certificado ou da chave do servidor para usar a nova chave.
- Confirme que as conversões continuam funcionando (a nova chave agora corresponde ao pin de backup).
- Mova o novo pin da lista de backup para a lista primária e remova o pin da chave aposentada. Implante.
- Gere e prepare o pin para a próxima rotação como o novo backup, de modo que o conjunto sempre tenha um backup utilizável.
Manter a lista de backup separada da lista primária permite preparar e validar o próximo pin sem alterar o que está ativo.
Autenticação
Seção intitulada “Autenticação”Quando apiKey não está vazio, a ponte o envia como um cabeçalho Authorization: Bearer na requisição de conversão. O campo é marcado com #[\SensitiveParameter] para que o valor seja ocultado dos stack traces. A ponte não carrega o segredo por você; forneça-o a partir de um gerenciador de segredos no início do processo e nunca o coloque em commit. O token não é gravado no log de requisições — a entrada de depuração registrada contém apenas a URL, o nome do arquivo, o formato e o tamanho do conteúdo.
Limite de confiança da resposta
Seção intitulada “Limite de confiança da resposta”Uma resposta só é aceita quando o status é 200, o Content-Type contém application/pdf e o corpo começa com a assinatura %PDF. A verificação da assinatura de bytes importa porque um tipo de conteúdo declarado, sozinho, não prova o que os bytes são. O padrão WHATWG MIME Sniffing formaliza o mesmo raciocínio em seu algoritmo de sniffing de tipo MIME, que deriva um tipo computado a partir da correspondência dos padrões dos bytes iniciais, e não do tipo fornecido. As orientações de upload de arquivos da OWASP declaram o princípio de aplicação correspondente: valide o tipo do arquivo e não confie no cabeçalho Content-Type declarado, porque ele pode ser falsificado (WHATWG MIME Sniffing §6.2.3; OWASP Cheat Sheet Series, validação de upload de arquivos; ambos fixados no sidecar de RAG da página). A ponte aplica a verificação equivalente de forma defensiva no lado de entrada: uma divergência gera uma exceção tipada, e os bytes nunca são retornados como resultado.
Esse limite também é o motivo pelo qual o contrato PSR-18 importa aqui. Um cliente PSR-18 lança uma exceção apenas quando não consegue enviar a requisição ou não consegue analisar a resposta em um objeto PSR-7 — ele não lança exceção por um código de status de erro. Uma resposta 4xx/5xx bem formada é retornada normalmente ao chamador (PSR-18, “Exceptions”; fixado no sidecar de RAG da página). Por isso, a ponte inspeciona o status, o tipo e a assinatura por conta própria, em vez de presumir que uma resposta retornada foi bem-sucedida. A semântica HTTP para uma violação da restrição de content-type — uma rejeição 415 (Unsupported Media Type), em que um servidor recusa conteúdo em um formato não suportado — é o modelo que a verificação de entrada espelha (RFC 9110 §15.5.16; fixado no sidecar de RAG da página).
Limites de recursos
Seção intitulada “Limites de recursos”A ponte tem um limite de recurso em processo: maxFileSize (padrão 52,428,800 bytes = 50 MiB). Ele é imposto antes da requisição, de modo que uma entrada grande demais nunca chega ao serviço. Não há limite de concorrência, limite de taxa nem limite de tamanho de saída embutidos na ponte. Essas são responsabilidades da implantação e do chamador (consulte /integrations/gotenberg/production-usage/). Defina maxFileSize com o menor valor que os documentos reais exigirem — um limite mais restrito é um controle de negação de serviço mais barato.
Implantando e protegendo o serviço Gotenberg
Seção intitulada “Implantando e protegendo o serviço Gotenberg”A ponte é tão segura quanto o serviço que ela chama. Você opera esse serviço; as responsabilidades abaixo complementam os controles acima.
- Encerre o TLS na frente do Gotenberg. O contêiner do Gotenberg fala HTTP simples por padrão. A ponte exige HTTPS, então coloque o Gotenberg atrás de um reverse proxy, ingress ou service mesh que faça o encerramento do TLS e aponte a ponte para o endpoint HTTPS. Fixe o SPKI do proxy se você habilitar o pinning.
- Não exponha o Gotenberg publicamente. Ele faz conversão de documentos com motores da classe LibreOffice e Chromium, e não é um serviço voltado para a internet. Restrinja o ingresso aos hosts da aplicação que o chamam, usando política de rede ou regras de firewall.
- Exija autenticação no caminho. A ponte envia um bearer token quando configurada; imponha-o (ou TLS mútuo) no proxy para que uma requisição não autenticada não consiga chegar ao motor de conversão.
- Fixe uma versão específica do serviço. A ponte assume exatamente dois caminhos de serviço —
/forms/libreoffice/converte/health. Fixe a imagem do Gotenberg em uma tag de patch específica, verifique esses dois caminhos na versão que você implanta e verifique novamente a cada atualização. - Dimensione deliberadamente a capacidade de conversão. Cada conversão ocupa um worker durante a duração da requisição. Dimensione a implantação do Gotenberg para a taxa máxima de conversões simultâneas e limite as conversões em andamento no lado do chamador para corresponder a ela. A capacidade é uma propriedade da implantação, não deste pacote.
- Trate as entradas de conversão como não confiáveis. Os documentos enviados para conversão são processados por motores complexos. Restrinja
maxFileSize, isole a implantação do Gotenberg (segmento de rede próprio, egress mínimo, sem acesso a serviços internos) e mantenha o motor com patches aplicados.
O que este pacote não afirma
Seção intitulada “O que este pacote não afirma”- Ele não é “seguro por padrão”: os controles são reais, mas dependem de implantação e configuração corretas.
- Ele não torna a conversão “à prova de adulteração” nem a saída “certificada”. Ele valida o transporte e o formato da resposta; não atesta o conteúdo do documento.
- Ele não oferece assinatura, carimbo de tempo nem validação de longo prazo. Essas são questões de pós-processamento. O suporte a PAdES da edição Pro é somente o baseline B-B e não inclui B-T, B-LT nem B-LTA; nada nesta ponte implica capacidade de carimbo de tempo ou de LTV.
- Ele não oferece suporte a “todos os arquivos do Office”. Ele oferece suporte aos seis formatos enumerados e rejeita todo o restante antes de qualquer requisição.
Consulte também
Seção intitulada “Consulte também”- /integrations/gotenberg/configuration/ — regras de seleção de transporte e o modelo completo de pins.
- /integrations/gotenberg/production-usage/ — novas tentativas, timeouts, concorrência e observabilidade.
- /integrations/gotenberg/troubleshooting/ — cada exceção de segurança e seu gatilho.
- /integrations/gotenberg/overview/ — o fluxo de conversão e o modelo de dependências.