Veilig delen van vertrouwelijke informatie

Genereer een beveiligde link
Vul uw naam in.
Vul een geldig e-mailadres in.
Vul de naam van de ontvanger in.
Vul een geldig e-mailadres in.
0/30
Toegangscode is verplicht (minimaal 4 tekens).
De toegangscode wordt nooit verstuurd via e-mail. Stuur deze separaat aan de ontvanger (bijv. via telefoon of chat).
⚠️ Kanaalscheiding — zo werkt het veilig
1. See It Once verstuurt het ID automatisch per e-mail naar de ontvanger ✓ Automatisch via See It Once
2. Stuur de sleutel via een ander kanaal: telefoon, SMS of chat ✓ Bel, app of SMS
3. Stuur de toegangscode eveneens via een apart kanaal naar de ontvanger ✓ Nooit samen met ID of sleutel
Stuur ID, sleutel én toegangscode nooit samen in één bericht ✗ Maakt beveiliging ongedaan
Secret ophalen
Vul het ID in.
Vul de sleutel in.
Vul de toegangscode in.
Het ID staat in de e-mail van de ontvanger. De sleutel en toegangscode ontvangt u separaat van de verzender.
Contact

Heeft u vragen, verbeteringen en/of opmerkingen over See It Once? Vul dan onderstaand contactformulier in. Wij nemen zo spoedig mogelijk contact met u op.

Vul uw naam in.
Vul een geldig e-mailadres in.
0/1000
Vul een bericht in (minimaal 10 tekens).
Technische werking
Architectuur
See It Once bestaat uit drie Docker-containers die via een intern netwerk communiceren: een Nginx-frontend die de interface serveert, een Node.js/Express-backend die de REST API aanbiedt, en Redis als in-memory datastore met ingebouwde TTL-ondersteuning. Alle API-verzoeken van de browser lopen via de Nginx-proxy naar de backend — de browser communiceert nooit rechtstreeks met Node.js.
Twee-staps verificatieflow
Het aanmaken van een secret verloopt via een bevestigde twee-staps flow:

Stap 1 — Aanmaken De verzender vult naam, e-mailadres, naam en e-mailadres van de ontvanger, de inhoud en een verplichte toegangscode in. De browser versleutelt het secret lokaal met PBKDF2 + AES-256-GCM op basis van de toegangscode, vóórdat er iets naar de server wordt gestuurd. De backend slaat het versleutelde secret tijdelijk op als pending in Redis (TTL: 1 uur) en stuurt een bevestigingsmail naar de verzender.

Stap 2 — Bevestiging De verzender klikt op de bevestigingsknop in de e-mail. De backend verifieert het eenmalige token, activeert het secret definitief in Redis en stuurt een notificatiemail naar de ontvanger met uitsluitend het id — zonder sleutel of toegangscode.

Stap 3 — Ophalen De ontvanger klikt op de link in de notificatiemail, voert de toegangscode in die de verzender separaat heeft gecommuniceerd (telefoon, chat) en de browser ontsleutelt het secret volledig lokaal. Daarna wordt het secret permanent van de server verwijderd.
Verplichte toegangscode (versleutelingslaag)
Een toegangscode is altijd verplicht. De browser versleutelt het secret vóór verzending via PBKDF2 (200.000 iteraties, SHA-256) gevolgd door AES-256-GCM. De toegangscode verlaat de browser nooit en wordt nergens opgeslagen — ook niet door de server. De ontvanger kan het secret alleen ontsleutelen met de toegangscode die de verzender separaat communiceert. Zelfs de server-operator kan de inhoud niet inzien.
Verzendersverificatie via e-mail
Voordat de ontvanger een notificatie krijgt, moet de verzender de actie bevestigen via een bevestigingslink die naar zijn eigen e-mailadres wordt gestuurd. Dit voorkomt misbruik: een bot of onbekende bezoeker die het formulier invult kan de flow niet voltooien zonder toegang tot het opgegeven e-mailaccount. De bevestigingslink bevat een willekeurig token van 32 bytes en is 1 uur geldig en eenmalig bruikbaar.

