Inleiding

In de Nederlandse zorg- en overheidssector zijn Zivver en ZorgMail de standaard voor "veilig mailen". Gemeenten, zorgverleners en zorginstellingen vertrouwen dagelijks op deze diensten voor het versturen van medische gegevens, persoonlijke dossiers en vertrouwelijke correspondentie.

Hun belofte is helder: berichten worden persoonlijk afgeleverd, de ontvanger moet zich identificeren, en de afzender houdt controle. OTP-codes via SMS, TOTP twee-factor authenticatie, ontvangstbevestigingen en de mogelijkheid om berichten in te trekken — het klinkt waterdicht.

Maar klopt het?

In dit artikel beschrijf ik hoe ik, met drie zelfgebouwde MCP-servers en een AI-agent, elke beveiligingsbelofte van zowel Zivver als ZorgMail volledig heb geautomatiseerd — zonder ook maar één regel te overtreden. Geen hack. Geen exploit. Gewoon automatisering van wat een mens handmatig zou doen.

Dit is geen kwetsbaarheidsmelding. Dit is een architectuuranalyse. Het beveiligingsmodel is conceptueel achterhaald.
···

Wat beloven Zivver en ZorgMail?

Beide diensten positioneren zich als de oplossing voor veilige communicatie in sectoren waar de AVG en NEN 7510 van toepassing zijn. Hun kernbeloften:

Persoonlijk afleveren

Het bericht kan alleen geopend worden door de beoogde ontvanger. Bij ZorgMail via een OTP-code per SMS. Bij Zivver via TOTP twee-factor authenticatie. De gedachte: als je de code hebt, ben je de juiste persoon.

Ontvangstbevestiging

De afzender ziet wanneer het bericht is geopend. Dit geeft de afzender de zekerheid dat de informatie is aangekomen bij de ontvanger — essentieel in de zorg, waar medische informatie tijdkritisch kan zijn.

Bericht intrekken

De afzender kan de toegang tot een bericht achteraf intrekken. Per ongeluk het verkeerde dossier verstuurd? Geen probleem — trek het bericht in. Bij zowel Zivver als ZorgMail wordt de link of toegang geïnvalideerd.

Versleuteling

Berichten zijn versleuteld tijdens transport (TLS) en bij Zivver ook in opslag. Dit voorkomt dat derden het bericht kunnen onderscheppen.

Op papier is dit een solide model. In de praktijk — in een wereld waar AI-agents bestaan — valt het uit elkaar.

···

De architectuur: drie servers, één agent

Om de beveiligingsbeloften te toetsen heb ik drie MCP-servers (Model Context Protocol) gebouwd. Samen vormen ze een volledig geautomatiseerde pipeline die beveiligde berichten opent, leest en beantwoordt — zonder menselijke interactie.

Server 1: SMS Gateway MCP

Een TypeScript MCP-server die communiceert met een Android telefoon via de Android SMS Gateway app. Deze server kan:

  • De SMS-inbox van de telefoon uitlezen via een REST API
  • Zoeken naar specifieke berichten (bijv. OTP-codes)
  • SMS-berichten versturen
  • De inbox verversen om nieuwe berichten op te halen

De server draait in local modus: directe communicatie met de telefoon over het lokale WiFi-netwerk, via Basic Auth. Tien tools, allemaal beschikbaar voor de AI-agent.

Server 2: ZorgMail MCP

Een Python MCP-server die via Playwright (headless Chromium) de ZorgMail web-applicatie bedient. De flow:

  1. Gmail scan: zoek naar ZorgMail notificatie-emails van noreply.viewer@zorgmail.nl
  2. URL openen: navigeer naar de viewer-URL in een headless browser
  3. OTP detecteren: herken de verificatie-pagina, trigger het versturen van een OTP-code
  4. OTP afvangen: poll de SMS-inbox via de SMS Gateway MCP (primair) of Gmail (fallback) tot de 6-digit code binnenkomt
  5. OTP invoeren: vul de code in, trigger Angular change detection, klik op "Verify"
  6. Bericht lezen: extraheer afzender, datum, onderwerp en volledige tekst uit de DOM
  7. Beantwoorden: open het reply-formulier, vul tekst in via TinyMCE, voeg bijlagen toe, verzend
