MasterSelects is a local-first application. All media processing, rendering, and editing happen in the browser using WebGPU, WebCodecs, and Web Workers. No user data is sent to external servers unless you explicitly invoke an external provider.
Local-first model
The trusted perimeter is the browser origin itself. Everything inside that boundary — rendering, timeline state, cached media, API keys — stays on your machine.
External services are only contacted when you explicitly trigger them:
| Service | Triggered by |
|---|
| OpenAI API | AI chat, Whisper transcription |
| Anthropic API | Multicam EDL generation |
| AssemblyAI / Deepgram | Cloud transcription |
| PiAPI / Kling AI | AI video generation |
| YouTube Data API | Video search in Download panel |
API key storage
API keys are stored encrypted in IndexedDB using the Web Crypto API:
- A unique AES-256-GCM encryption key is generated per browser instance
- The encryption key is stored in IndexedDB alongside the encrypted key material
- This protects against casual inspection (for example, browsing IndexedDB in DevTools)
The .keys.enc file export and import feature is disabled. The previous implementation used a hardcoded passphrase that provided only obfuscation, not real security. Keys must be re-entered manually on a new machine until a user-passphrase-based scheme is implemented.
Keys stored
| Key | Service |
|---|
openai | OpenAI API |
assemblyai | AssemblyAI transcription |
deepgram | Deepgram transcription |
piapi | PiAPI video generation |
kieai | Kie.ai |
youtube | YouTube Data API |
klingAccessKey / klingSecretKey | Kling AI |
Native Helper security
The Native Helper is the only component that has direct file system access outside the browser sandbox.
- Binds to 127.0.0.1 only — not accessible from other machines on the network
- Random startup Bearer token — a new token is generated each time the helper starts; both WebSocket and HTTP operations require it
- Origin validation — connections are only accepted from allowed localhost origins
- Restricted file roots — file reads, uploads, and directory searches are limited to explicit allowed directories (project root, temp, Desktop, Documents, Downloads, Videos) rather than the full home directory
AI bridge security
Both the development bridge (Vite HMR) and the production bridge (Native Helper HTTP) are restricted to local traffic:
| Bridge | Restriction |
|---|
Dev (Vite /api/ai-tools) | Active only when the Vite dev server is running; requires a per-session Bearer token; rejects non-loopback browser origins |
Production (Native Helper POST /api/ai-tools) | Binds to 127.0.0.1; requires the startup Bearer token; only forwards to a registered editor tab |
The per-session dev token is written to .ai-bridge-token in the project root. Any local process with file read access can obtain it, so this prevents cross-origin web attacks but not local process compromise.
Local file access
File reads and directory listings through either bridge are restricted to an explicit allowlist of roots:
- Project root folder
- System temp directory
- Desktop
- Documents
- Downloads
- Videos
Additional roots can be added via the MASTERSELECTS_ALLOWED_FILE_ROOTS environment variable.
Log redaction
All log output is scanned for common secret patterns before being stored in the log buffer. Detected patterns are replaced with [REDACTED]:
| Pattern | Example |
|---|
| OpenAI / Anthropic keys | sk-proj-..., sk-ant-... |
| Bearer tokens | Bearer eyJ... |
x-api-key header values | x-api-key: abc123... |
| URL key parameters | ?key=AIzaSy... |
| Long hex tokens (40+ chars) | a1b2c3d4... |
| Long alphanumeric tokens (40+ chars) | AbCd1234... |
Short strings, UUIDs, hex color codes, and normal log text are preserved.
Known boundaries
MasterSelects aims for clear, test-covered local trust boundaries — not perfect sandboxing. The following are known limitations:
-
IndexedDB encryption key stored alongside encrypted data. A same-origin script with storage access could decrypt all keys. This is defense against casual inspection, not a full security boundary.
-
Same-user local processes can read the
.ai-bridge-token file and make tool calls to the editor.
-
Malicious browser extensions with storage access or the ability to inject scripts into the page are not defended against.
-
Compromised same-origin code (for example, a supply-chain attack on a dependency) can access all in-page state.
-
No CSP headers in development. The Vite dev server does not set Content-Security-Policy headers. Production deployments should configure appropriate CSP.
-
Log redaction is pattern-based. Novel secret formats not matching the known patterns will not be redacted.
Reporting issues
If you discover a security vulnerability:
- Do not open a public GitHub issue.
- Contact the maintainers privately.
- Include steps to reproduce.
- Allow reasonable time for a fix before public disclosure.