From 00482fc332170c8640352826b3438d19d08e2ca2 Mon Sep 17 00:00:00 2001 From: "shakespeare.diy" Date: Thu, 24 Sep 2026 18:15:19 +0700 Subject: [PATCH] Security polish (audit F5-F6): disable broad allowMixedContent on Android (loopback cleartext stays via network_security_config); document CVM client's intentional fixed data-relay set + IP-disclosure privacy note Co-authored-by: shakespeare.diy --- capacitor.config.ts | 12 ++++++++++-- src/hooks/useCVMClient.ts | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/capacitor.config.ts b/capacitor.config.ts index f66b20a..e0441b8 100644 --- a/capacitor.config.ts +++ b/capacitor.config.ts @@ -10,8 +10,16 @@ const config: CapacitorConfig = { androidScheme: 'https', }, android: { - // Allow mixed content for Nostr WebSocket connections - allowMixedContent: true, + // Cleartext is NOT needed here for Nostr: all public relays are wss:// and + // are unaffected by this flag. The only cleartext endpoint is the optional + // local Citrine relay (ws://127.0.0.1:4869), which is permitted specifically + // and safely via res/xml/network_security_config.xml (loopback-only), NOT by + // this broad mixed-content switch. Keeping this false avoids silently + // allowing insecure sub-resources on the https-scheme app shell. + // NOTE: if the local Citrine relay ever fails to connect on a device after + // this change, fix it in network_security_config.xml (loopback cleartext), + // not by re-enabling global mixed content. + allowMixedContent: false, // Capture input for hardware back button captureInput: true, // Use the app's dark background for the splash diff --git a/src/hooks/useCVMClient.ts b/src/hooks/useCVMClient.ts index c5af238..580b3e8 100644 --- a/src/hooks/useCVMClient.ts +++ b/src/hooks/useCVMClient.ts @@ -12,6 +12,20 @@ import { useNostr } from '@nostrify/react'; // Relay list +/** + * Fixed set of PUBLIC data relays this discovery client queries. + * + * Intentionally NOT the user's personal NIP-65 relays: this hook powers the + * community content browser (spots, events, Lab, gear, crews, shops, tours), + * and that content is spread across the community's shared relays — a user's + * own relay set would return an incomplete, inconsistent view. So we always + * query the canonical skate-data relays regardless of personal config. + * + * PRIVACY NOTE: because these are fixed, a query here reveals the user's IP to + * these three relay operators even if the user configured different relays + * elsewhere in the app. This is disclosed on the Privacy page. All data queried + * is public; the private encrypted Stash is never touched by this client. + */ const DATA_RELAYS = [ 'wss://goskatespots.nostr1.com', 'wss://relay.ditto.pub',