De OTP-code wordt binnen 5 seconden afgevangen. De hele flow — van notificatie tot gelezen bericht — duurt minder dan 30 seconden. Volledig automatisch.

Server 3: Zivver MCP

Een Python MCP-server die via Playwright de Zivver Angular SPA bedient. Vier tools: conversaties listen, lezen, beantwoorden en nieuwe berichten versturen. De authenticatie:

  1. Login: email + wachtwoord automatisch invullen op app.zivver.com
  2. TOTP genereren: de MCP-server beschikt over de TOTP-secret en berekent met pyotp exact dezelfde 6-digit code als een authenticator-app
  3. 2FA invoeren: code invullen in het formulier, submit
  4. Sessie hergebruiken: persistent browser context — één keer inloggen per serversessie

Na authenticatie kan de agent conversaties lezen, beantwoorden en nieuwe beveiligde berichten versturen — allemaal zonder menselijke interactie.

···

Elke USP getoetst

1. OTP-verificatie (ZorgMail)

ZorgMail stuurt een 6-digit verificatiecode via SMS naar het telefoonnummer van de ontvanger. De aanname: als je de code kunt invoeren, ben je de eigenaar van dat telefoonnummer, en dus de beoogde ontvanger.

De werkelijkheid: de SMS Gateway MCP-server pollt elke 3 seconden de inbox van de Android telefoon. Zodra een SMS binnenkomt van ZorgMail (of met keywords als "verificatie" of "code"), wordt de 6-digit code geëxtraheerd met een simpele regex: \b(\d{6})\b. De code wordt vervolgens automatisch ingevoerd in het ZorgMail formulier.

De hele OTP-cyclus — van aanvragen tot invoeren — duurt minder dan 5 seconden. Er is een fallback-route via Gmail voor het geval de SMS-gateway niet bereikbaar is.

Verdict: beveiliging gefaald

OTP-verificatie bewijst dat je toegang hebt tot het telefoonnummer. Het bewijst niet dat je een mens bent, laat staan de beoogde ontvanger.

2. TOTP 2FA (Zivver)

Zivver gebruikt Time-based One-Time Passwords (TOTP) als tweede factor. De gebruiker scant een QR-code bij de setup, en de authenticator-app genereert elke 30 seconden een nieuwe 6-digit code.

De kern van TOTP is een gedeeld geheim (shared secret) — een Base32-gecodeerde string die zowel bij Zivver's backend als bij de gebruiker is opgeslagen. Iedereen met dat geheim kan dezelfde codes genereren.

De MCP-server heeft de TOTP-secret. Met één regel Python — pyotp.TOTP(secret).now() — genereert hij exact dezelfde codes als de authenticator-app. De 2FA-stap wordt een wiskundige formaliteit.

Verdict: beveiliging gefaald

TOTP bewijst bezit van de gedeelde secret, niet menselijke aanwezigheid. Als de secret beschikbaar is voor software, is 2FA een no-op.

3. Persoonlijk afleveren

Dit is de kern-USP van beide diensten. "Persoonlijk afleveren" betekent: het bericht kan alleen gelezen worden door iemand die zich heeft geïdentificeerd via OTP of 2FA.

Het probleem is fundamenteel: het verificatiemechanisme bewijst channel-eigenaarschap, niet identiteit. OTP bewijst dat iemand of iets toegang heeft tot een telefoonnummer. TOTP bewijst dat iemand of iets de gedeelde secret kent. Geen van beide bewijst dat er een mens aan de andere kant zit.

Playwright draait een volledige Chromium-browser. De User-Agent is identiek aan macOS Chrome. De timing van interacties — klikken, typen, wachten — is binnen menselijke parameters. ZorgMail en Zivver zien een normale browsersessie. Er is geen verschil te detecteren.

Verdict: conceptueel achterhaald

"Persoonlijk afleveren" is een marketingterm die gebaseerd is op de aanname dat alleen mensen browsers gebruiken. Die aanname is in 2026 niet meer houdbaar.

