Segurança e operações no pacote Laravel do NextPDF
Visão geral
Seção intitulada “Visão geral”O pacote define cabeçalhos de resposta fixos para Portable Document Format (PDF), sanitiza nomes de arquivos de download, valida os caminhos de saída da fila no worker e roteia as chamadas Hypertext Transfer Protocol (HTTP) para a autoridade de carimbo de tempo por meio de um cliente atento a falsificação de requisições. Esta página explica o modelo de ameaças e a configuração de implantação exigida por cada controle.
Instalação
Seção intitulada “Instalação”composer require nextpdf/laravelphp artisan vendor:publish --tag=nextpdf-configVisão conceitual
Seção intitulada “Visão conceitual”O pacote adapta um mecanismo de PDF a um framework web. A requisição HTTP e o transporte da fila definem o limite de confiança. Esses controles abrangem o tratamento de respostas, os payloads de jobs desserializados e o HTTP de saída para uma autoridade de carimbo de tempo.
Superfície da API — modelo de ameaças
Seção intitulada “Superfície da API — modelo de ameaças”| Ativo | Ameaça | Controle neste pacote | Configuração de implantação exigida |
|---|---|---|---|
| Resposta HTTP de PDF | Sniffing de content-type, clickjacking, indexação | Conjunto de cabeçalhos fixos em cada fábrica PdfResponse do pacote | Nenhuma; os cabeçalhos não são configuráveis |
| Nome do arquivo de download | Injeção de cabeçalho, path traversal em Content-Disposition | O sanitizador de nomes de arquivo remove separadores, caracteres de controle e bytes nulos | Nenhuma; o sanitizador sempre é executado |
| Caminho de saída do job de fila | Escrita arbitrária de arquivo via payload serializado adulterado | Caminho validado em handle() no worker | Roteie a saída para um caminho de armazenamento controlado |
| HTTP de saída para a autoridade de carimbo de tempo (TSA) | Server-side request forgery, adulteração de texto puro | Cliente HTTP atento a falsificação de requisições; HTTPS imposto, exceto quando relaxado explicitamente | Mantenha tsa.allow_insecure_http = false; fixe (pin) o Subject Public Key Info (SPKI) |
| Estado compartilhado do worker | Vazamento de estado entre requisições em workers de longa duração | Registro de fontes bloqueado; cache de imagens limitado; documento vinculado à fábrica | Defina preload_fonts; limite a memória no container |
Fortalecimento de respostas
Seção intitulada “Fortalecimento de respostas”Cada fábrica de PdfResponse define um conjunto de cabeçalhos fixos:
Cache-Control: private, max-age=0, must-revalidatePragma: publicX-Content-Type-Options: nosniffX-Frame-Options: DENYContent-Security-Policy: default-src 'none'X-Robots-Tag: noindex, nofollowReferrer-Policy: no-referrer
Esses valores são constantes em PdfResponse. Eles não são configuráveis. A suíte de testes do pacote verifica cada cabeçalho em cada método de fábrica, incluindo as variantes em streaming.
O nome do arquivo de download passa por um sanitizador antes de chegar ao cabeçalho Content-Disposition. O sanitizador remove separadores de caminho, caracteres de controle e bytes nulos e emite um parâmetro filename*= do Request for Comments (RFC) 5987 para nomes não ASCII. Um nome de arquivo vazio se torna document.pdf.
Validação de payload de fila
Seção intitulada “Validação de payload de fila”GeneratePdfJob serializa uma closure no transporte da fila. O worker valida o caminho de saída dentro de handle(), não no momento do dispatch. A validação rejeita:
- bytes nulos no caminho,
- esquemas de stream-wrapper (por exemplo
php://), ..segmentos de path traversal,- qualquer caminho que não termine em
.pdf(sem distinção de maiúsculas e minúsculas).
Cada rejeição lança InvalidArgumentException. A validação é executada quando o worker consome o job. Um payload serializado em um transporte Redis ou de banco de dados pode ser alterado antes de ser lido pelo worker. Roteie o caminho de saída para um diretório de armazenamento controlado; não o derive de uma entrada de requisição não validada.
HTTP de saída para uma autoridade de carimbo de tempo
Seção intitulada “HTTP de saída para uma autoridade de carimbo de tempo”Quando uma autoridade de carimbo de tempo está configurada, o pacote vincula um PHP Standard Recommendation (PSR)-18 Psr\Http\Client\ClientInterface. Um cliente PSR-18 envia uma requisição PSR-7 e retorna uma resposta PSR-7 (PSR-18 §2). O cliente vinculado encapsula um cliente baseado em curl com uma camada atenta a falsificação de requisições. Ele impõe HTTPS, exceto quando tsa.allow_insecure_http for explicitamente true.
A autoridade de carimbo de tempo é um recurso do nível Premium. O pacote Core documentado aqui vincula o cliente HTTP e a integração do cliente de carimbo de tempo; a assinatura em si requer nextpdf/premium. Esta página não documenta o comportamento de baseline das PDF Advanced Electronic Signatures (PAdES) além de B-B; baselines superiores ficam fora do escopo.
Orientação operacional para a autoridade de carimbo de tempo:
- Mantenha
tsa.allow_insecure_httpdefinido comofalseem produção. - Defina
tsa.pinned_public_keyscom os hashes SHA-256 SPKI em base64 do certificado da autoridade de carimbo de tempo (forma do RFC 7469). - Mantenha
tsa.warn_on_key_rotationdefinido comotruepara que um SPKI alterado seja registrado em log antes da expiração do certificado fixado. - Obtenha
tsa.urlapenas de configuração confiável. Se um operador puder defini-la a partir de uma área administrativa, aplique um firewall de egresso ou uma política de DNS para reduzir a exposição à falsificação de requisições.
Registro de logs
Seção intitulada “Registro de logs”Use Psr\Log\LoggerInterface para diagnósticos. Passe contexto estruturado, não strings interpoladas. O PSR-3 deixa o escape de placeholders a cargo da implementação do logger e instrui os chamadores a não escapar previamente os valores de contexto (PSR-3 §1.2). Registre em log a classe da exceção, não a mensagem nem o trace, para reduzir detalhes internos nos logs.
Exemplo de código — Produção
Seção intitulada “Exemplo de código — Produção”<?php
declare(strict_types=1);
// .env — production timestamp-authority hardening// NEXTPDF_TSA_URL=https://tsa.example.test// NEXTPDF_TSA_ALLOW_INSECURE_HTTP=false// NEXTPDF_TSA_WARN_ROTATION=true
return [ 'tsa' => [ 'url' => env('NEXTPDF_TSA_URL'), 'allow_insecure_http' => env('NEXTPDF_TSA_ALLOW_INSECURE_HTTP', false), 'warn_on_key_rotation' => env('NEXTPDF_TSA_WARN_ROTATION', true), 'pinned_public_keys' => [ // base64 SHA-256 SPKI hashes of the TSA certificate ], ],];Casos extremos e pegadinhas
Seção intitulada “Casos extremos e pegadinhas”- O conjunto de cabeçalhos de resposta é fixo. Aplicações que precisam de uma Content Security Policy (CSP) diferente devem pós-processar a resposta depois que a fábrica retorná-la.
- A validação de caminho é executada no worker. Um caminho inválido passa por
dispatch()e falha apenas quando o job é executado. tsa.allow_insecure_http = trueremove a imposição de HTTPS e enfraquece a confiança no carimbo de tempo. Restrinja-o ao desenvolvimento local.- O registro de fontes é bloqueado após o aquecimento; o pacote rejeita, por design, tentativas de registrar uma fonte em tempo de execução em um worker de longa duração.
Desempenho
Seção intitulada “Desempenho”Os controles de segurança usam operações de string e array em tempo constante e não adicionam custo mensurável por requisição. A análise (parsing) de fontes no primeiro uso é o custo operacional dominante; pré-carregue as fontes na inicialização do worker para evitar a latência da primeira requisição.
Notas de segurança
Seção intitulada “Notas de segurança”Esta página é a referência de modelo de ameaças do pacote. O código-fonte impõe esses controles, e a suíte de testes os verifica. A tabela de modelo de ameaças e as etapas da autoridade de carimbo de tempo destacam a configuração de implantação que o operador deve fornecer.
Conformidade
Seção intitulada “Conformidade”| Afirmação | Fonte | Cláusula | reference_id |
|---|---|---|---|
| O cliente PSR-18 envia uma requisição PSR-7 e retorna uma resposta PSR-7 | PSR-18 HTTP Client | §2 | |
| O chamador passa contexto de log estruturado sem escape | PSR-3 Logger | §1.2 |
O pinning de SPKI do RFC 7469 nomeia a forma usada pela chave de configuração tsa.pinned_public_keys. O pacote consome os valores de pin fornecidos pelo operador e não implementa o próprio RFC.
Contexto comercial
Seção intitulada “Contexto comercial”A assinatura PAdES B-B e a integração com a autoridade de carimbo de tempo requerem nextpdf/premium. Esse recurso opcional de Enterprise não exige nenhuma alteração de código no pacote Core documentado aqui. Consulte https://nextpdf.dev/get-license/?intent=laravel-signing.
Veja também
Seção intitulada “Veja também”- /integrations/laravel/configuration/ — cada chave de TSA, assinatura e fila
- /integrations/laravel/production-usage/ — padrões de injeção de dependência (DI) e de tratamento de erros
- /integrations/laravel/troubleshooting/ — por que as verificações de caminho rejeitam a entrada
- /integrations/laravel/boot-and-discovery/ — tempos de vida de binding em workers de longa duração