Security isn't a checkbox. It's the product.
Every tenant on Zyra sits behind the same multi-layered defense that protects our biggest customers. Multi-tenant isolation, hardened authentication, race-safe money flow, audit-grade logging — and a hundred small things a shop owner should never have to think about.
The numbers behind the hardening
Vulnerability classes closed in a single audit pass.
Source files continuously typecheck-verified on every change.
Business verticals with capability-accurate POS defaults.
GCM on every stored credential, SMTP pass and API key.
We never sell your data — export it any time.
Deactivated accounts fall out of scope everywhere.
Every sensitive read + write in a hash-chained log.
Every layer does its own job.
No single weakness breaks isolation. The proxy, route, service, model, and UI layers each enforce their piece — and none of them trust each other.
Hard multi-tenant isolation
Every query runs through a scope-enforcing helper that stamps the tenant's business id into the filter before it ever hits MongoDB. The legacy-fallback path was removed — orphan documents without a tenant never leak into another workspace. There is no 'cluster-wide find()' in the app.
Proxy-signed tenant headers
Client-supplied x-zyra-* headers are stripped on every request and re-injected only from the verified session JWT. An attacker cannot spoof an elevated role or impersonate another tenant by crafting a header — the proxy wipes it before the route ever sees it.
Authentication that doesn't leak
Distributed rate-limit on login. Timing-uniform bcrypt compare on missing accounts so the response time is indistinguishable from a wrong password. MFA with TOTP + single-use backup codes. Per-device session rows — revoke one browser without touching the rest.
Role & permission model
Role-based access control with a scoped permission map per resource. Elevation is a cryptographic JWT flag, not a role name — a custom role named 'Admin' inside your tenant cannot promote itself into platform-level access. Deactivated accounts fall out of scope within 60 seconds across every instance.
SSRF-hardened outbound
Every webhook, integration callback, and test-send resolves DNS server-side and refuses private IPs, loopback, link-local, and cloud metadata endpoints (169.254.169.254, metadata.google.internal). Tenant admins cannot point a webhook at your VPC.
ReDoS-proof search
Every user-supplied search string is escape-regex'd before reaching MongoDB's $regex engine. Inputs like (a+)+$ that would hang a Node worker under naive string interpolation are neutralized at the helper boundary — 20+ route handlers and 3 service helpers.
Race-safe money flow
Invoice numbers, voucher consumption, loyalty points, deal usage counters, and stock adjustments all use atomic Mongo operators ($inc with conditional filters, findOneAndUpdate CAS). Two cashiers ringing up the last in-stock variant at the same moment — exactly one wins, no oversells.
Credentials never in plaintext
SMTP passwords, webhook secrets, Resend / OpenAI / Plaid / Stripe / QuickBooks / Shopify tokens are AES-256-GCM encrypted at rest and decrypted in-process only when a transport needs them. GET endpoints never echo decrypted values — the UI shows bullets.
Idempotent writes
The checkout button can be double-clicked, a webhook retried, a gateway fired twice — the invoice still lands exactly once. Per-tenant Idempotency-Key window (24 h) shared across every serverless instance via MongoDB, with stale-lock eviction built in.
Tamper-evident audit trail
Every sensitive mutation — void, refund, cancel, permission change, role assignment, support-team shadow session — writes a structured audit row that carries the actor, the before/after snapshot, and the proxy-verified tenant stamp. Reads are tenant-scoped like everything else.
Cookies done right
Every auth cookie ships httpOnly, SameSite=Lax, Secure in production, Path=/. Support-session and portal cookies are HMAC-signed with NEXTAUTH_SECRET. An old elevated cookie left behind on a shared browser is refused when the session user id doesn't match — no silent inheritance.
Reference-integrity guards
Every body-supplied ObjectId for customer, supplier, staff, or product is verified against the caller's tenant before being persisted. A tenant-A user cannot bind a tenant-B customer to their own invoice — populate() on the read path would otherwise leak cross-tenant PII.
Timeout-bounded egress
Every outbound fetch — AI provider, billing gateway, Twilio, Plaid, Intuit, Resend, Zapier — ships with an AbortSignal.timeout. A slow third-party can't hang the serverless worker until the platform kills it. Explicit 10–60 s caps tuned per provider.
Audit Safe Mode
Destructive operations (refund, void, cash adjustment) can be gated behind a PIN-unlocked 15-minute window. Rate-limit + timing-safe compare on unlock. When safe mode is off, the standard RBAC matrix still applies.
CSV export injection-proof
Every exported row is prefix-neutralized so a cell starting with =, +, -, @, \t, or \r can't execute as a formula when the file opens in Excel, LibreOffice, or Google Sheets. Your customer list downloads as data, not code.
GDPR / data portability
A tenant owner can download their entire business — customers, invoices, appointments, audit trail, settings — as an NDJSON archive in one click. Rate-limited to 1/hour. Password hashes and webhook secrets are redacted on the way out.
Schema-level tenant stamping
Every tenant-scoped model carries business/businessId/branchKey in the schema itself. Mongoose strict-mode can't silently drop the tenant stamp the way it would on a legacy model missing the fields — each one of the 50+ collections declares its scope explicitly.
Production-only debug
Debug, seed, install, and maintenance endpoints all hard-block in production regardless of how the request arrives. The installer locks itself on first success and refuses to re-bootstrap without the maintenance API key.
Quiet security. Loud results.
The best security is the kind a shop owner never has to think about. These six principles explain why we sweat the stuff that doesn't make the feature list.
You can inspect every claim
Every guarantee on this page maps to a file in the codebase. Ask for the specific helper and we'll point you to the lines. No marketing mist.
Hardened across 100+ known classes
We ran a systematic audit covering OWASP top-10, multi-tenant leak classes, financial-integrity bugs, and race-condition surfaces — then fixed them all. Not gradually. All at once.
Every layer defended
Proxy strips + injects headers. Route gates permissions. Service layer owns race-safety. Model layer enforces tenant scope. UI layer gates by role. One weakness anywhere doesn't break isolation anywhere else.
Your staff, your rules
Cashier can ring up sales but can't void invoices without a manager's PIN. Manager sees their branch's reports only. Owner sees everything. Any platform-level shadow session is fully audit-logged and auto-downgrades itself on the way out.
We don't let you DoS yourself
Pagination is clamped. Search inputs are regex-escaped. Outbound fetches are timeout-bounded. Email test + reminder endpoints are rate-limited per tenant so a compromised admin can't spam through your SMTP.
Designed for audit
Roles are a matrix. Permissions map 1:1 with routes. The audit log is append-only. The backup export is rate-limited + permission-gated. If your accountant, auditor, or insurer asks 'who did what when', the answer is always in the same place.
Security posture, in one table.
Share this with your IT or compliance team. If a row looks vague, ask — the implementation detail is in a file they can read.
Something missing from the table that your auditor needs? Get in touch — we'll map the specific control to a file and ship a one-page brief.
Found something? Tell us before anyone else.
Security researchers and customers who discover a vulnerability should email hello@zyra.com with a reproducible write-up. We acknowledge within one business day, confirm within three, and credit you on the fix's changelog entry if you want the credit.
- We never pursue good-faith researchers who stay within our scope.
- Please don't exfiltrate tenant data, spam, or DDoS — report the class, not the content.
- Coordinated disclosure — give us 30 days before going public; we'll ship faster if the class is critical.
Your data, your control
Every tenant can export their full workspace as an NDJSON archive at any time, revoke any device's session with one click, rotate their webhook secret without downtime, and permanently delete their workspace with a 30-day grace window.
Talk to our security teamRun your business on something you can trust.
Sign up takes two minutes. Trial for 30 days. Security posture documented above applies from hour zero — not after you upgrade.
No credit card for trial. Export your data anytime. Delete your workspace with a click.
