Beveiligingsbeleid
Herkos verwerkt geheime sleutels en versleutelde berichten, dus we nemen beveiligingsmeldingen serieus en horen liever vroeg dan laat over een probleem.
Een kwetsbaarheid melden
Open voor beveiligingsproblemen alstublieft geen openbare issue.
Meld het vertrouwelijk per e-mail aan security@herkos.email.
Nuttig om te vermelden: wat het probleem is, hoe het te reproduceren is, welk platform en welke versie u hebt getest, en wat een aanvaller ermee zou kunnen bereiken. Een proof of concept helpt enorm.
Voeg nooit uw eigen nsec, geheime sleutel of bunkergeheim toe aan een melding.
We streven ernaar meldingen binnen enkele dagen te bevestigen. Omdat Herkos een klein project is, vragen we u een redelijke termijn voor een oplossing te geven voordat u iets openbaar maakt. We vermelden u graag in de advisory, tenzij u dat liever niet hebt.
Wat binnen de reikwijdte valt
De Herkos-applicatie zelf: het beheer en de opslag van sleutels, het versleutelen
en ontsleutelen van berichten (inclusief de NIP-59-afzendercontroles en de
Bcc-isolatie in local_packages/nostr_mail), de app-vergrendeling, de
communicatie met relays en bridges, de verwerking van bijlagen, en de build- en
releasepipeline.
Voor Herkos Drive ook het protocolpakket ervan
(packages/herkos_drive_protocol) en de pagina die de links ervan opent
(herkos.app/f/); zie de eigen sectie ervan hieronder.
Wat buiten de reikwijdte valt
- Het Nostr-protocol en de NIP's zelf — meld die upstream.
- Relays, bridges en Blossom-servers die door derden worden beheerd. Herkos wordt met standaardinstellingen geleverd maar beheert ze niet; meld problemen bij hun beheerders.
- Het upstreamproject Nostr Mail Client, tenzij het probleem specifiek is voor wijzigingen die in Herkos zijn gemaakt.
- Ontbrekende versteviging die we al als bekende beperking documenteren (zie hieronder).
Bekende beperkingen, onomwonden
Dit zijn ontwerpafwegingen, geen kwetsbaarheden. We schrijven ze liever op dan dat iemand ze op de harde manier ontdekt:
- E-mail naar traditionele adressen is niet end-to-end versleuteld. Berichten tussen Nostr-gebruikers gebruiken NIP-17 gift wrap en zijn E2E versleuteld. Schrijft u naar een gewoon e-mailadres, dan zet een bridge het bericht om en kan hij het lezen.
- De app-vergrendeling (pincode en biometrie) is een gemaksdrempel, geen versleuteling in rust. Ze houdt iemand tegen die een ontgrendeld apparaat oppakt; ze beschermt niet tegen een aanvaller met volledige toegang tot het apparaat of de opslag ervan.
- Op Windows kan alleen-biometrische authenticatie niet worden afgedwongen. Windows Hello laat niet toe de methode te kiezen, dus de pincode van het systeem blijft altijd beschikbaar als terugvaloptie.
- Uw sleutel kwijtraken betekent het account kwijtraken. Er is bewust geen herstel.
- Metadata zijn niet volledig verborgen. Relays kunnen verbindingspatronen waarnemen, en elk relay ziet uw IP-adres, ook als het de inhoud van berichten niet kan lezen. Wat Herkos (sinds 30-09-2026) niet prijsgeeft, is wie naar wie schrijft wanneer een relay om NIP-42-authenticatie vraagt:
- Opzoeken waar te bezorgen. De relay- en Blossom-lijsten van een ontvanger
worden opgevraagd via een aparte verbinding die u nooit identificeert, eerst
bij relays die geen authenticatie vereisen (
purplepag.es,user.kindpag.es,nos.lol,offchain.pub). - Profielen en de scheduler. De naam en afbeelding die voor anderen worden getoond (kind 0), en de relaylijst van de scheduler-DVM wanneer u een e-mail inplant of annuleert, worden op dezelfde manier opgevraagd: eerst anoniem en, als een relay aandringt, met de hieronder beschreven tijdelijke sleutel, nooit met de uwe (sinds 01-10-2026; daarvoor kreeg een relay dat om authenticatie vroeg uw sleutel, en kon het zien naar wiens profiel u keek). Alleen uw eigen profiel wordt nog als u gelezen.
- Bezorgen. Gift wraps gaan naar de DM-relays van de ontvanger, via diezelfde aparte verbinding. Vereist een daarvan authenticatie, dan antwoordt Herkos met een sleutel die daarvoor is aangemaakt en alleen in het geheugen wordt bewaard, nooit met de uwe; elk account op het apparaat heeft er een eigen. Het relay kan nog steeds zien dat hetzelfde apparaat (hetzelfde IP, dezelfde tijdelijke sleutel) tijdens een sessie meerdere enveloppen heeft verstuurd.
- Grote e-mails. De versleutelde kopie van een e-mail boven 32 kB wordt geüpload naar Blossom-servers, ook die van de ontvangers. Alleen uw eigen servers (uw Blossom-lijst) krijgen de upload geautoriseerd met uw sleutel. Elke andere server krijgt hem anoniem en, als hij op een autorisatie aandringt, een die is ondertekend met dezelfde tijdelijke sleutel als hierboven (sinds 01-10-2026; daarvoor kreeg elke server uw sleutel). Een server die alleen bekende sleutels accepteert, weigert hem, en de kopie blijft op de andere servers staan.
- Uw eigen gegevens. Het synchroniseren van uw postbus, labels, instellingen en concepten authenticeert, waar een relay daarom vraagt, als het account waartoe de gegevens behoren, ook tijdens het wisselen van account. Op uw eigen relays vertelt dat ze niets wat ze nog niet wisten: de verzoeken noemen uw sleutel toch al. Uw eigen relay- en Blossom-lijsten zijn openbaar en worden opgevraagd zonder u te identificeren, net als relays die in een e-maillink worden genoemd.
- Leesstatus en mappen zijn (voorlopig) openbare metadata. Een e-mail als gelezen markeren, een ster geven, archiveren of verplaatsen publiceert een onversleutelde NIP-32-labelgebeurtenis die aan uw publieke sleutel is gekoppeld, inclusief de namen van eigen mappen. Een afzender die het id kent van een e-mail die hij u stuurde, kan zien wanneer u er iets mee deed. Het versleutelen van deze labels is gepland; beschouw mapnamen tot die tijd als openbaar.
- Pushmeldingen en gepland verzenden gebruiken diensten van derden. De
pushserver, als u er een kiest (standaard geen;
api.nmail.limetrelay.nmail.liop verzoek), leert uw publieke sleutel, een pushtoken en wanneer u e-mail ontvangt; de scheduler-DVM leert uw publieke sleutel en de reeds versleutelde berichten die hij moet publiceren. Beide zijn opt-in en gedocumenteerd inPRIVACY.md. De tekst van een pushmelding wordt door de pushserver bepaald, en Herkos vertrouwt die alleen als UnifiedPush hem versleuteld aflevert (RFC 8291); een onversleutelde payload maakt de app alleen wakker om de e-mail zelf op te halen. - De webversie bewaart uw sleutel in de browser, en dat is de zwakste plek ervoor. De geïnstalleerde apps geven uw geheime sleutel aan de beveiligde opslag van het besturingssysteem (Android Keystore, DPAPI op Windows, libsecret, de iOS-/macOS-sleutelhanger). Een browser heeft daar niets van: de sleutel staat in de opslag van de origin en gaat bij elke ondertekening door JavaScript, binnen bereik van alle code die in de pagina draait — een browserextensie met toegang tot alle sites, een XSS-fout in de app of in een afhankelijkheid, een gemanipuleerde uitrol — en van elke infostealer die het browserprofiel kopieert. Er is ook geen moment waarop u de code één keer controleert: een ondertekend programma wordt bij de installatie gecontroleerd, terwijl een webpagina bij elk bezoek nieuwe code levert. Log in de webversie in met een externe ondertekenaar (NIP-46-bunker, Amber), zodat de sleutel de browser nooit bereikt, of beschouw het als een wegwerpidentiteit en bewaar uw echte sleutel in een geïnstalleerde app.
- E-mail via een bridge is maar zo betrouwbaar als de bridge. Herkos
controleert dat een bericht dat als via een bridge binnengekomen is gemarkeerd,
echt is ondertekend door een bridge die u hebt ingesteld (of een van de
standaardbridges). Het kan niets controleren over het traditionele
From:-adres dat de bridge doorgeeft. - Bijlagen worden door het besturingssysteem geopend. Herkos start nooit uitvoerbare bestanden of scripts en vraagt het eerst voordat het een andere niet-voorvertoonbare bijlage aan de standaardapp van het systeem geeft, maar de app die het bestand opent, valt buiten onze controle.
Herkos Local Relay: wat het beschermt en wat niet
Herkos Local Relay bewaart de gebeurtenissen van uw apps op uw apparaat, ook de privégebeurtenissen (concepten, privélijsten, de enveloppen die u ontvangt). Dit is wat ze beschermt en waar de grens ligt, platform per platform. Beveiligingsproblemen in het relay meldt u op dezelfde manier als alle andere (zie hierboven).
De hele database is versleuteld, inclusief het journaal (SQLite3 Multiple Ciphers, AEGIS-256). De sleutel bestaat uit 32 willekeurige bytes die op het apparaat worden aangemaakt en in de beveiligde opslag van het besturingssysteem worden bewaard: de Keystore op Android, DPAPI op Windows, de sleutelhanger (libsecret) op Linux. Er zit geen wachtwoord van u op, omdat het relay vanzelf moet kunnen starten. Zonder de sleutel start het relay niet en zegt het dat: het opent of maakt nooit een onversleutelde database, en het verwijdert nooit een database die het niet kan openen.
| Als… | Android | Windows | Linux |
|---|---|---|---|
| iemand het databasebestand kopieert (een back-up, een gesynchroniseerde map, een schijfkopie) | Beschermd | Beschermd | Beschermd |
| het apparaat of de schijf uitgeschakeld wordt gestolen | Beschermd: de sleutel staat in de Keystore | Beschermd, tenzij men uw Windows-aanmeldwachtwoord kent: DPAPI beschermt de sleutel daarmee | Beschermd, tenzij men het wachtwoord van uw sleutelhanger kent (bijna altijd dat van uw sessie) |
| een ander gebruikersaccount op hetzelfde apparaat | Beschermd | Beschermd: DPAPI werkt per gebruiker | Beschermd: de sleutelhanger is per gebruiker |
| een andere app of een ander programma dat als uw gebruiker draait | Beschermd: Android houdt elke app apart en de Keystore geeft de sleutel alleen aan het relay | Nee: DPAPI versleutelt per gebruiker, niet per app; een programma dat als u draait, kan de sleutel net zo goed opvragen als het relay | Nee: de sleutelhanger van uw sessie houdt apps niet van elkaar gescheiden |
| een geroote telefoon, of een tool die code uitvoert als de app | Nee | — | — |
| iemand het ontgrendelde apparaat in handen heeft | Alleen de pincode of vingerafdruk van het relay, als u die instelt | Idem | Idem |
| iemand het geheugen van het relay leest terwijl het draait | Nee | Nee | Nee |
Op een desktop is de grens van DPAPI en van de sleutelhanger die van elk programma: ze beschermen tegen andere gebruikers en tegen wie de schijf meeneemt, niet tegen een kwaadaardig programma dat al als u draait. Maakt u zich zorgen over dat geval, dan beschermt u zich door de systeemschijf te versleutelen (BitLocker, LUKS) en geen programma's uit te voeren die u niet vertrouwt. Op een Linux zonder sleutelhanger (geen Secret Service) start het relay niet en legt het uit waarom: het bewaart de sleutel nooit onversleuteld.
Wie er binnenkomt, op het apparaat zelf. Het relay luistert alleen op
127.0.0.1, en elke app op het apparaat, of een webpagina in de browser, kan
dat adres bereiken. Daarom:
- Een app moet gekoppeld worden: hij verschijnt op het scherm van het relay en u keurt hem goed (met de pincode of vingerafdruk, als u die hebt ingesteld). Elke app kan zichzelf elke naam geven: keur alleen goed als u er net vanuit die app om hebt gevraagd.
- Een webpagina moet altijd gekoppeld worden, en een koppeling geldt alleen vanaf de plek waar ze is gemaakt: die van een app op het apparaat geeft een webpagina nergens toegang toe, ook niet als die met dezelfde sleutel ondertekent.
- Een gekoppelde app leest en schrijft alleen de soorten gebeurtenissen die u hem hebt gegeven, en verwijdert alleen die welke hij mag schrijven. Als u hem intrekt, wordt de verbinding meteen verbroken.
- Een niet-gekoppelde app leest alleen uw openbare gebeurtenissen (die toch al openbaar zijn) en schrijft niets, tenzij u de instelling inschakelt die niet-gekoppelde apps op het apparaat toelaat.
- Privégebeurtenissen gaan alleen naar wie met NIP-42 bewijst dat hij de sleutel heeft waartoe ze behoren, en een envelop alleen naar de ontvanger ervan.
Wat het hier niet beschermt:
- Een kwaadaardige app op het apparaat kan het relay vertragen of het geheugen laten verbruiken. Iets privés lezen kan hij daarmee niet.
- Terwijl het relay slaapt of niet draait, is zijn poort vrij. Op Android slaapt het na 10 minuten zonder verbindingen; op een desktop is de poort vrij zolang u het niet hebt gestart. Een andere app zou daar kunnen luisteren en zich als het relay kunnen voordoen. Herkos-apps zullen de sleutel van het relay controleren voordat ze het iets privés sturen; dat doen ze nog niet, en tot dan is dit een echte grens.
- Op een desktop kunnen andere gebruikers van de computer verbinding maken als niet-gekoppelde app: uw openbare gebeurtenissen lezen en vragen om gekoppeld te worden.
Het lokale netwerk, als u het inschakelt (standaard staat het uit):
- Alleen
wss://, met een eigen certificaat van het relay; nooit onversleuteldws://buiten het apparaat. - Niets vóór authenticatie (NIP-42) met een sleutel op uw lijst. Een verbinding die dat niet binnen 30 seconden doet, wordt gesloten, en het lokale netwerk heeft een eigen aantal verbindingen: het neemt nooit die van de apps op het apparaat in.
- Een sleutel op de lijst leest uw openbare gebeurtenissen en zijn eigen privégebeurtenissen, en schrijft alleen gebeurtenissen die hij heeft ondertekend. Als u hem van de lijst haalt, wordt de verbinding verbroken.
- Het certificaat is alleen geldig voor namen in huis (
localhost,.local, privéadressen): zelfs als iemand de sleutel ervan stal, zou die niet bruikbaar zijn om een internetdomein te ondertekenen op de apparaten die het certificaat hebben geïnstalleerd.
Wat het hier niet beschermt: iedereen op hetzelfde netwerk ziet dat het apparaat een open poort heeft en hoeveel verkeer erdoor gaat, maar niet wat; en als het apparaat een openbaar adres heeft (geen router ertussen), is die poort vanaf het internet zichtbaar, al vraagt hij nog steeds om een sleutel op uw lijst.
Kopieën. De versleutelde kopie heeft een wachtwoord (scrypt en XChaCha20-Poly1305): zonder dat wachtwoord kan niemand haar openen, ook wij niet. De JSONL-export is niet versleuteld en bevat uw privégebeurtenissen in platte tekst; de app waarschuwt u daarvoor.
De vergrendeling (een pincode, plus vingerafdruk of Windows Hello) wordt gevraagd wanneer de app opent, na 30 seconden weg te zijn geweest, en om een koppeling goed te keuren. Het is een gemaksdrempel, zoals in Mail: ze versleutelt niets. Op Android zijn er met een ingestelde pincode geen schermafbeeldingen en geen miniatuur bij de recente apps, en sinds Android 12 kan geen venster van een andere app over dat van het relay heen liggen terwijl u het gebruikt.
Herkos Drive: wat het beschermt en wat niet
Herkos Drive bewaart uw bestanden op Blossom-servers en de lijst van uw
bestanden en mappen op Nostr-relays, beide versleuteld op uw apparaat. Dit is
wat ze beschermt en waar de grenzen liggen. Alle details staan in
spec-drive.md en het dreigingsmodel amenazas-drive.md, in
packages/herkos_drive_protocol/; wat elke relay en elke server ziet, staat
in het privacybeleid. Meld
beveiligingsproblemen in Drive op dezelfde manier als alle andere (zie
hierboven).
Wat relays en servers niet kunnen:
- Uw bestanden of hun namen lezen. Elk blok van een bestand wordt versleuteld met AES-256-GCM onder een eigen sleutel van de revisie; namen, mappen, groottes, datums en sleutels worden verzegeld met XChaCha20-Poly1305 onder de sleutel van de map waarin ze staan. Niets wordt afgeleid van de inhoud: hetzelfde bestand twee keer geüpload geeft verschillende blokken.
- Ongemerkt iets wijzigen, verwisselen of verplaatsen. Elk blok wordt gecontroleerd tegen het manifest dat in de vermelding van zijn bestand is verzegeld, en elke vermelding is ondertekend door de volumesleutel en verzegeld voor haar eigen plaats (volume, identificatie en map): een relay kan de ene vermelding niet voor een andere laten doorgaan, en ook geen blok voor een ander.
- Een oude versie terugbrengen. De app aanvaardt nooit een vermelding die ouder is dan die ze al heeft voor dezelfde identificatie.
- Met alleen de volumesleutel namens u schrijven. Wat uw apparaten schrijven, draagt het merkteken van de eigenaar, een HMAC met een sleutel die geen enkele link meegeeft; een vermelding of verwijdering zonder dat merkteken wordt niet aanvaard, en de app waarschuwt u.
Wat het niet beschermt:
- Het patroon van uw Drive. Relays kunnen uw bestanden en mappen tellen, de vorm van de boom zien en wanneer elke vermelding verandert; servers zien ongeveer hoe groot elk bestand is (blokken worden opgevuld tot 64 KiB, vermeldingen tot een macht van twee). Elke relay en elke server ziet uw IP-adres. Gebruik Tor of Orbot op systeemniveau als dat voor u belangrijk is.
- Wat iemand al heeft gedownload. Een link of een persoon verwijderen geeft wat die kon openen meteen nieuwe sleutels, zodat die niet opent wat u later toevoegt; wat al is opgeslagen, kan het niet terughalen.
- Een uitgelekte link. Een link zonder wachtwoord is de sleutel. De browser kan hem in zijn geschiedenis bewaren voordat de pagina hem uit de adresbalk haalt. Geef de link voor alles wat gevoelig is een wachtwoord, dat u op een andere manier verstuurt, of deel met het account van de persoon. Een zwak wachtwoord kan met de tijd worden gekraakt: wie de link heeft, kan het offline proberen.
- De pagina
herkos.app/f/draait in de browser van wie een link opent. Ze wordt geleverd met een strikte Content-Security-Policy, Subresource Integrity en zonder code van derden, maar wie de webhost beheert, zou een andere pagina kunnen leveren. Dat is de grens van elke webpagina die in de browser ontsleutelt. - Wie de volumesleutel heeft gehad (de uwe, of die met een link naar een map is meegegeven), kan de blokken die ermee zijn geüpload nog steeds verwijderen, totdat ze opnieuw worden geüpload. U kunt de volumesleutel wijzigen (Instellingen → Volumesleutel): uw andere apparaten volgen vanzelf.
- Uw apparaat. De lijst met bestanden wordt versleuteld in de cache bewaard, met de sleutel in de beveiligde opslag van het systeem; een bestand dat u downloadt of opent, wordt onversleuteld weggeschreven waar u kiest. De pincode van Drive is een gemaksdrempel, zoals in Mail.
- Een kwantumcomputer, later. De blokken en zegels zijn symmetrisch (AES-256, XChaCha20), maar uw locator is versleuteld met NIP-44 op secp256k1: wie hem vandaag bewaart en morgen secp256k1 kraakt, zou de hele Drive kunnen openen.
Hoe het wordt gecontroleerd. Twee interne reviews aan de hand van het dreigingsmodel (2 november 2026) en de correcties ervan; tests van wat elke gebeurtenis en elk blok laat zien; fuzzing van elke lezer van wat van buiten komt (gebeurtenissen, zegels, manifesten, links, back-ups). Nog geen externe audit: er is er een gepland vóór de openbare bèta, en het rapport ervan wordt volledig gepubliceerd. Drive is nog in ontwikkeling.
Ondersteunde versies
Beveiligingsoplossingen worden toegepast op de nieuwste uitgebrachte versie. Gezien de omvang van het project worden oudere versies niet onderhouden — werk alstublieft bij voordat u iets meldt.