Beveiligingsarchitectuur

Geplaatst op 7 april 2026 door Ruud van Vliet

PlusMin BudgetScanner

Project: PlusMin BudgetScanner
Status: High-Security Web Implementation (Production Grade)
Architectuur: React (Vite) + MUI v6 + Nginx (OpenResty/NPM)
Laatste Audit: 07 April 2026 (npm audit: 0 vulnerabilities)

1. Executive Summary

De PlusMin BudgetScanner hanteert een model voor lokale financiële dataverwerking zonder opslag en met strikte verificatie . De beveiliging rust op drie pijlers: transportbeveiliging (HSTS Preload, HTTP/2 en redirect naar https://), autorisatie van resources via dynamische nonces, en de volledige eliminatie van client-side opslag. Dit rapport beschrijft de mitigatie van XSS, data-exfiltratie en sessie-gebaseerde aanvallen.

2. Functionaliteit

De BudgetScanner is een web applicatie waarmee gebruikers banktransacties, bij voorkeur over een heel jaar, kunnen uploaden en categoriseren. Transacties worden geëxporteerd vanuit de bank als CSV- of CAMT.053-bestand (xml). De categorisatie bestaat uit het koppelen van transacties aan potjes, het kernconcept van de PlusMin-methode.

Alle verwerking vindt volledig client-side plaats in de browser. De applicatiestate kan tussentijds lokaal worden opgeslagen als JSON-bestand, met daarin alle transacties, potjes en de relaties daartussen. Door dit bestand opnieuw te importeren, hervat de gebruiker de categorisatie op het moment van opslaan.

Als eindresultaat kan een PDF-rapport worden gegenereerd met een samenvatting van de in- en uitgaven per potje, uitgesplitst per maand. De applicatie is daarmee bij uitstek geschikt als eerste stap in het traject voor financiële ondersteuning, waarbij de inventarisatie gestructureerd en versneld wordt ingevuld.

3. Security Design Principles

3.1 Transport Security & Protocol Hardening

De integriteit van de BudgetScanner is inherent verbonden met een beveiligde verbinding. De infrastructuur dwingt dit af op drie gelaagde niveaus via de Nginx Proxy Manager (NPM):

  • Server-side Force SSL (301 Redirect): De proxy is geconfigureerd om alle inkomende HTTP-verzoeken onmiddellijk via een 301 Moved Permanently statuscode om te leiden naar HTTPS. Dit garandeert dat de initiële verbinding altijd wordt getransformeerd naar een beveiligde tunnel.
  • HSTS Policy (Browser-side Lock): Ter versterking wordt de header Strict-Transport-Security "max-age=31536000; includeSubDomains" meegegeven. Hiermee dwingt de browser bij vervolgbezoeken zelfstandig HTTPS af (Client-side Redirect), nog voordat er contact met de server is gemaakt. Dit elimineert de kwetsbaarheid voor SSL-stripping aanvallen en beschermt de cryptografische nonces in de HTML-stroom tegen interceptie.
  • HTTP/2 Protocol Support: Door de activatie van HTTP/2 wordt niet alleen de performance van de vele gehashte JavaScript-chunks verbeterd, maar wordt ook het gebruik van moderne, veilige cipher suites afgedwongen. Dit minimaliseert het risico op aanvallen die gericht zijn op verouderde TLS-implementaties.

3.2 Dynamic Nonce Injection & Resource Integrity

De BudgetScanner gebruikt een unieke identifier per verzoek om inline stijlen en scripts te autoriseren zonder de veiligheid van de CSP te verzwakken.

  • Mechanism: Nginx genereert een $request_id die via de sub_filter module in de HTML wordt geïnjecteerd (window.__csp_nonce__).
  • Betrouwbaarheid: Om de fragiliteit van tekstvervanging in Nginx te beperken, is proxy_buffering en compressie op de proxy-layer uitgeschakeld. Dit garandeert dat de placeholder (%%CSP_NONCE%%) consistent wordt vervangen.
  • Asset Hashing & Resource Integrity: Alle statische assets (JS/CSS) worden geadresseerd via content-hashes in bestandsnamen. Dit maakt onbedoelde wijzigingen direct zichtbaar in deployment- en cachegedrag en voorkomt dat oude assets stilzwijgend worden hergebruikt. Dit mechanisme is sterk voor integriteit op build/deploy-niveau.

3.3 Content Security Policy (CSP) Directives

De browser dwingt de volgende policy af:

default-src 'self'; script-src 'self' 'nonce-ID'; style-src 'self' 'nonce-ID'; img-src 'self' data:; font-src 'self';

  • Exfiltratie-blokkade: Door het ontbreken van externe domeinen in de connect-src (via default-src), kan de browser onder geen beding data verzenden naar derden, zelfs niet bij een hypothetische script-injectie.

3.4 Zero-Persistence & Data Volatility

De applicatie is ontworpen om geen forensische sporen achter te laten:

  • Geen Cookies: Elimineert het risico op Session Hijacking en CSRF.
  • Geen Storage: Geen gebruik van localStorage, sessionStorage of IndexedDB. Gevoelige data bevindt zich uitsluitend in het vluchtige RAM-geheugen van de actuele tab.
  • Functionaliteit: Bij het sluiten van de tab of een browser-crash wordt de dataset direct vernietigd.

4. Applicatie Integriteit & Supply Chain

4.1 Data Parsing Security

De verwerking van bankbestanden (CSV en CAMT.053 XML) vindt volledig plaats binnen de browser-sandbox.

  • XML Safety: Er wordt gebruikgemaakt van browser-native parsers die bescherming bieden tegen XML External Entity (XXE) aanvallen door externe entiteiten standaard te blokkeren.
  • Dependency Auditing: Het project voert controles uit op externe bibliotheken. De scan via npm audit op 7 april 2026 resulteerde in 0 vulnerabilities. Het slagen van de scan is opgenomen als voorwaarde in het deployment script.

5. Risicoanalyse & Restrisico’s (Disclaimer)

Hoewel de architectuur robuust is, worden de volgende restrisico’s erkend:

  1. DOM-based XSS: De CSP en nonces beschermen tegen de injectie van externe scripts. De veiligheid tegen manipulatie van de bestaande pagina-inhoud blijft echter afhankelijk van strikte code-audits en het vermijden van onveilige React-patronen zoals dangerouslySetInnerHTML.
  2. Browser-Extensies (Client-Side Interceptie): Tijdens runtime kunnen aanroepen van het type chrome-extension:// in de netwerk-log voorkomen. Dit is een directe observatie van geïnstalleerde browser-extensies die assets (zoals lokalisatiebestanden of scripts) laden binnen de context van de applicatie.
    • Beperking: Omdat browser-extensies door het OS/Browser-model vaak privileges krijgen die buiten de CSP-sandbox vallen, kan de applicatie-architectuur niet beschermen tegen kwaadaardige software op extensie-niveau.
    • Mitigatie: De impact van dit risico wordt gemitigeerd door het Stateless-model; er zijn geen persistente gevoelige data (cookies, tokens of localStorage) aanwezig die door extensies geëxtraheerd kunnen worden voor later gebruik.
  3. Fragiliteit van sub_filter: De dynamische injectie van de nonce via Nginx is afhankelijk van de exacte match van tekststrings. Bij configuratiefouten in de upstream buffering zou de vervanging kunnen falen, wat leidt tot een functionele blokkade door de browser (veiligheidshalve).

6. Verificatiehandleiding voor Experts

A. Headers & Transport Audit

curl -I https://dev.plusmin.org/

Check: Verifieer de HSTS-header (inclusief preload) en de dynamische nonces in de CSP-header.

B. Storage & Leakage Audit

Inspecteer de browser DevTools (F12):

  1. Application Tab: Bevestig dat alle Storage-secties leeg blijven tijdens het gebruik.
  2. Network Tab: Bevestig dat er geen verbindingen buiten de eigen origin (dev.plusmin.org) plaatsvinden.

C. Source Code Audit

  1. De code is gepubliceerd op https://github.com/orgs/plusminapp/repositories
  2. Controleer de main.tsx op de correcte initialisatie van de CacheProvider met de nonce, en verifieer in de Dockerfile dat er geen onnodige server-side componenten actief zijn.
  3. Controleer de code op onveilige patronen zoals dangerouslySetInnerHTML.

7. Conclusie

De BudgetScanner implementeert een hoog beveiligingsniveau door de browser te dwingen als een geïsoleerde, vluchtige zandbak te fungeren. De combinatie van transportbeveiliging en een volledig stateless model biedt maximale privacygaranties voor lokale financiële data.