Contracts / Política de segurança
Visão geral
Seção intitulada “Visão geral”O domínio security-policy define três contratos deny-by-default (negar por padrão): CryptoPolicyInterface controla as escolhas de algoritmo e de chave, HtmlSecurityPolicyInterface restringe a superfície de recursos de Hypertext Markup Language (HTML) e ExternalResourcePolicyInterface rege o carregamento de recursos remotos. Como cada um deles é um contrato, você pode fornecer uma política de implantação mais restritiva sem precisar criar um fork.
Instalação
Seção intitulada “Instalação”composer require nextpdf/core:^3Visão conceitual
Seção intitulada “Visão conceitual”CryptoPolicyInterface é o controle de criptografia. O Core o chama antes de qualquer etapa de assinatura, criptografia ou hash. A verificação cobre o hash, o object identifier (OID) da assinatura, a cifra e a força da chave. O contrato também informa o hash mínimo e um nome de política para o log de auditoria. Use-o para aplicar um conjunto de regras como Federal Information Processing Standards (FIPS) 140-3 ou eIDAS. O código de assinatura e de criptografia não muda. Quando nenhuma política é definida, todos os algoritmos são permitidos. Um site regulado deve definir uma política explícita.
HtmlSecurityPolicyInterface atua na camada de parsing do HTML. Ela é executada antes que o conteúdo chegue a qualquer renderizador. A política decide se uma tag, um atributo, uma propriedade de Cascading Style Sheets (CSS) ou um esquema de uniform resource locator (URL) é permitido. Ela também limita o tamanho de entrada e a profundidade de aninhamento. Esse contrato trabalha junto com as políticas de transporte por renderizador (Chrome, Cloudflare, Gotenberg), que definem limites de tamanho e cabeçalhos de Content Security Policy (CSP). A política de HTML reduz a superfície de ataque na camada de parsing. Uma tag removida nunca chega ao layout. Um elemento injetado não consegue alterar a saída. Quando nenhuma política é definida, o padrão permite o conjunto completo de recursos.
ExternalResourcePolicyInterface decide se o pipeline de HTML pode buscar uma fonte, folha de estilo ou imagem externa. Ela também define os limites de cada busca. Sua postura padrão é deny-all (negar tudo). Toda opção permanece desativada até você ativá-la. O contrato segue o princípio do menor privilégio. HTML não confiável pode apontar para uma URL controlada por um invasor. A política controla as buscas de @font-face por esquema, tamanho e contagem de glifos. Ela controla @import por esquema, profundidade e tamanho total. Também controla background-image por uma lista de esquemas e uma allowlist de domínios por correspondência exata. Ela limita o tamanho de data-URI (Uniform Resource Identifier). Ela também controla referências externas de Scalable Vector Graphics (SVG). O contrato afirma que a produção deve sempre negá-las. Essas referências permitem request forgery (falsificação de requisição) e injeção de script. A busca de URL aberta é um caminho para server-side request forgery. O controle de acesso pode ser contornado ao alterar a URL, conforme descrito pelo Open Worldwide Application Security Project (OWASP) Top 10 2025. A obtenção de componentes externos deve se limitar a origens oficiais e transporte seguro.
Superfície da API
Seção intitulada “Superfície da API”| Tipo | Categoria | Membros principais | Estabilidade | Desde |
|---|---|---|---|---|
CryptoPolicyInterface | interface | isHashAlgorithmAllowed(), isSignatureAlgorithmAllowed(), isEncryptionAlgorithmAllowed(), isKeyStrengthAllowed(), getPreferredHashAlgorithm(), getName() | stable | 1.9.0 |
HtmlSecurityPolicyInterface | interface | isTagAllowed(), isAttributeAllowed(), isCssPropertyAllowed(), isUrlSchemeAllowed(), getMaxInputSize(), getMaxNestingDepth(), getName() | stable | 3.1.0 |
ExternalResourcePolicyInterface | interface | isFontFaceAllowed(), getAllowedFontSchemes(), getMaxFontFileSize(), getMaxFontGlyphs(), isImportAllowed(), getMaxImportDepth(), isBackgroundImageAllowed(), getAllowedImageDomains(), getMaxDataUrlSize(), isSvgExternalReferenceAllowed() | stable | 4.0.0 |
ExternalResourcePolicyInterface retorna limites tipados: tamanhos positive-int, profundidade de import int<1, 100> e listas de esquemas e domínios list<non-empty-string>. A implementação padrão nega todos os recursos.
Exemplo de código — Início rápido
Seção intitulada “Exemplo de código — Início rápido”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\HtmlSecurityPolicyInterface;
/** * Decide whether a tag survives the policy. * * @param HtmlSecurityPolicyInterface $policy A core or custom policy. */function tagSurvives(HtmlSecurityPolicyInterface $policy, string $tag): bool{ return $policy->isTagAllowed($tag);}A função depende apenas do contrato. Tanto uma política restritiva quanto a política padrão satisfazem esse contrato.
Exemplo de código — Produção
Seção intitulada “Exemplo de código — Produção”<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\CryptoPolicyInterface;use NextPDF\Contracts\ExternalResourcePolicyInterface;use NextPDF\Contracts\HtmlSecurityPolicyInterface;use Psr\Log\LoggerInterface;
final readonly class UntrustedHtmlGate{ public function __construct( private HtmlSecurityPolicyInterface $htmlPolicy, private ExternalResourcePolicyInterface $resourcePolicy, private CryptoPolicyInterface $cryptoPolicy, private LoggerInterface $logger, ) {}
/** * Reject input that exceeds the configured limits before rendering. * * @param string $html Untrusted HTML markup. */ public function assertAcceptable(string $html): void { $maxInput = $this->htmlPolicy->getMaxInputSize();
if ($maxInput > 0 && \strlen($html) > $maxInput) { $this->logger->warning('HTML rejected: input over limit', [ 'policy' => $this->htmlPolicy->getName(), 'limit' => $maxInput, ]);
throw new \LengthException('HTML input exceeds policy limit.'); }
if ($this->resourcePolicy->isSvgExternalReferenceAllowed()) { $this->logger->error('Unsafe policy: SVG external references enabled.');
throw new \LogicException('SVG external references must be denied in production.'); } }}O gate impõe o limite de entrada e rejeita uma política de recursos insegura antes que o pipeline seja executado. Ele registra o nome da política para auditoria e lança uma exceção específica.
Casos extremos e armadilhas
Seção intitulada “Casos extremos e armadilhas”CryptoPolicyInterfacepermite todos os algoritmos quando nenhuma política é definida. O padrão aberto é uma conveniência de desenvolvimento, não uma postura de produção. Defina uma política explícita em qualquer implantação regulada.HtmlSecurityPolicyInterface::getMaxInputSize()retorna0para ilimitado. Trate0como “sem limite de política”, não como “rejeitar tudo”. Aplique também um limite na camada de transporte.ExternalResourcePolicyInterfaceé deny-all por padrão. Habilitar@font-faceoubackground-imagesem definir uma lista de esquemas abre uma superfície de request forgery; defina a allowlist ao mesmo tempo.- Uma allowlist de domínios vazia em
getAllowedImageDomains()significa que todos os domínios são permitidos quando imagens de fundo estão habilitadas. Uma lista vazia não é uma regra de negação; forneça domínios explícitos. isSvgExternalReferenceAllowed()deve retornarfalseem produção. O contrato documenta isso; uma política que retornatrueé uma constatação, não uma escolha de configuração.
Desempenho
Seção intitulada “Desempenho”Uma verificação de política é uma chamada de predicado: O(1), sem custo proporcional à entrada. A política é consultada por tag, por atributo, por propriedade CSS e por URL durante o parsing. Um documento patológico multiplica a contagem de chamadas, mas cada chamada continua em tempo constante. O performance_budget de 1500 ms de tempo total e 64 MB de pico é dominado pelo parsing e pela renderização, não pela avaliação da política. Os limites de tamanho de entrada e de profundidade de aninhamento delimitam o custo do próprio parser. Uma política restritiva melhora o desempenho no pior caso ao rejeitar um documento grande demais ou profundamente aninhado antes do layout.
Notas de segurança
Seção intitulada “Notas de segurança”Esses contratos formam o perímetro defensivo do mecanismo, portanto o modelo de ameaças é explícito. CryptoPolicyInterface mitiga o downgrade de algoritmo ao bloquear hashes fracos e chaves curtas antes de qualquer operação. HtmlSecurityPolicyInterface mitiga cross-site scripting que afeta a saída em Portable Document Format (PDF) e a injeção de conteúdo ao remover tags, atributos e CSS não permitidos na camada de parsing antes que o renderizador seja executado. ExternalResourcePolicyInterface mitiga server-side request forgery, bombas de descompressão e bombas de tamanho cumulativo ao adotar deny-all como padrão e delimitar cada busca por esquema, tamanho, profundidade e domínio. Os limites de tamanho de entrada, profundidade de aninhamento, glifos de fonte e profundidade de import mitigam o esgotamento de recursos. Como cada política é um contrato, você pode reforçar o perímetro sem criar um fork do mecanismo, e o nome da política é exposto para registro de auditoria. Trate todo o HTML, todas as URLs e todos os bytes de fonte e de imagem como hostis. Esta página está marcada como export_control_class: legal-review-required porque os contratos regem a política de criptografia; a prosa parafraseia todas as fontes normativas e não cita nenhuma.
Conformidade
Seção intitulada “Conformidade”| Afirmação | Padrão | Cláusula | Evidência |
|---|---|---|---|
| O tratamento irrestrito de URL permite que alterações de URL contornem o controle de acesso, o que a política de recursos externos mitiga com padrões deny-all e uma allowlist de domínios por correspondência exata. | OWASP Top 10 2025 | A01 | |
| A obtenção de componentes externos deve se limitar a origens oficiais e transporte seguro, algo que a política suporta por meio de allowlists de esquemas. | OWASP Top 10 2025 | Software supply chain |
Ambos os pontos parafraseiam a orientação do OWASP. A página referencia o material do OWASP por cláusula; o mecanismo não reproduz esse texto.
Contexto comercial
Seção intitulada “Contexto comercial”O Core define e congela os três contratos de política. Ele fornece padrões permissivos para desenvolvimento e padrões restritivos para a política de recursos deny-all. A edição Enterprise fornece um perfil FIPS 140-3 por trás de CryptoPolicyInterface, de modo que uma implantação regulada obtém uma postura de algoritmo validada sem alterar o código de assinatura ou de criptografia. A superfície do contrato é idêntica entre as edições. A diferença está na implementação de política que você injeta.
Veja também
Seção intitulada “Veja também”- Contracts: 41 interfaces públicas (service provider interface, SPI) — visão geral e níveis de estabilidade.
- Contracts / Signing —
CryptoPolicyInterfaceaplicado à assinatura. - Contracts / Document — os pontos de entrada
writeHtml()eimage()que essas políticas controlam. - Security — a superfície de criptografia que a política de criptografia restringe.
- HTML — o pipeline de parsing que as políticas de HTML e de recursos protegem.
- Audit — registro de auditoria do nome da política.