Security
Everything below describes the system as it actually runs, verified against the production host rather than copied from a policy template. Where a control does not exist, this page says so instead of leaving it out.
Reporting a vulnerability: [email protected] · security.txt (RFC 9116)
Where the data lives
All production data sits on hardware operated by Hetzner Online GmbH in Nuremberg (nbg1), Germany. There is no managed third-party database and no replica outside the EU: PostgreSQL, the connection pooler and the search engine all run on that single host.
The database is not reachable from the internet. PostgreSQL, the pooler, the search engine and the application process are all bound to the loopback interface; the only ports that answer from outside are HTTP, HTTPS and SSH. SSH accepts public keys only — password and keyboard-interactive authentication are disabled — and repeated failures are banned automatically.
Web fonts are served from our own origin, so rendering a page does not hand a visitor's IP address to a font CDN. The full list of third parties that touch data is published separately. Sub-processors →
Data in transit
The entyrix.com virtual host negotiates TLS 1.2 and TLS 1.3 only; older protocol versions are not offered. HSTS is set to one year and includes subdomains, so a browser that has seen the site once will refuse to fall back to plaintext.
Every response carries a content security policy that blocks plugins and framing by third parties and pins form submissions to our own origin, together with MIME-sniffing protection, a no-referrer policy and a permissions policy that switches off camera, microphone, geolocation, payment and the rest of the powerful browser APIs. You can read these off any response with a single request.
curl -sI https://entyrix.com/ | grep -i strict-transport
Credentials and personal data
| Control | How |
|---|---|
| API keys are never stored in plaintext | SHA-256 digest at authentication time (src/api/middleware/auth.ts) |
| IP addresses are never persisted raw | SHA-256 over the IP and a salt that rotates at UTC midnight, so cross-day correlation is deliberately hard (src/lib/ip-hash.ts) |
| Access to personal data is logged per response | A row in gdpr.access_log for every response on a personal-data route — the record a data-subject request or an abuse investigation is answered from |
| Authentication secrets are compared in constant time | crypto.timingSafeEqual with a length guard, so a wrong token leaks no timing signal |
| Output escaping and URL whitelisting are centralised | One escaping helper and one protocol whitelist for every link and attribute built from external data — not re-implemented per template |
| Outbound webhooks are signed and SSRF-guarded | HMAC SHA-256 signature per delivery, with private and link-local destinations blocked |
| Rate limiting on every route | 600 requests per minute per API key, or per IP for unauthenticated traffic; only the liveness and readiness probes are exempt |
Personal-data handling is narrower than the security controls above and is documented on its own: natural persons are withheld rather than merely hidden from a user interface, dates of birth are reduced to a year for adults and suppressed for minors, and the same rules apply over the API and the MCP server as on the website. Privacy policy →
Backups
| What | Frequency | Where | Retention |
|---|---|---|---|
| Offsite, encrypted (irreplaceable set) | Daily 03:30 UTC | Cloudflare R2, client-side encrypted | 14 daily · 8 weekly · 12 monthly · 7 yearly |
| API keys | Daily 02:30 UTC | On-host dump | 30 days + 12 months |
| Application tables (PostgreSQL) | Weekly, Sunday 03:00 UTC | On-host dump | 3 weekly + 1 monthly (disk-bound) |
| Secrets file (.env) | Weekly, Sunday 04:00 UTC | AES-256-CBC + PBKDF2, passphrase-protected | Job refuses to run unencrypted |
The offsite job covers the irreplaceable set — the personal-data schema and the application tables that hold keys, subscriptions, monitoring state and sanctions matches — and encrypts it on this server before it leaves, so the storage provider holds ciphertext it cannot read. The bulk register corpus is deliberately excluded: it is re-derivable from the public sources it came from, so its recovery path is re-ingestion rather than restore.
Recovery — and how we know it works
RPO (recovery point): at most 24 hours for the irreplaceable set, bounded by the daily 03:30 UTC offsite run. Registry content restored by re-ingestion returns to the freshness of its upstream source, which is published per source on the status page.
RTO (recovery time): under 4 hours is our documented target, and it is a target rather than a measurement. The rebuild is scripted end to end and the restore path from the offsite copy is exercised weekly, but no full timed rebuild of the complete service has been performed, so we will not present a number as if it had been. If a contract needs a committed RTO, that is a conversation to have before signing, not after.
What we do not have
| Gap | What that means for you |
|---|---|
| No ISO 27001 or SOC 2 certification | There is no audited certification. Controls are documented and verifiable, not third-party attested. If your procurement requires an attestation, tell us before you start an evaluation. |
| The production volume is not encrypted at rest | Backups leaving the server are encrypted client-side and the secrets file is encrypted separately, but the running volume itself relies on the provider's physical and logical isolation rather than full-disk encryption. Almost all of the corpus is public-register data; the personal-data schema and the credential store are exactly what the encrypted offsite copy covers. |
| Single region, single host | One server in one datacentre. There is no hot standby, so an outage of that host is an outage of the service. Recovery runs from the offsite backup — see the recovery objectives above. |
| No bug-bounty programme | We do not pay for reports. We do read every one, and we will credit you if you want to be credited. |
Reporting a vulnerability
Write to [email protected]. The same address is published in /.well-known/security.txt per RFC 9116, in Slovak or English.
Please include enough detail to reproduce the issue, and give us a reasonable window to fix it before publishing. We will not pursue anyone who reports in good faith and does not exfiltrate data, degrade the service or access other people's information. Please do not run automated scanners against production — the rate limiter will simply block you and the findings will be noise.
Anything that is not a vulnerability — contracts, data questions, a data-subject request — goes to [email protected] or through the pages below.