This application implements a dual CSP strategy to balance security with development experience.
Location: index.html meta tag
In development mode, CSP allows:
unsafe-eval- Required for Vite's Hot Module Reloading (HMR)unsafe-inline- Required for style injection during developmentws://localhost:*- Required for Vite's WebSocket connection
Rationale: Without these directives, HMR would not work and development would be significantly slower.
Location: src/main/index.ts session headers
In production (packaged app), CSP enforces:
- ❌ No
unsafe-eval- Scripts must be pre-compiled - ✅
unsafe-inlinefor styles only (required by ReactQuill editor) - ✅
'self'for scripts - Only bundled code can execute - ✅ Whitelisted external domains for API calls
The following domains are allowed for network requests:
-
Google OAuth & APIs:
https://accounts.google.com- OAuth authenticationhttps://oauth2.googleapis.com- Token exchangehttps://www.googleapis.com- API discoveryhttps://gmail.googleapis.com- Gmail APIhttps://sheets.googleapis.com- Google Sheets APIhttps://script.google.com- Apps Script Web App endpoints
-
LLM Providers:
https://generativelanguage.googleapis.com- Google Gemini APIhttps://api.openai.com- OpenAI API
- ✅ Cross-site scripting (XSS) attacks
- ✅ Injection of malicious scripts
- ✅ Unauthorized API calls to unknown domains
- ✅ Data exfiltration to unauthorized servers
⚠️ Development mode allowsunsafe-evalfor HMR⚠️ This is a standard practice for Electron + Vite apps- ✅ Production build removes all unsafe directives
- ✅ Warning disappears when app is packaged
To verify CSP is working:
-
Development: Run
npm run electron:dev- Warning will still appear (expected, due to HMR needs)
-
Production: Package the app with
npm run build- No CSP warning should appear
- Only whitelisted domains can be accessed
Beyond CSP, this app implements:
- Context Isolation: Enabled in
webPreferences - Node Integration: Disabled in renderer process
- Preload Script Security: Uses IPC for controlled API access
- Encrypted Config Storage: Uses electron-store with encryption
- Apps Script: API keys pulled via authorized App Script endpoints, avoiding static API keys stored locally in unprotected configs
- OAuth Tokens: Refresh tokens encrypted in electron-store
If you need to add a new external API:
- Add the domain to
index.html(development) - Add the domain to
src/main/index.tssession handler (production) - Update this document with the reason for the addition