Zum Inhalt springen / Skip to content

Security at Wavor

Your business data deserves the same protection as a bank. We don't just tell you WHAT we protect. We show you HOW.

AES-256TLS 1.32FADSGVO/GDPRUK GDPRLGPD (BR)DPDP (IN)Servere UE

Core Security

AES-256 Encryption
Sensitive fields are stored encrypted. Read without the key, they show nothing.
EU Data Centers (Hetzner DE)
Servers and customer files in Germany. Offsite backups sit encrypted outside the EU under the EU's transfer safeguards; the privacy policy names the provider.

Uptime & Infrastructure

99.9%
Uptime Target
6h
Backup Interval
90d
Longest retention
Nerd zone

It gets technical from here. You do not need to read any of it to use Wavor safely - it is here so it can be checked.

Security Architecture

How your data flows. From request to storage

STEP 1
Cloudflare Edge
DDoS protection, WAF, TLS 1.3 with 1.2 fallback. Global anycast network.
STEP 2
Cloudflare Tunnel
Origin physically unreachable. Outbound-only connection to CF, no inbound port. AOP Custom-only Trust with Wavor RSA-4096 cert.
STEP 3
Node.js App
Session validation, 2FA check, RBAC, input validation via Zod schemas.
STEP 4
PostgreSQL + Vault
Encrypted storage with AES-256. Secrets in HashiCorp Vault.
TLS 1.3 (1.2 Fallback)
Full Strict HTTPS on all 7 domains.
DDoS Protection
Edge protection before the server sees the request.
Where is data stored?
The servers are at Hetzner in Germany (Falkenstein and Nuremberg), customer files in object storage in Germany. The data centres are guarded around the clock, with biometric access. Backups and some services such as email, SMS and AI run through providers outside the EU. Those transfers are secured under the EU's rules, and the privacy policy names every provider.
How are keys secured?
All API keys and secrets in HashiCorp Vault (KV v2, encrypted, access-controlled). Automatic rotation warning at 90/180/365 days. No plaintext secrets in code, env, or logs.
How does backup work?
Automated PostgreSQL backups every 6 hours. Kept: every one for two days, one a day up to 14 days, one a week up to 90 days. Each is decrypted again and checked after encryption, and every night the newest is restored as a test. Offsite copy at Backblaze, encrypted with our own key before it leaves the server.

Defense Layers

HTTP Security Headers: 14 hardened directives

CSP Level 3 (21 Direktiven)
Enforce mode. Maximum W3C standard incl. script-src-elem/-attr granular, Trusted-Types on admin subdomain, manifest/worker/media-src whitelist.
HSTS (Strict-Transport-Security)
max-age 1 year, includeSubDomains, preload enabled.
X-Frame-Options
DENY. No clickjacking via iframes.
X-Content-Type-Options
nosniff. Browsers cannot misinterpret MIME types.
Referrer-Policy
strict-origin-when-cross-origin.
Permissions-Policy
Camera, microphone, geolocation. All disabled by default.
COOP (Cross-Origin-Opener-Policy)
same-origin. Isolates browsing context.
CORP (Cross-Origin-Resource-Policy)
same-site. Resources cannot be embedded cross-origin.

Independently verifiable: Mozilla's HTTP Observatory grades the headers of wavor.io A+. A test asks Mozilla for the result again every night. https://developer.mozilla.org/en-US/observatory/analyze?host=wavor.io(developer.mozilla.org)

Account Security

2FA: TOTP / SMS / Email
Three methods for the second factor. Backup codes single-use.
Device Recognition
Instant notification on new devices via email with IP + User-Agent.
Session Management
View active sessions, terminate individually or sign out all at once.
Brute-Force Protection (3 layers)
5 fails per email / 15min lockout. 10 per IP / 1h. 5 distinct emails from one IP / 24h ban.
Cloudflare Turnstile Captcha
Bot protection without click-puzzle. Script loaded with crossOrigin anonymous + no-referrer. No session leak to Cloudflare.
Bcrypt Password Hashing (cost 12)
Every guess costs computing time, which makes list attacks unaffordable. Passwords >= 12 chars, zxcvbn strength check.
Zod Input Validation
All API input validated server-side via Zod. Drizzle-Zod as single-source-of-truth with DB schema.
Rate limiting with a sliding window
A sliding window rather than fixed blocks, so a limit is not handed out afresh at the top of every minute. The counter currently lives in the individual worker process; once Redis is configured, all processes share one.

Advanced Controls

Fine-Grained RBAC (fail-closed)
Role + HTTP-method aware: GET needs view, POST/PATCH need edit, DELETE needs delete. Missing permission = 403, never bypass.
Multi-Tenant Isolation
companyId-scope on every DB query. No data leak between tenants.
Audit Logs
Every mutation logged via eventLog + AuditLogger. Immutable trail with userId, companyId, action, entity.
Approval by two people
Four actions need two approvals: changes to legal values, prices and terms, and a new sub-processor. While only one person is authorised, that person decides alone. The rule takes effect once there is a second.
Secret Rotation Policy
Automatic warning at 90/180/365 days via secretRotation.ts.
PII Masking in Responses
Email, IBAN, phone masked for team-members without PII access. piiMasking.ts central.
Log Scrubbing
All logs are centrally scrubbed. Zero PII in logs, monitoring or debug output.
API Keys with Scopes
Granular permissions with expiration via apiKeyAuth.ts.
Soft-Delete & Recovery
28-day recovery of deleted data. deletedAt column with automatic query filter.
Data export
Full JSON export of all user data in one request. Deletion via DSAR flow (Art. 17).

