Beveiliging en operationeel beheer voor Artisan
In één oogopslag
Sectie met titel “In één oogopslag”De bridge geeft mogelijk niet-vertrouwde HTML weer in Chrome, achter twee onafhankelijke netwerkbarrières en een strikt inhoudsbeleid. De besturingssysteem-sandbox van Chrome is een afzonderlijk, optioneel beheersmiddel met expliciete grenzen. Deze pagina documenteert die grens. Ze beweert niet dat die grens absoluut is.
Conceptueel overzicht
Sectie met titel “Conceptueel overzicht”Een weergave is server-side uitvoering van een verzoek: je toepassing geeft HTML door aan een browser-engine die standaard bronnen kan ophalen. Wanneer niet-vertrouwde invoer een uitgaande ophaalactie aanstuurt, ontstaat het risico op server-side request forgery (SSRF): CWE-918 in de Common Weakness Enumeration (CWE) definieert dit als een server die de inhoud van een opgegeven URL ophaalt zonder voldoende zekerheid dat het verzoek de verwachte bestemming bereikt. SSRF (CWE-918) is een zwakheid uit de CWE Top 25. De Application Security Verification Standard (ASVS) van het Open Worldwide Application Security Project (OWASP) vereist dat je uitgaande verzoeken vanuit servercomponenten beheert in plaats van ze impliciet toe te staan. De OWASP SSRF Prevention Cheat Sheet beschouwt het weigeren van oproepen naar willekeurige bestemmingen op netwerkniveau als het sterke beheersmiddel. Het deny-by-default-netwerkmodel hieronder is het antwoord van de bridge op die vereiste. Special Publication (SP) 800-53 SC-7 van het National Institute of Standards and Technology (NIST) beschrijft hetzelfde deny-all-permit-by-exception-grensprincipe dat de bridge op de transportlaag toepast.
Dataresidentie en PII-mitigaties
Sectie met titel “Dataresidentie en PII-mitigaties”HTML die aan de bridge wordt doorgegeven, wordt volledig in-process en binnen de lokale Chrome-instantie verwerkt. De bridge doet zelf geen enkele uitgaande netwerkoproep en blokkeert dat Chrome er een doet (zie het netwerkmodel hieronder), zodat invoerinhoud de host niet via de renderer verlaat. Persoonlijk identificeerbare informatie (PII) in de invoer komt terecht in de Portable Document Format (PDF)-uitvoer die je produceert, dus behandel de uitvoer met dezelfde residentiebeheersmiddelen als de invoer. De bridge slaat invoer of uitvoer niet op schijf op; persistentie is de verantwoordelijkheid van de aanroeper.
Veilige telemetrie en log-scrubbing
Sectie met titel “Veilige telemetrie en log-scrubbing”ChromeHtmlRenderer en BrowserPool accepteren een optionele PHP Standard Recommendation (PSR)-3 LoggerInterface. De bridge logt alleen operationele metadata: bytelengte van de invoer, doelbreedte en -hoogte, bytelengte van de uitvoer, gemeten inhoudshoogte, browserstart met het geconfigureerde binaire pad, herstartmeldingen met een weergavetelling en afsluitgebeurtenissen. De bridge logt geen HTML-inhoud, weergegeven bytes of geëxtraheerde tekst. Dit sluit aan bij de richtlijn van NIST SP 800-92 om operationele gebeurtenissen te loggen terwijl gevoelige payloads buiten de logs blijven. Het binaire pad wordt gelogd. Behandel het als niet-gevoelige implementatiemetadata. Tests bevestigen de vorm van de logaanroepen in tests/Unit/Artisan/ChromeHtmlRendererTest.php::renderLogsDebugWithSizeWidthHeightAndPdfSize en tests/Unit/Artisan/BrowserPoolTest.php::getBrowserLogsInfoOnLaunchWithBinaryPath.
Netwerkisolatiemodel (defense in depth)
Sectie met titel “Netwerkisolatiemodel (defense in depth)”De bridge past twee onafhankelijke barrières toe, zodat omzeiling van één barrière de host niet blootstelt:
-
Content-Security-Policy. Elke weergave wordt door
ChromeSecurityPolicy::wrapHtml()ingepakt in een document dat het volgende bevat:default-src 'none'; style-src 'unsafe-inline'; img-src data:;base-uri 'none'; form-action 'none'; frame-ancestors 'none';navigate-to 'none';De Content Security Policy (CSP)-richtlijn
default-src 'none'weigert alle bronoorsprongen.img-src data:staat alleen inline afbeeldingen toe.navigate-to 'none'blokkeert client-side navigatie.style-src 'unsafe-inline'is de enige versoepeling die nodig is om ChromeprintToPDFinline-stijlen te laten toepassen. Geverifieerd insrc/Artisan/ChromeSecurityPolicy.phpen bevestigd doorChromeSecurityPolicyTest::wrapHtmlIncludesNavigationCspDirectives. -
Chrome DevTools Protocol (CDP)-transportblokkering. Voordat inhoud wordt geladen, verstuurt
ChromeHtmlRendererNetwork.enableen daarnaNetwork.setBlockedURLsmet het patroon['*']. Dit blokkeert elke subresource-URL op de transportlaag van het Chrome DevTools Protocol, onafhankelijk van CSP. Geverifieerd insrc/Artisan/ChromeHtmlRenderer::blockAllNetworkRequests()en bevestigd doorChromeHtmlRendererTest::renderAutoFitsHeightAndBlocksNetworkRequests(die de exacte volgorde van de CDP-methoden en de parameter['urls' => ['*']]controleert). Dit is de blokkering op netwerkniveau die de OWASP SSRF-richtlijn aanbeveelt als sterkste beheersmiddel, en het is een deny-all op transportniveau die consistent is met NIST SP 800-53 SC-7.
Het resultaat: een externe <img>, stylesheet, lettertype, script of iframe-URL in de invoer wordt niet geladen. De bridge implementeert geen domein-allowlist of privé-IP-filter omdat die niet nodig zijn: de bridge staat helemaal geen uitgaande subresource-ophaalactie toe.
Opmerking over drift: de
nextpdf/core-docblock opwriteHtmlChrome()zegt dat Chrome “externe bronnen zal ophalen” en adviseert een beleid te configureren om “privé-IP-bereiken te blokkeren en toegestane domeinen te beperken.” Dat beschrijft een configureerbaar allowlist-model. De meegeleverde ArtisanChromeSecurityPolicybiedt geen allowlist; deze blokkeert alle subresource-verzoeken onvoorwaardelijk. De code, niet de core-docblock, is gezaghebbend. Deze drift is vastgelegd voor het core-docsteam.
Invoervalidatie (pre-Chrome)
Sectie met titel “Invoervalidatie (pre-Chrome)”ChromeSecurityPolicy::validate() wordt uitgevoerd voordat de bridge contact opneemt met Chrome, en weigert:
| Controle | Limiet | Onderbouwing |
|---|---|---|
| HTML-grootte | > maxHtmlSize (standaard 5 MB) | Begrenzing tegen uitputting van bronnen (CWE Top 25 ongecontroleerd verbruik van bronnen) |
| Base64 data-URI | capture-groep >= 13_000_000 bytes | Begrenzing tegen decompressiebommen |
<meta http-equiv="refresh"> | elke (hoofdletterongevoelig, single/double aanhalingsteken) | Blokkeert client-side omleidingen naar interne endpoints, een SSRF-navigatievector |
Het blokkeren van meta-refresh is expliciete SSRF-versterking. Zonder deze blokkering zou door een aanvaller beheerde HTML Chrome kunnen omleiden naar een cloud-metadata-endpoint vóór printToPDF. Grensgedrag wordt bevestigd in ChromeSecurityPolicyTest (validateThrowsOnOversizedHtml, validateRejectsMetaRefreshRedirect, validateRejectsMetaRefreshCaseInsensitive, validateRejectsMetaRefreshWithSingleQuotes, validateRejectsOversizedBase64DataUri, validateRejectsBase64DataUriAtExactThreshold).
Daarnaast verwijdert ChromeSecurityPolicy::wrapHtml() </style> uit defaultCss vóór injectie om te voorkomen dat een stijlblok uitbreekt naar de scriptcontext (bevestigd door ChromeSecurityPolicyTest::wrapHtmlStripsStyleClosingTagsFromDefaultCss).
De Chrome-sandboxgrens — expliciet vermeld
Sectie met titel “De Chrome-sandboxgrens — expliciet vermeld”De besturingssysteem-sandbox van Chrome is een afzonderlijk beheersmiddel naast de netwerkbarrières hierboven, en de bridge garandeert die sandbox niet.
- Standaard is
noSandboxfalse, dus Chrome start met zijn eigen sandbox ingeschakeld. De bridge implementeert die sandbox niet; de bridge vertrouwt op de sandbox van de Chrome-binary, die afhankelijk is van ondersteuning door de host-kernel. - Het instellen van
noSandbox: truestart Chrome met--no-sandbox. Dit verwijdert de procesisolatie-sandbox van Chrome. De optie is bedoeld voor containers waarin de sandbox niet kan initialiseren. Het is een reële vermindering van de isolatie: een gecompromitteerde renderer wordt niet langer ingeperkt door de sandbox van Chrome. - De netwerkbarrières van de bridge (CSP + CDP-blokkering) blijven van kracht, ongeacht of de sandbox is ingeschakeld, maar ze zijn geen vervanging voor procesisolatie. De OWASP ASVS-richtlijn voor minimale rechten is van toepassing: voer Chrome uit als een niet-root-gebruiker, in een beperkte container, met
noSandboxalleen waar dit onvermijdelijk is, en behandel een--no-sandbox-implementatie als een implementatie die meer vertrouwen in de invoer vereist.
Deze documentatie beweert niet dat de bridge “standaard veilig” of “manipulatiebestendig” is. Ook beweert ze niet dat het uitschakelen van de sandbox veilig is. Ze vermeldt welke beheersmiddelen bestaan en waar hun grens ligt. Het inrichten van een sandbox-geschikte container wordt behandeld op de pagina /integrations/artisan/chrome-renderer-setup/.
Foutmodi
Sectie met titel “Foutmodi”Deze foutmodi zijn opgesomd op basis van src/Artisan/Exception/ en de render-/transportcode:
| Voorwaarde | Verschijnt als | Bron |
|---|---|---|
chrome-php/chrome-bibliotheek ontbreekt | ChromeNotAvailableException (met installatieopdracht) | BrowserPool::getBrowser() |
HTML overschrijdt maxHtmlSize | RuntimeException (“exceeds maximum allowed size”) | ChromeSecurityPolicy::validate() |
| Te grote base64 data-URI | RuntimeException (“oversized base64 data URI”) | ChromeSecurityPolicy::validate() |
| Verboden meta-refresh | RuntimeException (“forbidden meta refresh redirect”) | ChromeSecurityPolicy::validate() |
| Chrome-start / time-out / crash | ChromeRenderException (die de oorzaak omhult) | ChromeHtmlRenderer::render() |
| Chrome retourneerde een lege PDF | ChromeRenderException (“returned empty data”) | ChromeHtmlRenderer::render() |
| Pagina heeft geen content-stream | PdfParseException | PageImporter::import() |
Als ChromeRenderException tijdens de weergave wordt opgeworpen, wordt deze ongewijzigd opnieuw opgeworpen. Elke andere Throwable wordt omhuld als ChromeRenderException, met behoud van de vorige uitzondering (bevestigd door ChromeHtmlRendererTest::renderRethrowsChromeRenderExceptionWithoutWrapping en ::renderWrapsUnexpectedThrowablesWithChromeRenderException). De Chrome-pagina wordt altijd gesloten in een finally-blok, ook bij een fout.
Bronlimieten
Sectie met titel “Bronlimieten”- Invoergrootte:
maxHtmlSize(standaard 5 MB) en de base64-data-URI-limiet van 13 MB. - Tijd:
renderTimeoutseconden begrenst zowel het laden van inhoud als de synchrone CDP-oproepen. CDP-besturingsopdrachten gebruiken een vaste time-out van 5 seconden. - Proces:
BrowserPoolherstart Chrome om de 100 weergaven om geheugengroei te begrenzen en sluit het proces bijclose()/ destructie.
Dit zijn grenzen, geen quota. Gebruik voor elk pad dat aan niet-vertrouwde invoer wordt blootgesteld nog steeds een bronlimiet op hostniveau (cgroup, ulimit, verzoekbudget), in lijn met de CWE Top 25-richtlijn voor verbruik van bronnen.
Observability-hooks
Sectie met titel “Observability-hooks”Injecteer een PSR-3-logger om het begin van de weergave (grootte, breedte, hoogte), de voltooiing van de weergave (uitvoergrootte, inhoudshoogte), de browserstart (binair pad), de browserherstart (weergavetelling) en het sluiten van de browser (weergavetelling) vast te leggen. Dit zijn de enige gebeurtenissen die worden uitgezonden, en ze bevatten geen payload-inhoud. Gebruik ze voor service-level objectives (SLO’s) voor latentie en waarschuwingen over herstartfrequentie.
Conformiteit
Sectie met titel “Conformiteit”| Bewering | Referentie | clause_id | reference_id |
|---|---|---|---|
| Uitgaande verzoeken vanuit servercomponenten moeten worden beheerd | OWASP ASVS 5.0 | § (SSRF/uitgaande controle) | |
| SSRF = server haalt een opgegeven URL op zonder de bestemming te valideren | CWE Top 25 2025 (CWE-918) | cwe_top25_2025#x28.x2.p2 | |
| SSRF (CWE-918) is een zwakheid uit de CWE Top 25 | CWE Top 25 2025 | cwe_top25_2025#x1.p73 | |
| Ongecontroleerd verbruik van bronnen is een zwakheid uit de CWE Top 25 | CWE Top 25 2025 (CWE-400) | cwe_top25_2025#x19.x2.p2 | |
| Deny-by-default-grensbescherming (toestaan bij uitzondering) | NIST SP 800-53 Rev 5 SC-7 | SC-7 | |
| Weigering op netwerkniveau van oproepen naar willekeurige bestemmingen is het sterke SSRF-beheersmiddel | OWASP Cheat Sheet Series (SSRF Prevention §Network layer) | owasp_cheatsheet_series#x132.x2 | |
| Bescherm URL-ophalende componenten tegen SSRF | OWASP Cheat Sheet Series | § (SSRF-preventie, URL-ophaaltools) | |
| Isoleer weergave van niet-vertrouwde inhoud, minimale rechten | OWASP ASVS 5.0 | § (sandbox / minimale rechten) | |
| Log operationele gebeurtenissen; houd payloads buiten de logs | NIST SP 800-92 | § (richtlijn voor loginhoud) |
Citaten zijn opgehaald via de NextPDF compliance-engine (corpusmanifest 1d05b7c4…d790b6); clausuletekst is geparafraseerd, nooit geciteerd.
Dreigingsmodel
Sectie met titel “Dreigingsmodel”| Dreiging | Beheersmiddel | Restrisico |
|---|---|---|
| SSRF via externe subresource | CSP default-src 'none' + CDP setBlockedURLs('*') | Een Chrome-engine-bug die beide barrières omzeilt (defense in depth verlaagt het risico, maar elimineert het niet) |
| SSRF via meta-refresh-navigatie | Pre-Chrome-validatie weigert de tag | Een nieuwe navigatievector die niet door het patroon wordt herkend |
| Uitputting van bronnen | Invoergrootte + base64-limieten + time-out + herstart na 100 weergaven | Geen quotum per host; combineer met cgroup/ulimit |
| Compromittering van het rendererproces | Chrome-sandbox wanneer ingeschakeld | noSandbox: true verwijdert dit beheersmiddel volledig |
| Stijluitbraak / injectie | </style>-verwijdering in defaultCss; CSP blokkeert script | Injectie via een toekomstige vector die niet wordt verwijderd |
FIPS-modusgedrag
Sectie met titel “FIPS-modusgedrag”De bridge voert geen cryptografische bewerkingen uit. Ze produceert PDF-bytes via Chrome en sluit deze in. Ondertekening, versleuteling en het gedrag in de Federal Information Processing Standards (FIPS)-modus zijn aangelegenheden van core/Premium en worden niet beïnvloed door Artisan.
Zie ook
Sectie met titel “Zie ook”- /integrations/artisan/configuration/
- /integrations/artisan/chrome-renderer-setup/
- /integrations/artisan/troubleshooting/
- /integrations/artisan/production-usage/
- /integrations/artisan/overview/