4. Ontvangstbevestiging

De afzender ziet: "Bericht gelezen op 10 mei 2026, 14:32." Wat de afzender niet ziet: dat een AI-agent het bericht heeft geopend, de inhoud heeft geëxtraheerd, en de menselijke ontvanger er mogelijk nog niet naar heeft gekeken.

De ontvangstbevestiging bevestigt browsertoegang, niet menselijke lezing. Een arts die een diagnose stuurt via ZorgMail krijgt een groen vinkje — maar het is een robot die het bericht heeft "gelezen".

Verdict: misleidend

De ontvangstbevestiging geeft de afzender een vals gevoel van zekerheid. Het bericht is geopend, maar niet noodzakelijk door een mens gelezen.

5. Bericht intrekken

Zowel Zivver als ZorgMail bieden de mogelijkheid om berichten in te trekken. Bij Zivver verschijnt de melding "Je toegang tot dit bericht is ingetrokken." Bij ZorgMail wordt de viewer-link geïnvalideerd.

Het probleem: intrekken werkt alleen als het bericht nog niet is gelezen. Zodra de AI-agent het bericht heeft geopend, is de volledige tekst geëxtraheerd uit de DOM en opgeslagen — in geheugen, in een database, in een bestand. Het intrekken van de link heeft geen effect op de reeds gekopieerde data.

Met een geautomatiseerde flow van <30 seconden is het venster voor intrekken vrijwel nihil. Tenzij de afzender het bericht intrekt binnen seconden na verzending, is de inhoud al geëxtraheerd.

Verdict: te laat

Intrekken is een race condition die de afzender per definitie verliest tegen een geautomatiseerde ontvanger.

6. Versleuteling in transit

TLS/HTTPS-versleuteling is intact. Playwright communiceert via HTTPS met de servers van Zivver en ZorgMail. De verbinding is versleuteld. Dit is de enige USP die standhoudt — maar het is ook de USP die gewone email (met TLS) eveneens biedt.

Verdict: intact

Versleuteling in transit werkt correct. Dit is echter geen onderscheidend kenmerk — standaard email biedt dit ook.

···

Waarom werkt er geen anti-automatisering?

De kern van het probleem: noch Zivver, noch ZorgMail detecteert of blokkeert geautomatiseerde toegang. Er is geen CAPTCHA, geen device fingerprinting, geen behavioral analysis, geen rate limiting op OTP-pogingen.

Dit is geen oversight — het is een ontwerpkeuze. Beide diensten zijn ontworpen voor de zorg, waar:

  • Gebruiksgemak cruciaal is (patiënten moeten zonder technische kennis een bericht kunnen openen)
  • Toegankelijkheid een vereiste is (geen CAPTCHA die slechtzienden uitsluit)
  • Snelheid belangrijk is (tijdkritische medische informatie)

Het gevolg: het beveiligingsmodel leunt volledig op de aanname dat de OTP/2FA-stap voldoende is om een menselijke ontvanger te garanderen. Die aanname was tot voor kort redelijk. Met de opkomst van AI-agents is hij achterhaald.

Het is geen kwestie van of iemand dit bouwt. Het is een kwestie van wanneer. Ik heb het gebouwd in twee dagen.
···

Juridische en compliance-implicaties

De kern: als "persoonlijk afleveren" niet meer garandeert wat het belooft, zijn er directe gevolgen voor compliance:

NEN 7510

De NEN 7510 (informatiebeveiliging in de zorg) vereist adequate bescherming van patiëntgegevens. Als de "persoonlijk afleveren"-functie van ZorgMail niet daadwerkelijk garandeert dat alleen de patiënt het bericht leest, voldoet de implementatie mogelijk niet aan de norm — ook al is de dienst NEN 7510-gecertificeerd.

AVG / GDPR

De AVG vereist "passende technische en organisatorische maatregelen" voor de bescherming van persoonsgegevens. Als een beveiligingsmaatregel eenvoudig te automatiseren is zonder dat de afzender dit merkt, is de maatregel dan nog "passend"?

Ontvangstbevestiging als bewijs