Bescherming tegen e-mailscanners (Safe Links)
Beveiligingssoftware zoals Microsoft Defender Safe Links volgt alle links in inkomende e-mails automatisch — ook vóórdat de gebruiker klikt. Als de bevestiging direct via een GET-request zou worden uitgevoerd, zou de scanner de token verbruiken en de gebruiker zou een "verlopen link" zien zonder ooit zelf te hebben geklikt.

Om dit te voorkomen werkt de bevestigingsflow in twee stappen: de link in de e-mail opent uitsluitend een landingspagina (GET zonder bijwerking). De daadwerkelijke activatie — opslaan van het secret en versturen van de notificatiemail — vindt pas plaats na een expliciete klik op de bevestigingsknop op die pagina, via een POST-request. Scanners volgen geen POSTs, waardoor de token intact blijft tot de verzender zelf bevestigt.
Notificatiemail naar ontvanger
De notificatiemail aan de ontvanger bevat uitsluitend het id van het secret — geen sleutel, geen toegangscode. Onderschepping van de e-mail geeft een aanvaller niets bruikbaars: zonder de toegangscode (die via een apart kanaal wordt gecommuniceerd) is het secret niet te ontsleutelen.
Atomaire ophaal & verwijdering (GETDEL)
Het ophalen van een secret gebeurt via een atomaire Redis GETDEL-operatie: ophalen en verwijderen zijn één ondeelbare stap. Dit voorkomt een race condition waarbij twee gelijktijdige verzoeken hetzelfde secret zouden kunnen ontvangen. Zodra het secret is opgehaald — ook bij een onjuiste sleutel of toegangscode — is het permanent verwijderd van de server.
Cleane URL — sleutel nooit in adresbalk
De notificatiemail bevat een link in de vorm /s/{id}. De server-sleutel en toegangscode staan nooit in de URL: de sleutel wordt via een versleuteld POST-verzoek (request body) verstuurd, niet als querystring. Na het ophalen van het secret vervangt de browser de URL automatisch terug naar / via history.replaceState, zodat het ID niet achterblijft in de browserhistorie.
Automatisch verlopen & datapersistentie
Niet-geopende secrets worden automatisch verwijderd door Redis na de ingestelde vervaltijd (15 minuten tot 7 dagen). De backend luistert via een aparte subscriber-verbinding op Redis keyspace-events; zodra een secret verloopt, worden de statistieken direct bijgewerkt.

Redis is geconfigureerd met AOF-persistentie (appendfsync everysec) en aanvullende RDB-snapshots. Bij een herstart of update blijven alle nog-niet-verlopen secrets en statistieken bewaard — maximaal 1 seconde dataverlies bij een onverwachte crash.
Invoervalidatie
Elk API-endpoint valideert inkomende data via Zod-schema's vóórdat enige businesslogica wordt uitgevoerd. Ontbrekende velden, verkeerde typen of waarden buiten de toegestane grenzen worden direct afgewezen met een duidelijke foutmelding. Het id in de URL en de key in de request body worden gefilterd op toegestane tekens ([a-f0-9]) voordat ze Redis ingaan.
Beveiliging & rate limiting
De backend zet via Helmet automatisch HTTP-beveiligingsheaders (X-Frame-Options, X-Content-Type-Options, Referrer-Policy e.a.). Verzoeken worden op drie niveaus beperkt via express-rate-limit:

· Globaal: max 100 req/min per IP op alle API-routes
· Secret aanmaken: max 20 req/min per IP
· Contactformulier: max 3 req/10 min per IP

De server retourneert bij onbekende routes altijd een JSON-404 en bij onverwachte fouten een JSON-500 — stack traces worden nooit naar de client gestuurd.
Wat de server nooit ziet
De server ontvangt nooit de decryptiesleutel, de toegangscode of de leesbare tekst van het secret. De enige manier om een secret te lezen is met het juiste ID, de juiste sleutel én de juiste toegangscode — na één gebruik is het secret permanent verwijderd.
Dataflow samengevat
1 · Aanmaken Browser versleutelt secret lokaal (PBKDF2 + AES-256-GCM) → Zod valideert invoer → backend slaat pending op in Redis (1 uur TTL) → bevestigingsmail naar verzender

2 · Bevestigen Verzender klikt link → landingspagina getoond (GET, geen activatie) → verzender klikt bevestigingsknop → POST stuurt token → secret geactiveerd in Redis met gekozen TTL → notificatiemail naar ontvanger (alleen id, geen sleutel)

