KoaichGet Koaich →
/ WEB-TIER SECURITY · THE BROWSER THREAT MODEL

Browsers concede a wider attack surface. Here's what we do about it.

Some encrypted-messaging tools (Signal, for example) refuse to ship a browser app. They have a reason. We took the harder path — and built around the actual problems instead of working around them by skipping the web tier entirely.

IN PLAIN ENGLISH

Koaich is a Progressive Web App — you get it from app.koaich.com, not from Apple's App Store or Google Play. The honest trade-off: browsers add a few risks native apps don't (extensions can read JS memory, infrastructure compromise reaches users on next load). The page below lists each risk and the specific mitigation we ship. The short version: PWA gives up two narrow properties native apps have and gains three the app stores don't — no third-party origins, forced re-unlock per session, no app-store telemetry linked to your Apple ID or Google account.

Pre-launch · No spam · Unsubscribe anytime

§ 1

The honest framing

A browser-served app is structurally weaker than a native one for three concrete reasons:

  • Code delivery per session. Every page load fetches JavaScript from the server. The same vendor that ships our standard code could ship malicious code to a single user — and unless something catches it, that user has no way to know. Native apps install signed binaries once.
  • Browser storage is exposed. IndexedDB and localStorage are readable to any script running on our origin, including malicious browser extensions that the user installed for unrelated reasons. Native apps use OS keystores that are isolated from app-layer code.
  • No OS-level secure enclave. Modern phones and laptops have hardware-backed key storage (Secure Enclave, TPM, StrongBox). Browsers don't have direct access to these — unless you go through WebAuthn, which we do.

Calling the browser a fundamentally weaker surface isn't controversial. Treating it as un-improvable is. Below is exactly what we ship today, and exactly what we're building next.

§ 2

What we ship today

ZERO THIRD-PARTY SCRIPTS
LIVE

No analytics SDKs, no ad pixels, no chat widgets, no fingerprinting libraries, no Google Fonts (we self-host every typeface we use), no CDN-served assets, no preconnects to off-domain hosts. Audit a page load on this marketing site and the only origin in flight is koaich.com. We measure on our own infrastructure.

Caveat on the product app: when the user has opted into Calendar or Gmail integrations on the Koaich product app, the browser connects directly to Google's API endpoints under the user's own OAuth grant. Those connections go from the user's device to Google — we don't proxy them or retain Google's responses server-side. A reviewer reading the product-app CSP will see Google domains in connect-src for this reason; they are user-opt-in integrations, not vendor analytics.

WEBAUTHN PASSKEYS — EVERYWHERE
LIVE

Authentication uses WebAuthn passkeys — your authenticator (iCloud Keychain, Google Password Manager, 1Password, hardware key) signs challenges directly. The private key never leaves the authenticator. No password fields, anywhere. Phishing-resistant by construction; the browser refuses to honor a challenge from a wrong origin.

Same passkey, same credential store, same hardware backing on iOS Safari, Android Chrome, and desktop browsers — that's what PWA + WebAuthn gets you. There's no "native passkey" vs "web passkey" distinction in our threat model.

HTTPS-ONLY (HSTS)
LIVE

HTTP Strict Transport Security with a two-year max-age tells the browser to refuse HTTP entirely for koaich.com — preempting downgrade attacks at the network layer.

CONTENT SECURITY POLICY (THIRD-PARTY BLOCKED)
LIVE

Our CSP locks every off-origin loader: connect-src is self + Supabase only; img-src is self + data + blob; font-src is self only; frame-ancestors is none (except the iframe-embeddable scorecard). No third-party JS, no third-party fonts, no third-party images can load.

COOP + COEP HEADERS
LIVE

Cross-Origin Opener Policy same-origin and Cross-Origin Embedder Policy credentialless isolate our window from cross-origin contexts. A malicious site that opens us as a popup can't inspect our state via shared memory or window handles.

REFERRER + PERMISSIONS POLICY
LIVE

