mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-02-02 20:43:36 +00:00
Security improvements identified for the protect-api-with-api-key branch: - Use short-lived wsToken for WebSocket auth (not session tokens in URLs) - Add AUTOMAKER_HIDE_API_KEY env var to suppress console logging - Add rate limiting to login endpoint (5 attempts/min/IP) - Use timing-safe comparison for API key validation - Make WebSocket tokens single-use 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
95 lines
2.8 KiB
Markdown
95 lines
2.8 KiB
Markdown
# API Security Hardening Design
|
|
|
|
**Date:** 2025-12-29
|
|
**Branch:** protect-api-with-api-key
|
|
**Status:** Approved
|
|
|
|
## Overview
|
|
|
|
Security improvements for the API authentication system before merging the PR. These changes harden the existing implementation for production deployment scenarios (local, Docker, internet-exposed).
|
|
|
|
## Fixes to Implement
|
|
|
|
### 1. Use Short-Lived wsToken for WebSocket Authentication
|
|
|
|
**Problem:** The client currently passes `sessionToken` in WebSocket URL query parameters. Query params get logged and can leak credentials.
|
|
|
|
**Solution:** Update the client to:
|
|
|
|
1. Fetch a wsToken from `/api/auth/token` before each WebSocket connection
|
|
2. Use `wsToken` query param instead of `sessionToken`
|
|
3. Never put session tokens in URLs
|
|
|
|
**Files to modify:**
|
|
|
|
- `apps/ui/src/lib/http-api-client.ts` - Update `connectWebSocket()` to fetch wsToken first
|
|
|
|
---
|
|
|
|
### 2. Add Environment Variable to Hide API Key from Logs
|
|
|
|
**Problem:** The API key is printed to console on startup, which gets captured by logging systems in production.
|
|
|
|
**Solution:** Add `AUTOMAKER_HIDE_API_KEY=true` env var to suppress the banner.
|
|
|
|
**Files to modify:**
|
|
|
|
- `apps/server/src/lib/auth.ts` - Wrap console.log banner in env var check
|
|
|
|
---
|
|
|
|
### 3. Add Rate Limiting to Login Endpoint
|
|
|
|
**Problem:** No brute force protection on `/api/auth/login`. Attackers could attempt many API keys.
|
|
|
|
**Solution:** Add basic in-memory rate limiting:
|
|
|
|
- ~5 attempts per minute per IP
|
|
- In-memory Map tracking (resets on server restart)
|
|
- Return 429 Too Many Requests when exceeded
|
|
|
|
**Files to modify:**
|
|
|
|
- `apps/server/src/routes/auth/index.ts` - Add rate limiting logic to login handler
|
|
|
|
---
|
|
|
|
### 4. Use Timing-Safe Comparison for API Key
|
|
|
|
**Problem:** Using `===` for API key comparison is vulnerable to timing attacks.
|
|
|
|
**Solution:** Use `crypto.timingSafeEqual()` for constant-time comparison.
|
|
|
|
**Files to modify:**
|
|
|
|
- `apps/server/src/lib/auth.ts` - Update `validateApiKey()` function
|
|
|
|
---
|
|
|
|
### 5. Make WebSocket Tokens Single-Use
|
|
|
|
**Problem:** wsTokens can be reused within the 5-minute window. If intercepted, attackers have time to use them.
|
|
|
|
**Solution:** Delete the token after first successful validation.
|
|
|
|
**Files to modify:**
|
|
|
|
- `apps/server/src/lib/auth.ts` - Update `validateWsConnectionToken()` to delete after use
|
|
|
|
---
|
|
|
|
## Implementation Order
|
|
|
|
1. Fix #4 (timing-safe comparison) - Simple, isolated change
|
|
2. Fix #5 (single-use wsToken) - Simple, isolated change
|
|
3. Fix #2 (hide API key env var) - Simple, isolated change
|
|
4. Fix #3 (rate limiting) - Moderate complexity
|
|
5. Fix #1 (client wsToken usage) - Requires coordination with server
|
|
|
|
## Testing Notes
|
|
|
|
- Test login with rate limiting (verify 429 after 5 attempts)
|
|
- Test WebSocket connection with new wsToken flow
|
|
- Test wsToken is invalidated after first use
|
|
- Verify `AUTOMAKER_HIDE_API_KEY=true` suppresses banner
|