3 · Ophalen Ontvanger opent site → vult ID, sleutel en toegangscode in → browser ontsleutelt lokaal → secret getoond → backend verwijdert secret én persoonsgegevens permanent uit Redis → ontvangstbevestiging verstuurd naar verzender
Ontvangstbevestiging
Zodra een secret succesvol is opgehaald ontvangt de verzender automatisch een bevestigingsmail met tijdstip van ophalen en de referentie (indien opgegeven). Deze melding is niet-fataal: als de bevestigingsmail niet afgeleverd kan worden, wordt het secret toch correct teruggegeven aan de ontvanger.
Geanonimiseerde audit-log
Bij elk ophaalmoment schrijft de backend een gestructureerde logmelding met: een afgekorte variant van het secret-ID, de referentie (indien aanwezig), het tijdstip (ISO 8601), en een gehashte versie van het IP-adres (SHA-256 met een server-side salt). Het werkelijke IP-adres wordt nooit opgeslagen. De hash is alleen bruikbaar voor correlatie bij een incident — niet voor identificatie.
Content Security Policy
De backend stuurt via Helmet een strikte Content-Security-Policy header mee op alle responses. Dit voorkomt dat een eventuele XSS-aanval de client-side encryptie kan omzeilen door externe scripts te laden of data naar externe domeinen te sturen. De policy staat uitsluitend eigen scripts, stijlen en het Google Fonts CDN toe.
Redis TLS
De verbinding tussen de backend en Redis kan worden beveiligd via TLS door REDIS_TLS=true in te stellen en een rediss:// URL te gebruiken. Dit is aanbevolen wanneer Redis op een externe host of apart netwerksegment draait. Binnen een geïsoleerd Docker-netwerk (internal bridge) is het risico beperkt, maar de optie is beschikbaar voor productie-omgevingen met hogere eisen.
Wachtwoordgenerator

Genereer een sterk willekeurig wachtwoord om te gebruiken als toegangscode.

Wachtwoorden worden lokaal gegenereerd in je browser — er wordt niets naar de server gestuurd.

Release notes
202604.07 April 2026
  • 📬 Ontvangstbevestiging: verzender krijgt e-mail zodra secret is opgehaald
  • 🛡️ Content Security Policy headers ingeschakeld (XSS-bescherming)
  • 🔐 Redis TLS-ondersteuning via REDIS_TLS=true env var
  • 📋 Geanonimiseerde audit-log per ophaalgebeurtenis (IP-hash, tijdstip, ref)
  • ♻️ Redis replica toegevoegd aan Docker-configuratie (redundantie)
  • 📖 Kanaalscheiding-stappenkaart toegevoegd aan aanmaak-formulier
  • 🧹 Versienummer verwijderd uit footer
202604.06 April 2026
  • 🛡️ Safe Links fix: bevestigingslink toont nu eerst een landingspagina
  • 🖱️ Activatie pas na expliciete klik op knop — niet meer bij GET (scanners)
  • 🔄 Bevestiging verloopt via POST zodat e-mailscanners de token niet verbruiken
202604.05 April 2026
  • 🔒 Race condition opgelost: secret ophalen is nu atomair via Redis GETDEL
  • 🔗 Cleane ophaal-URL: /s/{id} i.p.v. ?id=… querystring
  • 🚫 Server-sleutel nooit meer zichtbaar in adresbalk of browser-history
  • 🧹 URL verdwijnt naar / na ophalen (history.replaceState)
  • 📤 Key wordt via POST body verstuurd in plaats van querystring
202604.03 April 2026
  • 🔑 Toegangscode veld toegevoegd aan ophalen-formulier
  • 🐛 Bugfix: ID bleef consistent na bevestiging (was nieuw gegenereerd bij confirm)
  • 📧 E-mailteksten vernieuwd: menselijker, minder spam-gevoelig
  • 📧 Notificatiemail onderwerp bevat nu naam van verzender
  • 📧 Bevestigingsmail: melding inbox/spam toegevoegd
  • 🔒 Wachtwoord verplicht gesteld, pw=1 uit URL verwijderd
202604.02 April 2026
  • 📊 Redis-backed statistieken met keyspace expiry listeners
  • 📬 Nodemailer SMTP integratie (Office365)
  • 🛡️ Contactformulier met honeypot en rate limiting
  • 🎨 Hamburger navigatie en card layout frontend
  • 📄 Technische documentatiepagina
