Skip to main content
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:
ServiceTriggered by
OpenAI APIAI chat, Whisper transcription
Anthropic APIMulticam EDL generation
AssemblyAI / DeepgramCloud transcription
PiAPI / Kling AIAI video generation
YouTube Data APIVideo 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

KeyService
openaiOpenAI API
assemblyaiAssemblyAI transcription
deepgramDeepgram transcription
piapiPiAPI video generation
kieaiKie.ai
youtubeYouTube Data API
klingAccessKey / klingSecretKeyKling 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:
BridgeRestriction
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]:
PatternExample
OpenAI / Anthropic keyssk-proj-..., sk-ant-...
Bearer tokensBearer eyJ...
x-api-key header valuesx-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:
  1. 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.
  2. Same-user local processes can read the .ai-bridge-token file and make tool calls to the editor.
  3. Malicious browser extensions with storage access or the ability to inject scripts into the page are not defended against.
  4. Compromised same-origin code (for example, a supply-chain attack on a dependency) can access all in-page state.
  5. No CSP headers in development. The Vite dev server does not set Content-Security-Policy headers. Production deployments should configure appropriate CSP.
  6. 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:
  1. Do not open a public GitHub issue.
  2. Contact the maintainers privately.
  3. Include steps to reproduce.
  4. Allow reasonable time for a fix before public disclosure.

Build docs developers (and LLMs) love