In juridische context wordt een ontvangstbevestiging soms als bewijs gebruikt dat informatie is ontvangen door de beoogde persoon. Als de bevestiging alleen browsertoegang aantoont en geen menselijke lezing, is de bewijskracht discutabel.

De certificering garandeert dat de techniek correct is geïmplementeerd. Het garandeert niet dat de aannames achter het beveiligingsmodel nog kloppen.
···

Vergelijking: vóór en na automatisering

FeatureBelofteNa automatisering
OTP-verificatieBewijs identiteit ontvangerBewijs channel-toegang (ook door robot)
TOTP 2FA"Iets dat je hebt" (telefoon)"Iets dat software kent" (secret)
Persoonlijk afleverenAlleen de ontvanger leest hetDe ontvanger óf zijn AI-agent leest het
OntvangstbevestigingBericht is gelezen door persoonBericht is geopend door browser
Bericht intrekkenVoorkom ongewenste lezingRace condition (<30s window)
Anti-automatiseringAfwezig bij beide diensten
···

Niet gehackt — geautomatiseerd

Ik wil dit expliciet benadrukken: er is niets gehackt, gekraakt of gebroken.

  • Alle communicatie verloopt via HTTPS
  • Alle credentials zijn legitiem (eigen accounts, eigen telefoonnummer)
  • De OTP-codes worden ontvangen op het eigen telefoonnummer van de accounthouder
  • De TOTP-secret is verkregen via de officiële setup-procedure
  • Playwright draait een volledige, ongemodificeerde Chromium-browser
  • Er worden geen API's misbruikt of rate limits overschreden

Dit is puur automatisering van een handmatige flow. Dezelfde stappen die een mens met een browser zou doorlopen — maar dan in 30 seconden in plaats van 3 minuten, en zonder dat iemand hoeft op te letten.

En dat is precies het punt.

De sterkste beveiligingsanalyse is niet die welke een systeem breekt, maar die welke laat zien dat het systeem al gebroken was — zonder dat iemand het doorhad.
···

Wat moet er veranderen?

De oplossing is niet simpel, want het kernprobleem is conceptueel: hoe bewijs je dat een mens een bericht leest? Enkele richtingen:

1. Anti-automatisering detectie

Behavioral analysis, browser fingerprinting, timing-analyse. Detecteer of interactie-patronen consistent zijn met menselijk gedrag. Nadeel: impact op toegankelijkheid en gebruiksgemak.

2. Hardware-gebonden 2FA

FIDO2/WebAuthn met hardware security keys. De private key verlaat nooit het fysieke apparaat. Moeilijk te automatiseren — maar vereist een hardware-investering van elke gebruiker.

3. Transparantie over beperkingen

Communiceer eerlijk dat "persoonlijk afleveren" channel-verificatie is, niet identiteitsverificatie. Laat de certificering de werkelijke garanties weerspiegelen.

4. Aanvullende verificatie

Biometrische verificatie, video-identificatie, of periodieke re-verificatie. Verhoogt de drempel aanzienlijk, maar maakt de dienst minder gebruiksvriendelijk.

Geen van deze oplossingen is perfect. De kern is dat het huidige model — OTP + 2FA als bewijs van menselijke identiteit — niet meer voldoet in een wereld met AI-agents. De branche moet dit erkennen en communiceren.

···

Over deze analyse

Deze analyse is uitgevoerd als onafhankelijk security research door iCt Horse. Alle tests zijn uitgevoerd op eigen accounts met eigen credentials. Er zijn geen systemen van derden zonder toestemming benaderd.

De drie MCP-servers zijn functionele, werkende software die dagelijks wordt gebruikt voor het efficiënt verwerken van beveiligde berichten. Ze zijn niet gebouwd als exploit — ze zijn gebouwd als productiviteitstool. Dat ze tegelijkertijd de beveiligingsbeloften van twee marktleiders ondermijnen, is een bijeffect dat de branche niet kan negeren.

3MCP Servers
17Geautom. tools
<30sVolledige flow
0Regels overtreden

← Terug naar interactief overzicht iCt Horse →