Contracts / Политика безопасности
Краткий обзор
Заголовок раздела «Краткий обзор»Домен security-policy определяет три контракта с моделью запрета по умолчанию: CryptoPolicyInterface контролирует выбор алгоритмов и ключей, HtmlSecurityPolicyInterface ограничивает набор возможностей Hypertext Markup Language (HTML), а ExternalResourcePolicyInterface управляет загрузкой удалённых ресурсов. Поскольку каждый из них — контракт, вы можете задать более строгую политику развёртывания без форка.
Установка
Заголовок раздела «Установка»composer require nextpdf/core:^3Концептуальный обзор
Заголовок раздела «Концептуальный обзор»CryptoPolicyInterface — криптографический шлюз. Core вызывает его перед любой операцией подписи, шифрования или хеширования. Проверка охватывает хеш, идентификатор объекта подписи (OID), шифр и стойкость ключа. Контракт также сообщает минимальный хеш и имя политики для журнала аудита. Используйте его для применения набора правил, например Federal Information Processing Standards (FIPS) 140-3 или eIDAS. Код подписи и шифрования при этом не меняется. Если политика не задана, разрешены все алгоритмы. В регулируемой среде необходимо задать явную политику.
HtmlSecurityPolicyInterface работает на уровне разбора HTML. Он срабатывает до передачи содержимого в любой модуль отрисовки. Он определяет, разрешены ли тег, атрибут, свойство Cascading Style Sheets (CSS) или схема uniform resource locator (URL). Он также ограничивает размер ввода и глубину вложенности. Он работает совместно с транспортными политиками отдельных модулей отрисовки (Chrome, Cloudflare, Gotenberg), которые задают ограничения размера и заголовки Content Security Policy (CSP). Политика HTML сокращает поверхность атаки на уровне разбора. Исключённый тег никогда не доходит до макета. Внедрённый элемент не может изменить вывод. Если политика не задана, по умолчанию разрешён полный набор возможностей.
ExternalResourcePolicyInterface решает, может ли конвейер HTML загрузить внешний шрифт, таблицу стилей или изображение. Он также задаёт ограничения для каждой загрузки. Его позиция по умолчанию — запрет всего. Все параметры отключены, пока вы их не включите. Контракт следует принципу наименьших привилегий. Недоверенный HTML может ссылаться на URL, подконтрольный злоумышленнику. Загрузки @font-face контролируются по схеме, размеру и количеству глифов. @import контролируется по схеме, глубине и суммарному размеру. background-image контролируется по списку схем и списку разрешённых доменов с точным совпадением. Размер data-URI (Uniform Resource Identifier) ограничивается. Контракт также контролирует внешние ссылки Scalable Vector Graphics (SVG). Контракт указывает, что в production их необходимо всегда запрещать. Они открывают путь к подделке запросов и внедрению скриптов. Неограниченная загрузка по URL — путь к подделке запросов на стороне сервера. Контроль доступа можно обойти изменением URL, как описано в Open Worldwide Application Security Project (OWASP) Top 10 2025. Получение внешних компонентов должно быть ограничено официальными источниками и безопасным транспортом.
Поверхность API
Заголовок раздела «Поверхность API»| Тип | Вид | Основные члены | Стабильность | С версии |
|---|---|---|---|---|
CryptoPolicyInterface | интерфейс | isHashAlgorithmAllowed(), isSignatureAlgorithmAllowed(), isEncryptionAlgorithmAllowed(), isKeyStrengthAllowed(), getPreferredHashAlgorithm(), getName() | стабильно | 1.9.0 |
HtmlSecurityPolicyInterface | интерфейс | isTagAllowed(), isAttributeAllowed(), isCssPropertyAllowed(), isUrlSchemeAllowed(), getMaxInputSize(), getMaxNestingDepth(), getName() | стабильно | 3.1.0 |
ExternalResourcePolicyInterface | интерфейс | isFontFaceAllowed(), getAllowedFontSchemes(), getMaxFontFileSize(), getMaxFontGlyphs(), isImportAllowed(), getMaxImportDepth(), isBackgroundImageAllowed(), getAllowedImageDomains(), getMaxDataUrlSize(), isSvgExternalReferenceAllowed() | стабильно | 4.0.0 |
ExternalResourcePolicyInterface возвращает типизированные ограничения: размеры positive-int, глубину импорта int<1, 100>, а также списки схем и доменов list<non-empty-string>. Реализация по умолчанию запрещает все возможности.
Пример кода — быстрый старт
Заголовок раздела «Пример кода — быстрый старт»<?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);}Функция зависит только от контракта. Контракту удовлетворяют как ограничительная политика, так и политика по умолчанию.
Пример кода — production
Заголовок раздела «Пример кода — production»<?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.'); } }}Шлюз применяет ограничение размера ввода и отклоняет небезопасную политику ресурсов до запуска конвейера. Он записывает имя политики в журнал для аудита и выбрасывает конкретное исключение.
Граничные случаи и подводные камни
Заголовок раздела «Граничные случаи и подводные камни»CryptoPolicyInterfaceразрешает все алгоритмы, если политика не задана. Разрешающее значение по умолчанию — удобство для разработки, а не позиция для production. В любом регулируемом развёртывании задавайте явную политику.HtmlSecurityPolicyInterface::getMaxInputSize()возвращает0при отсутствии ограничения. Трактуйте0как “нет ограничения политики”, а не “отклонить всё”. Дополнительно применяйте ограничение на транспортном уровне.ExternalResourcePolicyInterfaceпо умолчанию запрещает всё. Включение@font-faceилиbackground-imageбез задания списка схем открывает поверхность атаки для подделки запросов; одновременно задавайте список разрешений.- Пустой список разрешённых доменов в
getAllowedImageDomains()означает, что после включения фоновых изображений разрешены все домены. Пустой список не является правилом запрета; указывайте явные домены. isSvgExternalReferenceAllowed()в production должен возвращатьfalse. Контракт документирует это; политика, возвращающаяtrue, — обнаруженная проблема, а не вариант конфигурации.
Производительность
Заголовок раздела «Производительность»Проверка политики — это вызов предиката: O(1), без затрат, пропорциональных размеру ввода. Во время разбора политика опрашивается для каждого тега, каждого атрибута, каждого свойства CSS и каждого URL. Патологический документ увеличивает количество вызовов, но каждый вызов по-прежнему выполняется за постоянное время. performance_budget в 1500 ms по времени и 64 MB по пику определяется разбором и отрисовкой, а не вычислением политики. Ограничения размера ввода и глубины вложенности сдерживают собственные затраты парсера. Строгая политика улучшает производительность в худшем случае, отклоняя слишком большой или глубоко вложенный документ до построения макета.
Замечания по безопасности
Заголовок раздела «Замечания по безопасности»Эти контракты образуют защитный периметр движка, поэтому модель угроз задана явно. CryptoPolicyInterface снижает риск понижения алгоритма, блокируя слабые хеши и короткие ключи перед любой операцией. HtmlSecurityPolicyInterface снижает риск межсайтового скриптинга, влияющего на вывод Portable Document Format (PDF), и внедрения содержимого, удаляя запрещённые теги, атрибуты и CSS на уровне разбора до запуска модуля отрисовки. ExternalResourcePolicyInterface снижает риск подделки запросов на стороне сервера, бомб распаковки и бомб суммарного размера, по умолчанию запрещая всё и ограничивая каждую загрузку по схеме, размеру, глубине и домену. Ограничения размера ввода, глубины вложенности, количества глифов шрифта и глубины импорта снижают риск исчерпания ресурсов. Поскольку каждая политика — контракт, вы можете усилить периметр без форка движка, а имя политики доступно для записи в журнал аудита. Считайте весь HTML, все URL, а также все байты шрифтов и изображений враждебными. Эта страница помечена export_control_class: legal-review-required, поскольку контракты управляют криптографической политикой; текст пересказывает все нормативные источники и не цитирует ни один из них.
Соответствие
Заголовок раздела «Соответствие»| Утверждение | Стандарт | Пункт | Подтверждение |
|---|---|---|---|
| Неограниченная обработка URL позволяет обходить контроль доступа изменением URL; политика внешних ресурсов снижает этот риск запретом всего по умолчанию и списком разрешённых доменов с точным совпадением. | OWASP Top 10 2025 | A01 | |
| Получение внешних компонентов должно быть ограничено официальными источниками и безопасным транспортом; политика поддерживает это через списки разрешённых схем. | OWASP Top 10 2025 | Цепочка поставок ПО |
Оба пункта пересказывают рекомендации OWASP. Страница ссылается на материалы OWASP по пунктам; движок не воспроизводит их текст.
Коммерческий контекст
Заголовок раздела «Коммерческий контекст»Core определяет и фиксирует три контракта политики. Он поставляется с разрешающими значениями по умолчанию для разработки и строгими значениями по умолчанию для политики ресурсов с запретом всего. В редакции Enterprise профиль FIPS 140-3 поставляется за CryptoPolicyInterface, поэтому регулируемое развёртывание получает проверенную политику выбора алгоритмов без изменения кода подписи или шифрования. Набор контрактов идентичен во всех редакциях. Разница заключается в реализации политики, которую вы внедряете.
См. также
Заголовок раздела «См. также»- Contracts: 41 публичный интерфейс (service provider interface, SPI) — обзор и уровни стабильности.
- Contracts / Подпись —
CryptoPolicyInterfaceприменительно к подписи. - Contracts / Document — точки входа
writeHtml()иimage(), которые контролируют эти политики. - Security — поверхность шифрования, которую ограничивает криптографическая политика.
- HTML — конвейер разбора, который защищают политики HTML и ресурсов.
- Audit — журналирование аудита имени политики.