Aanleiding
Bij de afbeelding-hardening (#343 / PR #347) blokkeert de backend nu het rechtstreeks opslaan van een rauwe data:image/svg+xml-databron; alleen raster-formaten (webp/png/jpeg/gif) worden geaccepteerd. Dit is bewust conservatief. SVG is voor diagrammen/architectuurplaatjes echter fijn (haarscherp bij elke zoom, klein, toegankelijk). Dit issue is om te onderzoeken of en hoe we echte vector-SVG veilig kunnen ondersteunen — met een expliciete onderbouwing waarom het nu niet aanstaat, én een eerlijke schets van de mogelijkheden om het wél te doen.
Huidige situatie (stand van zaken)
Waarom nu niet (onderbouwing standaarden / BIO)
SVG is geen statische afbeelding maar actieve content: het kan <script>, event-handlers (onload=), <foreignObject> en externe verwijzingen bevatten. Rauwe, niet-gesaneerde SVG die ergens inline in de DOM belandt, voert die code uit → stored XSS. Voor een overheids-DPIA-tool met gevoelige gegevens weegt dat zwaar:
- BIO (Baseline Informatiebeveiliging Overheid) — verplicht normenkader (o.b.v. ISO 27002). Relevant: invoervalidatie en secure development (o.a. 8.26 application security requirements, 8.28 secure coding). Uploads moeten als onvertrouwd worden behandeld en gevalideerd/gesaneerd.
- NCSC — ICT-beveiligingsrichtlijnen voor webapplicaties (sluit expliciet aan op de BIO; via Forum Standaardisatie verplicht voor overheidswebsites): invoervalidatie, content-handling en CSP. Treat uploads als untrusted.
- NeRDS richtlijn 6 — Maak veilige systemen + de leidraad op developer.overheid.nl: secure-by-design en defense-in-depth. De huidige rasterisatie + server-allowlist is precies dat: de visuele waarde behouden, het risico weghalen.
- OWASP: SVG-upload-XSS is een bekende klasse; het advies is SVG als actieve content te behandelen en óf te saneren, óf via
<img> te renderen, óf te rasteriseren (PNG/WebP) — dat laatste verwijdert alle uitvoerbare inhoud en is wat we nu doen.
Kortom: de huidige keuze (rasteriseren) is verdedigbaar en standaard-conform. Het is een bewuste leg-uit: visueel resultaat behouden, aanvalsoppervlak elimineren.
Mogelijkheden om het wél (veilig) te doen
Er zijn reële opties die écht vector-SVG behouden — met oplopende complexiteit en restrisico:
- Gesaneerde inline-SVG (DOMPurify, server + client). Strip
<script>, <foreignObject>, event-handlers en externe/javascript:-verwijzingen. Aandachtspunten: sanitizer-bypasses zijn voorgekomen (bv. CVE-2024-47875), dus ook XML-entity-expansie (billion-laughs) en grootte begrenzen; saneren op de server (niet alleen client), plus een strikte CSP. Onderhoudslast + audit nodig.
- Alleen via
<img> renderen (geen inline-SVG). Browsers voeren géén scripts uit in SVG die via <img src=data:image/svg+xml> wordt geladen, en blokkeren externe resource-loads. ImageField.vue toont al via <img :src>. Relatief veilig voor weergave, maar fragiele garantie: de PDF-export (pdfmake) behandelt SVG anders dan raster, en elk toekomstig inline-gebruik doorbreekt de aanname.
- Server-side rasteriseren naar PNG/WebP (bv. resvg/sharp), evt. op hogere resolutie. Consistente output, strikt zonder actieve content — maar nog steeds raster (geen vector). Verbetert hooguit de scherpte t.o.v. nu.
Opties 1 en 2 leveren echte vector op; 3 niet. Voor weergave-kwaliteit zonder vector kan ook simpelweg de huidige rasterisatie op hogere resolutie/instelbaar gemaakt worden.
Tegenargument (pro-SVG, voor de balans)
- Toegankelijkheid (WCAG / NeRDS toegankelijkheid): SVG schaalt zonder kwaliteitsverlies en kan
<title>/tekst bevatten — gunstig voor zoom en screenreaders.
- Kwaliteit & omvang: voor diagrammen vaak scherper én kleiner dan raster.
Te onderzoeken / acceptatiecriteria
Referenties
Context: server-side blokkade geïntroduceerd in #343 / PR #347.
Aanleiding
Bij de afbeelding-hardening (#343 / PR #347) blokkeert de backend nu het rechtstreeks opslaan van een rauwe
data:image/svg+xml-databron; alleen raster-formaten (webp/png/jpeg/gif) worden geaccepteerd. Dit is bewust conservatief. SVG is voor diagrammen/architectuurplaatjes echter fijn (haarscherp bij elke zoom, klein, toegankelijk). Dit issue is om te onderzoeken of en hoe we echte vector-SVG veilig kunnen ondersteunen — met een expliciete onderbouwing waarom het nu niet aanstaat, én een eerlijke schets van de mogelijkheden om het wél te doen.Huidige situatie (stand van zaken)
ImageField.vue+imageResize.ts) accepteert een SVG-upload, maar rasteriseert die op een canvas (2× resolutie) naar WebP. Wat opgeslagen wordt is dusdata:image/webp;base64,….isImageValue-guard al SVG; de server-check uit Security audit follow-up: resterende low/info-hardening (F8, data:-URI, readOnlyRootFilesystem) #343 is het sluitstuk daarvan (defense-in-depth, ook tegen een omzeilde client).Waarom nu niet (onderbouwing standaarden / BIO)
SVG is geen statische afbeelding maar actieve content: het kan
<script>, event-handlers (onload=),<foreignObject>en externe verwijzingen bevatten. Rauwe, niet-gesaneerde SVG die ergens inline in de DOM belandt, voert die code uit → stored XSS. Voor een overheids-DPIA-tool met gevoelige gegevens weegt dat zwaar:<img>te renderen, óf te rasteriseren (PNG/WebP) — dat laatste verwijdert alle uitvoerbare inhoud en is wat we nu doen.Kortom: de huidige keuze (rasteriseren) is verdedigbaar en standaard-conform. Het is een bewuste leg-uit: visueel resultaat behouden, aanvalsoppervlak elimineren.
Mogelijkheden om het wél (veilig) te doen
Er zijn reële opties die écht vector-SVG behouden — met oplopende complexiteit en restrisico:
<script>,<foreignObject>, event-handlers en externe/javascript:-verwijzingen. Aandachtspunten: sanitizer-bypasses zijn voorgekomen (bv. CVE-2024-47875), dus ook XML-entity-expansie (billion-laughs) en grootte begrenzen; saneren op de server (niet alleen client), plus een strikte CSP. Onderhoudslast + audit nodig.<img>renderen (geen inline-SVG). Browsers voeren géén scripts uit in SVG die via<img src=data:image/svg+xml>wordt geladen, en blokkeren externe resource-loads.ImageField.vuetoont al via<img :src>. Relatief veilig voor weergave, maar fragiele garantie: de PDF-export (pdfmake) behandelt SVG anders dan raster, en elk toekomstig inline-gebruik doorbreekt de aanname.Opties 1 en 2 leveren echte vector op; 3 niet. Voor weergave-kwaliteit zonder vector kan ook simpelweg de huidige rasterisatie op hogere resolutie/instelbaar gemaakt worden.
Tegenargument (pro-SVG, voor de balans)
<title>/tekst bevatten — gunstig voor zoom en screenreaders.Te onderzoeken / acceptatiecriteria
<img>-weergave, PDF-export (pdfmake), en eventuele toekomstige inline-rendering.img-src data:voldoende is, of dat een aparte aanpak nodig is.svg-node vs. raster).Referenties
Context: server-side blokkade geïntroduceerd in #343 / PR #347.