Spaces:
Running
Security
Access Control
- Optional Access Keys:
ACCESS_KEYSenvironment variable for usage restriction - Rate Limiting: Applied to search and inference endpoints
- Server-side Validation: Access keys verified before proxying to SearXNG
- Key Timeout:
ACCESS_KEY_TIMEOUT_HOURScontrols cache duration
Access Key Validation Flow
- User enters access key on the AccessPage UI
- Client hashes the key client-side using argon2id
- Server validates the hash against configured
ACCESS_KEYSviavalidateAccessKeyServerHook - On success: key hash is stored in localStorage with timestamp
- On subsequent loads,
useAccessKeyValidationinApp.tsxcallsverifyStoredAccessKey()to check if the cached key is still valid - If expired (based on
ACCESS_KEY_TIMEOUT_HOURS), user is prompted to re-enter
Whether access keys are enabled is read at runtime from /api/config. When that
request fails, the app shell refuses to render rather than assuming access keys
are off, so a request that never arrives cannot skip the access key page.
/api/config Exposure
/api/config is unauthenticated by design: the client needs it before it can
prove anything, and the access key page itself depends on it. It returns only
whether a feature is on plus its display defaults, and never returns
ACCESS_KEYS, INTERNAL_OPENAI_COMPATIBLE_API_KEY, or any other secret. Adding
a field to ServerConfig in shared/serverConfig.ts publishes it to anyone who
can reach the instance, so keep secrets out of that interface.
Search Token Lifecycle
Every HTTP request from client to backend carries a token query parameter for CSRF protection:
- Token Generation: On build/startup,
regenerateSearchToken()writes a random token to{os.tempdir()}/minisearch-token, readable only by the user running the build (0600) - Client Injection: The token is injected as
VITE_SEARCH_TOKENcompile-time constant via Vite'sdefineoption - Per-Request Auth: Client includes token as
?token=parameter on all/search/textand/search/imagesrequests - Server Verification:
handleTokenVerification()insearchEndpointServerHook.tsvalidates the token before proxying to SearXNG - Session Tracking: Validated tokens are stored in an in-memory
Set<string>(verifiedTokens.ts) for session counting
Privacy
- Local-First Storage: All data stored in IndexedDB, no cloud sync
- No Tracking: No telemetry, analytics, or user tracking
- SearXNG Integration: All web searches routed through privacy-focused metasearch
- No External Requests: Optional browser-only mode for complete privacy
Data Protection
- Access Key Hashing: Access keys hashed using argon2id before storage (via hash-wasm)
- TTL-based Cleanup: Automatic cleanup of cached data
- No PII Collection: No personally identifiable information stored
- User Control: Users can export and delete all their data
Security Best Practices
- Input validation on all endpoints
- Sanitization of user-generated content
- Search token generation: a per-build/per-startup token written to a temp file (
server/searchToken.ts), using 32 bytes from thenode:cryptoCSPRNG, with the file restricted to its owner (0600) - HTTPS enforcement in production
- Regular dependency updates via Renovate
- Argon2 Hashing: Access keys hashed using argon2id for secure validation (not storage encryption)
- Cross-Origin Isolation: COOP/COEP headers for SharedArrayBuffer security
- CSRF Protection: Search tokens validated via argon2 hash comparison, over a 32-byte digest
Server-Side Security Modules
| Module | Purpose |
|---|---|
server/searchToken.ts |
Reads/writes the CSRF token from {tempdir}/minisearch-token |
server/verifiedTokens.ts |
In-memory Set<string> of verified session tokens |
server/searchesSinceLastRestart.ts |
In-memory counters for abuse monitoring |
server/searchEndpointServerHook.ts |
Proxies text/image search to SearXNG after token verification (via handleTokenVerification) |
server/verifyTokenAndRateLimit.ts |
Verifies the Argon2 token hash and enforces rate limiting (10 requests per 10 seconds) shared by search and inference endpoints |
server/handleTokenVerification.ts |
Middleware bridge that calls verifyTokenAndRateLimit and writes 400/401/429 error responses for the search and inference endpoints |
server/configEndpointServerHook.ts |
Serves the non-secret runtime config at /api/config, including whether access keys are enabled |
Threat Model
- Local Environment: Assumes trusted local execution
- Network Requests: All external requests go through SearXNG proxy
- AI Models: Models run locally or through trusted providers
- Data Exfiltration: Prevented by local-first architecture
Related Topics
- Configuration:
docs/configuration.md- Environment variables for access control - Overview:
docs/overview.md- Security architecture and data flow - AI Integration:
docs/ai-integration.md- Privacy implications of inference types