Referrer-Policy: no-referrer means clicks off koaich.com don't leak which page the user was on. Permissions-Policy denies every browser feature we don't use (geolocation, camera-by-default, microphone-by-default, USB, MIDI, autoplay, payment, etc.). Reduces the surface a malicious script could probe even if it somehow ran.

§ 3

What's shipping next

STRICT INLINE-FREE CSP (NONCE-BASED)
PLANNED

The product app already runs strict CSP. The landing site you're reading uses Next.js streaming SSR, which emits inline <script> hydration data — today's CSP allows 'unsafe-inline' on script-src for that. The PLANNED tightening switches to a nonce-based CSP via middleware, so every page can drop 'unsafe-inline' while still letting Next.js's own hydration scripts run.

Note on style-src: the production app also currently allows 'unsafe-inline' on style-src because react-native-web injects CSS at runtime via dynamic <style> elements. A malicious script that bypassed script-src could in principle inject CSS (e.g. overlay clickable areas) — but the bound is set by the strict script-src first. Eliminating inline styles is bundler-side work tracked separately.

MOBILE PASSKEYS (NATIVE)
PLANNED

The web tier is passkey-only today; the mobile app still uses email + password while we integrate Apple Passkeys (iOS) and Android Credential Manager. End state: same WebAuthn ceremony as web; PRF-derived encryption keys where the device supports it (iOS 18+, recent Android), passkey-gated secure-store fallback for older devices. No password fallback in the end state — passkey or recovery, nothing else.

SUBRESOURCE INTEGRITY
PLANNED

SHA-384 integrity hashes on every script and stylesheet, so a tampered asset fails the browser's check and never runs. Already in production for the app's critical-path bundles; the rest of the bundle graph plus the landing site are next.

ENCRYPTED INDEXEDDB AT REST
PLANNED

The browser's local database currently stores ciphertext that the app reads back and decrypts in memory. We're moving to a model where every row is encrypted under a key derived from your WebAuthn authenticator. A malicious extension can read the bytes; it can't derive the wrapping key without your authenticator.

TRUSTED TYPES POLICY
PLANNED

Trusted Types converts dangerous DOM sinks (innerHTML, script.src) into typed objects that must come from a sanitizer. Kills the last category of XSS even when CSP is bypassed by a future browser bug.

REPRODUCIBLE BUILDS
PLANNED

Every release will be a deterministic build from a tagged Git commit. Anyone can rebuild the source and verify the deployed JavaScript bundle matches, byte-for-byte. Closes the "vendor pushed different code to one user" attack — anyone who suspects we did would be able to prove it.

BUNDLE TRANSPARENCY LOG
PLANNED

Each release signs its bundle hash into a public transparency log (Sigstore / Rekor). A small browser extension (ours, optional) verifies the loaded bundle against the log before letting the app execute. This is the property that makes a web client meaningfully verifiable end-to-end.

ENCRYPTED VAULT LABELS + INVITE PAYLOADS + CONTACT-APPROVAL DATA
LIVE

Vault names + descriptions, vault invite payloads, and vault contact-approval data are now ciphertext-only server-side. Cleartext columns were dropped from vaults, vault_email_invites, and vault_contact_approvals on 2026-05-17. The server has no decrypt path for any of these fields; CHECK constraints enforce ciphertext-required on every future row. Contact list entries (address book) were already encrypted via address_book.encrypted_payload. /security §6.5 tracks the per-category state.

§ 4

What this means in practice

For a security reviewer: the web tier today provides phishing-resistant auth, content-injection-resistant code delivery, isolated origin context, and zero third-party trust. The remaining gaps — local storage that's readable to extensions, no public verifiability of the deployed bundle — are roadmap items with concrete designs. Read the architecture page; ask us specifics; we'll answer.

For an everyday user: you get Koaich at app.koaich.com — same passkey, same iCloud Keychain / Google Password Manager backing native apps use, auto-locks after 60 seconds of inactivity. If you want to minimize the extension attack surface, use a dedicated browser profile or a privacy-focused browser like Brave or Firefox Focus.

Want the technical depth?

/security is the canonical architecture page. /blast-radius shows the pattern this design is built against.

Pre-launch · No spam · Unsubscribe anytime