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()— rawBearer <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
| Severity | Examples | Acknowledgement | Fix target |
|---|---|---|---|
| Critical | Auth bypass, account takeover, master-key leak, RCE | ≤ 72h | ≤ 7 days |
| High | Stored XSS reaching another user, privilege escalation | ≤ 72h | ≤ 14 days |
| Medium | Reflected XSS, CSRF on sensitive action | ≤ 72h | ≤ 30 days |
| Low | Information disclosure without PII, missing security header | ≤ 7d | best-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 :
- 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-fieldscall) but the LLM provider (Anthropic) is the destination, not a target of MITM substitution. - 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 viareact-native > react-devtools-core.react-devtools-coreis a dev-only Metro overlay used when runningexpo start; it is not bundled into the EAS production build that ships to Apple.undici(high, header injection + WebSocket DoS) — pulled in viaexpo > @expo/cli.@expo/cliis 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 fixnon-breaking to clearwsandqs(closes WebSocket memory disclosure, qs comma-format DoS). - Remaining 3 vulnerabilities (1 low, 2 moderate) are all build-time
only —
postcssXSS viastringify()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 fixinfcba102: closeshonoadvisories (12 GHSA, including JWT bypass and Set-Cookie injection — we don't use hono directly, it was transitive via@modelcontextprotocol/sdk),qs,ws,expresstransitive. - Remaining 1 low-severity finding is
esbuildvia thetsxdev 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/.