Wat vindt AI ervan?

We hebben drie toonaangevende AI-modellen gevraagd om See It Once te beoordelen vanuit het perspectief van een security officer: zou je de tool gebruiken voor het veilig delen van vertrouwelijke informatie? Hieronder de onafhankelijke analyses van Claude, ChatGPT en Gemini.

🟠
Claude (Anthropic)
Sonnet — security review
✓ Ja, met kanttekeningen
See It Once is aantoonbaar beter dan het alternatief: wachtwoorden en credentials via e-mail of chat sturen. De combinatie van client-side AES-256-GCM encryptie, verplichte twee-kanaals communicatie (ID via mail, sleutel via apart kanaal) en eenmalig lezen via atomaire GETDEL maakt dit een solide keuze voor intern gebruik binnen een organisatie die de server zelf beheert.
Sterk
  • Client-side encryptie — server ziet nooit de leesbare inhoud
  • Wachtwoord verlaat de browser nooit
  • Atomaire ophaal+verwijder (GETDEL) — race-conditionproof
  • Twee-staps e-mailbevestiging voorkomt misbruik
  • Safe Links-proof bevestigingsflow (GET → landingspagina, POST → activatie)
  • Sleutel nooit in URL of browserhistorie
  • Self-hosted: geen afhankelijkheid van externe partijen
Aandachtspunten
  • Vereist gebruikersdiscipline: ID en sleutel mogen nooit via hetzelfde kanaal
  • Geen audit trail per secret (wie las het, wanneer, welk IP)
  • Server-operator heeft toegang tot de versleutelde blob + serversleutel
  • Geen identiteitsverificatie van de ontvanger
  • Redis moet goed beveiligd zijn (geen publieke toegang, encryptie at rest)
Geschikt voor: intern delen van tijdelijke credentials, wachtwoorden en API-sleutels tussen collega's en bekende externe partijen. Niet geschikt voor situaties waarbij de server-operator zelf niet vertrouwd wordt, of waarbij harde audit-vereisten gelden (AVG-logging, NEN 7510).
🟢
ChatGPT (OpenAI)
GPT-4o — security review
~ Voorwaardelijk ja
See It Once hanteert een verdedigbare security-architectuur. De keuze voor client-side encryptie via de Web Crypto API (PBKDF2 + AES-256-GCM) is in lijn met moderne best practices. Het ontwerp minimaliseert server-side risico's effectief: zelfs bij een volledig gecompromitteerde Redis-instantie beschikt een aanvaller alleen over versleutelde data zonder het wachtwoord.
Sterk
  • Zero-knowledge architectuur voor de inhoud van het secret
  • TTL-gebaseerde automatische verwijdering reduceert aanvalsoppervlak
  • Dubbele versleuteling (client-side + server-side) biedt defence-in-depth
  • Rate limiting op alle endpoints beperkt brute-force risico
  • Twee-staps verificatie via e-mail voorkomt ongeautoriseerd aanmaken
Risico's
  • Geen MFA of sessiebeheer voor de gebruiker
  • Beveiliging staat of valt bij correcte scheiding van kanalen door gebruikers
  • Geen logging of alerting bij verdachte toegangspatronen
  • SMTP-transport als potentieel zwakke schakel voor notificaties
  • Ontbreekt: Content Security Policy headers voor de frontend
Voor een zelfbeheerde, interne implementatie binnen een vertrouwde infrastructuur is See It Once een acceptabele keuze als vervanging voor onveilige kanalen. Aanbevolen aanvullingen: CSP-headers instellen, Redis-verbinding versleutelen met TLS, en een minimale audit-log toevoegen voor compliance-doeleinden.
🔵
Gemini (Google DeepMind)
Gemini 1.5 Pro — security review
~ Voorwaardelijk ja
See It Once pakt een reëel en veelvoorkomend probleem aan: organisaties sturen dagelijks gevoelige informatie via inherent onveilige kanalen zoals e-mail en messaging-apps. De tool biedt een structurele verbetering, mits correct ingezet. De self-hosted opzet is vanuit privacyperspectief een pre — er is geen afhankelijkheid van derde partijen voor de opslag van gevoelige data.
Sterk
  • Versleutelde opslag: server slaat nooit plaintext op
  • Eenmalig lezen elimineert persistente blootstelling
  • Self-hosted: volledige controle over data en infrastructuur
  • Open codebase maakt onafhankelijke audit mogelijk
  • Bevestigingsflow beschermt tegen geautomatiseerd misbruik
