Security Policy

LifeHandler stores highly sensitive personal data (identity documents, IBAN, bank accounts…) under a zero-knowledge encryption scheme. We take security reports seriously and appreciate responsible disclosure.

Reporting a vulnerability

Do not open a public GitHub issue for security vulnerabilities.

Send a private report to security@lifehandler.fr with the subject line [security] <short description>. Include:

  • A description of the issue and its potential impact.
  • Steps to reproduce (proof of concept, screenshots, request/response pairs, etc.).
  • Your name or handle if you want public credit after the fix ships, or an explicit request to remain anonymous.

You will get an acknowledgement within 72 hours.

PGP key: not currently published. If you need encrypted communication, send an unencrypted first contact asking for an out-of-band channel.

Scope

In scope:

  • The web application at the production domain.
  • The mobile application (Expo).
  • The MCP server (https://*.functions.fnc.fr-par.scw.cloud).
  • MCP server authentication (signed Supabase JWT verified via supabase.auth.getUser() — raw Bearer <user-id> is rejected).
  • The public API routes under /api/.
  • The client-side encryption code (AES-256-GCM + Argon2id).
  • The hardcoded sensitive-keys runtime gate (src/lib/sensitive-keys.ts) that prevents hyper-sensitive fields (SSN, IBAN, ID/passport numbers, card data, passwords…) from ever being transmitted to the AI agent.
  • The 3-tier data-sensitivity model that governs both UI rendering and agent access:
    • Tier 1 (e.g. marital status, contract type) — visible by default, agent may request the value with user consent.
    • Tier 2 (e.g. email, postal address) — masked by default, eye toggle to reveal; agent is prompt-forbidden from requesting them and may only see them if the user proactively pastes the value into the chat.
    • Tier 3 (e.g. NIR, IBAN, ID/passport numbers) — masked + strong-auth-gated reveal; agent can never access these (hard-coded ABSOLUTE_BLOCKED runtime gate, no override). Full model documented in PRIVACY.md §4 and on the project Notion (Page 05 "Crypto zéro-knowledge").

Out of scope:

  • Issues reproducible only with browser extensions, malware, or physical access to an unlocked device.
  • Denial-of-service through brute volume.
  • Social engineering of the maintainer.
  • Reports against third-party services (Supabase, Vercel, Scaleway, Anthropic) — please report those directly to the vendor.

Severity & response timeline

SeverityExamplesAcknowledgementFix target
CriticalAuth bypass, account takeover, master-key leak, RCE≤ 72h≤ 7 days
HighStored XSS reaching another user, privilege escalation≤ 72h≤ 14 days
MediumReflected XSS, CSRF on sensitive action≤ 72h≤ 30 days
LowInformation disclosure without PII, missing security header≤ 7dbest-effort

Hall of fame

We will publicly credit researchers who report valid vulnerabilities, once a fix has shipped and the user has had time to update.

(Empty for now — be the first.)

What we promise

  • We will not pursue legal action against you for security research conducted in good faith on the scope above.
  • We will keep you informed of the fix progress.
  • We will not disclose your identity without your consent.
  • We will publish a post-mortem for any user-affecting incident.

Transport security

All client-server communication (mobile → MCP, mobile → /api, web → /api, mobile → Supabase, mobile → Anthropic) uses HTTPS with TLS 1.2+ enforced by the underlying platforms (iOS 14+ default ATS configuration, Android 5+ default network security config). Cleartext HTTP is rejected at the OS level — NSAllowsArbitraryLoads is left at its default false on iOS, and no usesCleartextTraffic override is set on Android.

Certificate pinning — current posture

LifeHandler does not implement TLS certificate pinning at this stage. The decision rests on two observations :

  1. The threat that pinning addresses is bounded by the zero-knowledge architecture. All user vault values (Tier 1 / Tier 2 / Tier 3) are encrypted client-side with AES-256-GCM before any transit. A successful MITM with a rogue CA would see ciphertext, not plaintext — the master key never leaves the device. The wand autofill path is the narrowest exposure (matched values transit transiently during the /api/match-fields call) but the LLM provider (Anthropic) is the destination, not a target of MITM substitution.
  2. Operational risk of pinning exceeds the marginal security gain. Pinning would couple every TLS-bearing endpoint (Supabase, MCP, Anthropic, Vercel) to a fixed cert / SPKI set that needs a coordinated app-store update on every rotation. A missed rotation locks all users out until they reinstall — a higher availability risk than the MITM threat we'd reduce, given 1.

This posture is reassessed if any of the following materialise :

  • LifeHandler stores or transmits decrypted Tier 2 / Tier 3 data for any feature (today the wand autofill is the only borderline case and it goes server-side only as an envelope to Anthropic).
  • A regulatory authority (CNIL, ANSSI, ENISA) issues a formal recommendation for pinning on personal data vaults.
  • The mobile threat-model audit (post-launch backlog) identifies a realistic MITM-exploitable surface not covered by the existing E2E layer.

Dependency vulnerabilities (npm audit posture)

npm audit reports vulnerabilities across the dependency tree indiscriminately — including transitive packages that ship only with the development toolchain and never reach the user-facing binary. We track the audit output continuously but distinguish between runtime and dev-only findings before deciding whether a fix is worth the upgrade churn.

Mobile (lifehandler-mobile)

The audit currently shows ~29 vulnerabilities, including some labelled critical or high. After tracing each one through the dependency tree :

  • shell-quote (critical, CWE-77/78) — pulled in via react-native > react-devtools-core. react-devtools-core is a dev-only Metro overlay used when running expo start ; it is not bundled into the EAS production build that ships to Apple.
  • undici (high, header injection + WebSocket DoS) — pulled in via expo > @expo/cli. @expo/cli is the developer CLI that runs on the developer's machine ; it is not included in the iOS or Android binary.
  • Moderate findings (js-yaml, postcss, uuid <11, etc.) — all transitive in the dev tooling (Babel/Metro/Jest config plumbing).

We confirmed via tabletop inspection that npm audit fix (non-breaking) attempts to bump these by pulling in react-native@0.86 side-by-side with our pinned react-native@0.81.5 (the version Expo SDK 54 requires). This duplicate-react-native tree creates a real risk of Metro/Hermes confusion at bundle time — strictly worse than the dev-only vulnerabilities it fixes. We therefore do not apply npm audit fix to the mobile repo.

npm audit fix --force would resolve everything by upgrading to Expo SDK 56, which is a breaking change across our entire stack (crypto adapter, Hermes, SecureStore, native modules). Tracked as post-MVP backlog (re-evaluate 2-3 months after launch when SDK 56 ecosystem stabilises).

Web (lifehandler)

Runtime is Vercel serverless functions — every transitive dep can potentially execute against a user request. We are more aggressive here:

  • Bumped Next.js 16.2.4 → 16.2.9 in fcba102 (closes 4 GHSA advisories including DoS, middleware proxy bypass, cache poisoning, App Router CSP-nonce XSS).
  • Applied npm audit fix non-breaking to clear ws and qs (closes WebSocket memory disclosure, qs comma-format DoS).
  • Remaining 3 vulnerabilities (1 low, 2 moderate) are all build-time only — postcss XSS via stringify() output that we never invoke with attacker-controlled CSS (Tailwind input is our own static classes).

MCP server (mcp-server)

Hosted on Scaleway Serverless Containers — runtime exposure similar to web.

  • Applied npm audit fix in fcba102 : closes hono advisories (12 GHSA, including JWT bypass and Set-Cookie injection — we don't use hono directly, it was transitive via @modelcontextprotocol/sdk), qs, ws, express transitive.
  • Remaining 1 low-severity finding is esbuild via the tsx dev dependency — not in the production bundle that Scaleway builds.

Tracking

The npm audit output is checked at each release. New runtime findings on web or MCP are addressed in the next deploy ; new dev-tooling findings on mobile are deferred to the Expo SDK 56 migration unless they can be patched without a major upgrade.


Compliance

In case of a data breach affecting users, LifeHandler commits to notifying the CNIL within 72 hours (RGPD Art. 33) and informing affected users without undue delay if the risk is high (Art. 34). The full internal procedure (detection, containment, assessment, notification, post-mortem) is documented in compliance/INCIDENT-RUNBOOK.md along with the CNIL Art. 33 notification template and user Art. 34 notification template. The internal register required by Art. 33(5) lives in compliance/breach-log/.