Data Protection

Concrete technical measures

Field-Level Encryption (AES-256-GCM)
IBAN, tax-ID, social-security, bank-details, TOTP 2FA secrets and one-time codes (login/verification/reset): AES-256-GCM with 96-bit IV, 128-bit auth-tag. Random IV per encrypt.
Fail-closed Encryption
Without ENCRYPTION_KEY in production: server refuses to start. No plaintext fallback (GDPR Art. 32 lit. a).
Tamper Detection (GCM)
AES-GCM auth-tag detects any ciphertext tampering. Decrypt fails hard. Never silent accept.
HMAC-SHA256 Search Hashes
Encrypted fields stay searchable via deterministic HMAC. Separate key (Key-Separation per NIST SP 800-57).
Vault Key Management
ENCRYPTION_KEY + SESSION_SECRET + all API keys in HashiCorp Vault (KV v2). No plaintext in code, env, or logs.
Key Versioning for Rotation
Ciphertext format v1:iv:data:tag. Rotatable to new version without data loss.

Supply Chain Security

Protection against compromised dependencies (event-stream 2018, ua-parser-js 2021)

Dependencies as a build gate
Every build checks all dependencies against the vulnerability database. New findings block; known ones sit in a dated baseline that may only shrink.
Dependabot Alerts
GitHub Dependabot checks daily against CVE database. Automatic security PRs.
Lockfile committed
package-lock.json in repo. Prevents CI from pulling different versions than local.
SSRF protection on outbound fetches
Every address that comes from user input is checked before Wavor fetches it. Private networks are blocked, and each redirect is checked again instead of being followed blindly.
Auto Security Patches
unattended-upgrades installs operating-system security fixes automatically.
External Scripts: CORS + Referrer
Turnstile (Cloudflare) loaded with crossOrigin anonymous + referrerPolicy no-referrer. No credential leak.

Monitoring & Observability

Error Tracking (self-hosted)
Real-time error alerts with stack traces.
Metrics (Prometheus + Grafana)
Request latency, DB queries, memory, custom business metrics.
Server Monitoring
Uptime, CPU, memory, disk: 24/7 automated checks.

File-Upload Security (7-Layer Stack)

Protection against malware, polyglot attacks, SVG-XSS, path-traversal, MIME-sniffing

Layer 1: Absolute Size Gate (100 MB)
Hard cap against zip bombs + DoS. Multer + defense-in-depth.
Layer 2: Per-Type Size Gate
Images 5 MB, PDF 20 MB, video 100 MB. Type-specific limits.
Layer 3: MIME Whitelist + Blocklist
22 types allowed. HTML/JS/EXE/SH/JAR explicitly blocked (XSS vectors).
Layer 4: Filename Sanitization
Path-traversal (../), null-byte, Windows-reserved names blocked.
Layer 5: Magic-Byte Validation
File content MUST match extension + MIME. File-type library detects 'evil.exe renamed picture.jpg' attacks.
Layer 6: SVG Sanitization
DOMPurify strips embedded <script> tags from SVGs. Without sanitize, SVG upload is common XSS vector.
Layer 7: virus scan
Server-side virus scan before storage, provided the scanner is running on the server. If it is missing, that is logged rather than passed over silently.

XSS Defense in Depth (4 Layers)

Stored, reflected, DOM, supply-chain XSS. All vectors covered

Layer 1: React JSX Auto-Escape
All user inputs escaped by default. <script> tags rendered as text, never executed. Code rule: never dangerouslySetInnerHTML with user input.
Layer 2: DOMPurify Sanitizer
sanitizeProse() + sanitizeEmailPreview() clean article-HTML, email-previews + markdown. Removes <script>, <iframe>, on*-handlers, javascript:/data: URIs.
Layer 3: CSP script-src 'self'
Even if layers 1+2 fail: browser blocks foreign scripts. Whitelist only for Stripe + Turnstile captcha.
Layer 4: Trusted-Types (Admin)
require-trusted-types-for 'script' on admin.wavor.io forces every DOM manipulation through a policy. Prevents library bugs from causing DOM-XSS.

Certification Roadmap

We are transparent: We are building up and don't have formal certifications yet. But we already implement the standards and are actively working towards them.

DSGVO / GDPR (EU)
Implemented
UK GDPR (Data Protection Act 2018)
Implemented
LGPD (Brasilien)
Implemented
DPDP Act 2023 (Indien)
Implemented
AVG (Niederlande)
Implemented
FADP (Schweiz)
Implemented
ePrivacy (Cookie-Consent)
Implemented
DSA (Digital Services Act)
Implemented
SOC 2 Type II
Planned
ISO 27001:2022
Planned
ISO 27017 + 27018 (Cloud)
Planned
ISO 27701 (Privacy)
Planned
ISO 42001 (AI Management)
Planned
BSI C5 Type II
Planned
CSA STAR Level 1
Planned

We additionally align with the EU AI Act, NIS2 and GoBD (German bookkeeping). These are regulations, not certifications.

Report Security Issue

Found a vulnerability? Report it confidentially to our team. We take every report seriously and will get back to you as quickly as possible.