Risico's
  • Vertrouwensmodel: server-operator is impliciet vertrouwd
  • Geen bevestiging aan verzender dat het secret is opgehaald
  • Gebruikersfout (kanalen mengen) is de grootste kwetsbaarheid
  • Geen ondersteuning voor bestanden of binaire data
  • Schaalbaarheidsvraag: single Redis instance als single point of failure
Een pragmatische, goed doordachte tool voor het beoogde doel. De beveiligingsaanpak is consistent met het dreigingsmodel. Gemini beveelt aan om de tool te begeleiden met gebruikerstraining over kanaalscheiding, en overweeg een optionele ontvangstbevestiging toe te voegen voor hoog-risico use cases.
ⓘ De reviews van ChatGPT en Gemini zijn samengesteld op basis van hun publiek gedocumenteerde security-analyseprincipes en redeneerpatronen, toegepast op de architectuur van See It Once. De review van Claude is een directe evaluatie. Alle drie de modellen zijn gevraagd dezelfde vraag te beantwoorden: "Zou je See It Once als security officer gebruiken, en waarom?"
Over See It Once

Het begon met nieuwsgierigheid. Gewoon eens kijken wat er mogelijk is met Docker, een Redis-database en een zelfgebouwde backend en frontend. Geen groot plan, geen strak businessmodel — gewoon bouwen, proberen, stukmaken en opnieuw beginnen.

In het begin was het vooral technisch spelen: containers opzetten, services met elkaar laten communiceren, caching regelen via Redis. Maar al snel ontstond er een praktisch idee — hoe handig zou het zijn om tijdelijk gevoelige informatie te kunnen delen? Denk aan tokens of een korte boodschap: iets wat je één keer wilt bekijken en daarna nooit meer.

En daar zit precies de uitdaging. Want eerlijk is eerlijk: er zijn al genoeg van dit soort tools. "One-time secret", "burn after reading" — noem het maar op. Maar welke kun je vertrouwen? Waar blijft je data echt privé? Wat gebeurt er op de achtergrond?

In plaats van te vertrouwen op iets wat ik niet volledig begrijp of kan controleren, besloot ik het zelf te bouwen. Niet omdat ik dacht het beter te kunnen dan de rest, maar omdat ik wilde weten hóe het werkt. Volledige controle over de logica, de opslag, de beveiliging. Geen black box — maar iets waarvan ik elke regel code ken.

Langzaam groeide het project. AI-ondersteuning kwam erbij — niet als gimmick, maar als hulpmiddel. Voor het versnellen van ontwikkeling, het verbeteren van logica en het itereren op features. Het werd een combinatie van experiment en praktijktool.

En ja, het voelt soms nog steeds als "één uit een dozijn". Maar tegelijk ook niet. Want dit is mijn dozijn. Gebouwd vanuit nieuwsgierigheid, met aandacht voor veiligheid en transparantie. Geen grote marketingverhalen — gewoon iets dat werkt.

Het is geen afgerond product, maar een doorlopend experiment. Iets dat blijft groeien, verbeteren en soms ook weer opnieuw begint. En stiekem hoop ik dat meer mensen het gaan gebruiken — niet alleen omdat het handig is, maar omdat het laat zien dat je zelf ook controle kunt nemen over de tools die je dagelijks gebruikt.

Gemaakt door
Erik Norder
LinkedIn ✉ info@seeitonce.eu
Heb je vragen, opmerkingen of twijfel je over deze tool? of stuur een mail naar info@seeitonce.eu .
🔒
AES-256-GCM encryptie
De decryptiesleutel is uitsluitend in de link aanwezig, nooit op de server opgeslagen.
Eenmalige toegang
Bericht wordt direct verwijderd nadat het eenmaal gelezen is.
Automatisch verlopen
Ongelezen berichten worden automatisch verwijderd na de gekozen tijd.
🛡
Lokaal gehost en privacygericht
Gehost in Nederland. Geen logging, geen tracking.