Contracts / Sicherheitsrichtlinien
Auf einen Blick
Abschnitt betitelt „Auf einen Blick“Die Domäne der Sicherheitsrichtlinien umfasst drei Contracts mit Deny-by-default-Verhalten: CryptoPolicyInterface kontrolliert die Wahl von Algorithmus und Schlüssel, HtmlSecurityPolicyInterface beschränkt die HTML-Funktionsfläche, und ExternalResourcePolicyInterface steuert das Laden entfernter Ressourcen. Jede Richtlinie ist als Contract modelliert, sodass ein Deployment eine strengere Richtlinie bereitstellen kann, ohne einen Fork zu erstellen.
Installation
Abschnitt betitelt „Installation“composer require nextpdf/core:^3Konzeptioneller Überblick
Abschnitt betitelt „Konzeptioneller Überblick“CryptoPolicyInterface ist das Gate für Kryptografie. Core fragt es vor jedem Signatur-, Verschlüsselungs- oder Hashing-Schritt ab. Die Prüfung umfasst den Hash, die Signatur-OID, die Chiffre und die Schlüsselstärke. Der Contract liefert außerdem den schwächsten Hash und einen Richtliniennamen für das Audit-Log. Er wendet ein Regelwerk wie FIPS 140-3 oder eIDAS an. Der Code zum Signieren und Verschlüsseln ändert sich dabei nicht. Wenn keine Richtlinie gesetzt ist, ist jeder Algorithmus erlaubt. Ein reguliertes Deployment muss eine explizite Richtlinie setzen.
HtmlSecurityPolicyInterface arbeitet auf der HTML-Parse-Schicht. Sie greift, bevor Inhalte einen Renderer erreichen. Sie entscheidet, ob ein Tag, ein Attribut, eine CSS-Eigenschaft oder ein URL-Schema erlaubt ist. Außerdem begrenzt sie Eingabegröße und Verschachtelungstiefe. Sie ergänzt die transportbezogenen Richtlinien je Renderer (Chrome, Cloudflare, Gotenberg), die Größenlimits und CSP-Header setzen. Die HTML-Richtlinie verkleinert die Angriffsfläche der Parse-Schicht. Ein herausgefiltertes Tag erreicht niemals das Layout. Ein eingeschleustes Element kann die Ausgabe damit nicht verändern. Wenn keine Richtlinie gesetzt ist, erlaubt die Standardkonfiguration den vollen Funktionsumfang.
ExternalResourcePolicyInterface entscheidet, ob die HTML-Pipeline eine externe Schriftart, ein Stylesheet oder ein Bild abrufen darf. Sie setzt außerdem die Grenzwerte für jeden Abruf. Ihre Standardhaltung ist Deny-all. Jede Option ist deaktiviert, bis Sie sie aktivieren. Der Contract folgt dem Least-Privilege-Prinzip. Nicht vertrauenswürdiges HTML kann auf eine von Angreifern kontrollierte URL verweisen. Der Contract kontrolliert den Abruf von @font-face nach Schema, Größe und Glyphenzahl. Er kontrolliert @import nach Schema, Tiefe und Gesamtgröße. Er kontrolliert background-image anhand einer Schemaliste und einer Domain-Allowlist mit exakter Übereinstimmung. Er begrenzt die Größe von Data-URIs. Außerdem kontrolliert er externe SVG-Referenzen. Der Contract legt fest, dass Produktionsumgebungen sie immer verweigern müssen. Sie ermöglichen Request Forgery und Skript-Injektion. Ein offener URL-Abruf ist ein Pfad für serverseitige Request Forgery. Gemäß OWASP Top 10 2025 kann Zugriffskontrolle durch Ändern der URL umgangen werden. Komponenten dürfen nur aus offiziellen Quellen über sichere Verbindungen stammen.
API-Fläche
Abschnitt betitelt „API-Fläche“| Typ | Art | Wichtige Mitglieder | Stabilität | Seit |
|---|---|---|---|---|
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 gibt typisierte Grenzwerte zurück: positive-int für Größen, int<1, 100> für die Import-Tiefe und list<non-empty-string> für Schema- und Domainlisten. Die Standardimplementierung verweigert standardmäßig jede Fähigkeit.
Codebeispiel — Schnellstart
Abschnitt betitelt „Codebeispiel — Schnellstart“<?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);}Die Funktion ist nur vom Contract abhängig. Sowohl eine restriktive Richtlinie als auch die Standardrichtlinie erfüllen ihn.
Codebeispiel — Produktion
Abschnitt betitelt „Codebeispiel — Produktion“<?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.'); } }}Das Gate erzwingt das Eingabelimit und weist eine unsichere Ressourcenrichtlinie zurück, bevor die Pipeline läuft. Es protokolliert den Richtliniennamen für das Audit und löst eine spezifische Exception aus.
Sonderfälle & Fallstricke
Abschnitt betitelt „Sonderfälle & Fallstricke“CryptoPolicyInterfaceerlaubt jeden Algorithmus, wenn keine Richtlinie gesetzt ist. Die offene Standardkonfiguration ist eine Bequemlichkeit für die Entwicklung, keine Produktionshaltung. Setzen Sie in jedem regulierten Deployment eine explizite Richtlinie.HtmlSecurityPolicyInterface::getMaxInputSize()gibt0für unbegrenzt zurück. Behandeln Sie0als „keine Richtliniengrenze“, nicht als „alles ablehnen“, und setzen Sie zusätzlich ein Limit auf der Transportschicht.ExternalResourcePolicyInterfaceist standardmäßig Deny-all. Wenn Sie@font-faceoderbackground-imageohne Schemaliste aktivieren, öffnen Sie eine Angriffsfläche für Request Forgery; setzen Sie die Allowlist, wenn Sie eine Fähigkeit aktivieren.- Eine leere Domain-Allowlist bei
getAllowedImageDomains()bedeutet, dass alle Domains erlaubt sind, sobald Hintergrundbilder aktiviert sind. Eine leere Liste ist kein Deny; geben Sie explizite Domains an. isSvgExternalReferenceAllowed()sollte in der Produktionfalsezurückgeben. Der Contract dokumentiert dies; eine Richtlinie, dietruezurückgibt, ist ein Befund, keine Konfigurationsentscheidung.
Performance
Abschnitt betitelt „Performance“Eine Richtlinienprüfung ist ein Prädikataufruf: O(1), ohne Kosten proportional zur Eingabegröße. Die Richtlinie wird beim Parsen für jedes Tag, jedes Attribut, jede CSS-Eigenschaft und jede URL herangezogen. Ein pathologisches Dokument vervielfacht die Anzahl der Aufrufe. Jeder Aufruf bleibt in konstanter Zeit. Das performance_budget von 1500 ms Wandzeit und 64 MB Spitzenverbrauch wird vom Parsen und Rendern bestimmt, nicht von der Richtlinienauswertung. Die Limits für Eingabegröße und Verschachtelungstiefe dienen dazu, die Kosten des Parsers selbst zu begrenzen. Eine strenge Richtlinie verbessert die Worst-Case-Performance, indem sie ein übergroßes oder tief verschachteltes Dokument vor dem Layout zurückweist.
Sicherheitshinweise
Abschnitt betitelt „Sicherheitshinweise“Diese Contracts bilden den Verteidigungsperimeter der Engine, daher ist das Bedrohungsmodell explizit. Algorithmus-Downgrade wird durch CryptoPolicyInterface abgewehrt, das schwache Hashes und kurze Schlüssel vor jeder Operation blockiert. Cross-Site-Scripting-to-PDF und Content-Injektion werden durch HtmlSecurityPolicyInterface abgewehrt, das unzulässige Tags, Attribute und CSS auf der Parse-Schicht entfernt, bevor der Renderer läuft. Serverseitige Request Forgery, Dekompressionsbomben und Bomben mit kumulativer Größe werden durch ExternalResourcePolicyInterface abgewehrt, das standardmäßig Deny-all ist und jeden Abruf nach Schema, Größe, Tiefe und Domain begrenzt. Ressourcenerschöpfung wird durch die Limits für Eingabegröße, Verschachtelungstiefe, Font-Glyphen und Import-Tiefe abgewehrt. Da jede Richtlinie als Contract modelliert ist, kann ein Deployment den Perimeter härten, ohne die Engine zu forken, und der Richtlinienname wird für das Audit-Logging offengelegt. Behandeln Sie alles HTML, alle URLs sowie alle Font- und Bild-Bytes als feindlich. Diese Seite ist mit export_control_class: legal-review-required markiert, weil die Contracts kryptografische Richtlinien regeln; die Prosa paraphrasiert alle normativen Quellen und gibt keine davon wörtlich wieder.
Konformität
Abschnitt betitelt „Konformität“| Aussage | Standard | Klausel | Nachweis |
|---|---|---|---|
| Unbeschränkte URL-Behandlung kann es ermöglichen, die Zugriffskontrolle durch Ändern der URL zu umgehen; die Richtlinie für externe Ressourcen wehrt dies durch Deny-all-Standards und eine Domain-Allowlist mit exakter Übereinstimmung ab. | OWASP Top 10 2025 | A01 | |
| Externe Komponenten dürfen nur aus offiziellen Quellen über sichere Verbindungen bezogen werden; die Richtlinie setzt dies über Schema-Allowlists durch. | OWASP Top 10 2025 | Software-Lieferkette |
Beide Punkte sind aus den OWASP-Vorgaben paraphrasiert. OWASP-Material wird nach Klausel referenziert; die Engine gibt den Text nicht wieder.
Kommerzieller Kontext
Abschnitt betitelt „Kommerzieller Kontext“Core definiert die drei Richtlinien-Contracts und friert sie ein. Außerdem liefert Core permissive Standardwerte für die Entwicklung sowie strenge Standardwerte für die Deny-all-Ressourcenrichtlinie. Die Enterprise-Edition liefert ein FIPS 140-3-Profil hinter CryptoPolicyInterface, sodass ein reguliertes Deployment validierte Vorgaben zur Algorithmusauswahl erhält, ohne den Code zum Signieren oder Verschlüsseln zu ändern. Die Contract-Fläche ist über alle Editionen hinweg identisch. Der Unterschied liegt in der Richtlinienimplementierung, die ein Deployment injiziert.
Siehe auch
Abschnitt betitelt „Siehe auch“- Contracts: 41 öffentliche Interfaces (SPI) — Überblick über SPI und Stabilitätsstufen.
- Contracts / Signing —
CryptoPolicyInterfaceangewendet auf das Signieren. - Contracts / Document — die Einstiegspunkte
writeHtml()undimage(), die durch diese Richtlinien kontrolliert werden. - Security — die Verschlüsselungsfläche, die die Kryptorichtlinie beschränkt.
- HTML — die Parse-Pipeline, die von den HTML- und Ressourcenrichtlinien geschützt wird.
- Audit — Audit-Logging des Richtliniennamens.