If you set RAG_API_KEY, every endpoint needs a valid key.
Supported methods:
Authorization: Bearer <key>Authorization: ApiKey <key>X-API-Key: <key>header
Local-only mode: If RAG_API_KEY isn't set, authentication is off. That's fine for local development, but you don't want to run it that way in production.
API key validation uses Node.js crypto.timingSafeEqual with padding so it doesn't leak key length or leave the door open for timing attacks.
CORS is set up through the CORS_ORIGINS environment variable.
Default origins (localhost only):
http://localhost:5173http://localhost:3000http://127.0.0.1:5173http://127.0.0.1:3000
Custom setup:
- Comma-separated list:
CORS_ORIGINS=https://app.example.com,https://admin.example.com - Allow all (not recommended):
CORS_ORIGINS=*
In-memory rate limiting keeps things from getting abused:
| Setting | Default | Environment Variable |
|---|---|---|
| Window | 1 minute | RATE_LIMIT_WINDOW_MS |
| Max requests | 100 | RATE_LIMIT_MAX_REQUESTS |
Rate limit headers come back in every response:
X-RateLimit-Limit: Maximum requests per windowX-RateLimit-Remaining: Requests remainingX-RateLimit-Reset: Window reset timestamp
The HTTP server uses Helmet to set security headers:
- Content-Security-Policy: Restricts resource loading
- X-Content-Type-Options: Prevents MIME sniffing
- X-Frame-Options: Prevents clickjacking
- X-XSS-Protection: Legacy XSS protection
- Strict-Transport-Security: HTTPS enforcement (when behind HTTPS)
- Extension check: Only allowed extensions (
.pdf,.docx,.txt,.md,.html,.json) - MIME type check: Validates Content-Type header
- Magic byte validation: Uses file-type to check the actual file content
- Size limit: 100MB maximum
Database scanning is locked to paths inside ALLOWED_SCAN_ROOTS:
- Default: User's home directory
- Custom:
ALLOWED_SCAN_ROOTS=/path/one,/path/two
Symlinks get resolved before path validation so they can't be used to break out of allowed directories.
These dependency overrides are set in package.json:
| Package | Minimum Version | Reason |
|---|---|---|
tar |
>=7.5.4 |
CVE fixes for path traversal |
hono |
>=4.11.4 |
Security patches |
diff |
>=4.0.4 |
Security patches |
# Check for vulnerabilities
pnpm audit
# Auto-fix where possible
pnpm audit:fixAPI requests time out after 30 seconds to prevent resource exhaustion:
- Returns
503 Service UnavailablewithREQUEST_TIMEOUTerror code - Protects against slow loris and similar attacks
You'll want to cover these before going live:
- Set
RAG_API_KEY. Running without it in production means no authentication at all. - Specify your CORS origins instead of using
*. Lock it down to the domains that actually need access. - Put it behind HTTPS with a reverse proxy (nginx, Caddy).
- Set
NODE_ENV=productionso stack traces don't show up in error responses. - Keep an eye on rate limit headers to catch abuse patterns early.
- Use
.env.exampleas a starting point for your local config - Don't commit
.envfiles with secrets in them - Run
pnpm auditbefore deploying
If you find a security issue, report it through GitHub Security Advisories or email the repository maintainer.
Don't create public issues for security vulnerabilities.