Security Guide¶
This document describes the security architecture and best practices for AI Code UI.
Authentication¶
JWT Token Authentication¶
AI Code UI uses JSON Web Tokens (JWT) for authentication.
Flow:
- User submits credentials to
/api/auth/login - Server validates against bcrypt-hashed password
- Server issues JWT token
- Client stores token in localStorage
- Client includes token in
Authorization: Bearer <token>header - Server validates token on each request
Configuration:
Current Limitations:
- Tokens do not expire (consider implementing expiration)
- Single secret key for all tokens
- No refresh token mechanism
Recommendations:
- Set a strong
JWT_SECRETin production - Consider implementing token expiration
- Use HTTPS in production
Platform Mode¶
For single-user deployments, platform mode bypasses JWT authentication:
Behavior:
- No login required
- First user in database used for all requests
- Suitable for local development or trusted environments
API Key Authentication¶
Optional API key for external access:
When set, requests must include:
Password Security¶
Storage¶
Passwords are hashed using bcrypt before storage:
Parameters:
- Salt rounds: 10 (industry standard)
- Algorithm: bcrypt (resistant to rainbow tables)
Requirements¶
Current implementation has no password requirements. Consider enforcing:
- Minimum length (8+ characters)
- Complexity requirements
- Password history
Tool Approval System¶
AI Code UI implements a tool approval system for Claude SDK integration.
How It Works¶
- Claude SDK requests tool execution
- Backend intercepts via
canUseToolcallback - Backend sends approval request to frontend via WebSocket
- User sees approval dialog with tool name and arguments
- User approves or denies
- Backend returns decision to SDK
- SDK proceeds or cancels
Timeout:
- 55 seconds (under SDK's 60-second limit)
- Configurable via
CLAUDE_TOOL_APPROVAL_TIMEOUT_MS
Security Benefits¶
- Users control what tools execute
- Visibility into AI actions
- Audit trail of approved operations
Message Types¶
// Server → Client: Request approval
{
type: 'claude-permission-request',
requestId: 'uuid',
toolName: 'bash',
toolInput: { command: '...' }
}
// Client → Server: User decision
{
type: 'claude-permission-response',
requestId: 'uuid',
allow: true
}
Input Validation¶
Path Traversal Prevention¶
File operations validate paths to prevent directory traversal:
// Paths must be within project root
const safePath = path.resolve(projectRoot, userPath);
if (!safePath.startsWith(projectRoot)) {
throw new Error('Path traversal detected');
}
Protected Operations:
- File reading/writing
- Directory listing
- Terminal session working directory
SQL Injection Prevention¶
All database queries use prepared statements:
// Safe - uses parameterized query
db.prepare('SELECT * FROM users WHERE id = ?').get(userId)
// Unsafe - never do this
db.exec(`SELECT * FROM users WHERE id = ${userId}`)
Session ID Sanitization¶
Session IDs are restricted to alphanumeric characters:
WebSocket Security¶
Connection Handling¶
- WebSocket connections authenticated via token query parameter
- Connections closed on authentication failure
- Rate limiting on message processing
Message Validation¶
- Message types validated against whitelist
- Payload structure validated
- Large payloads rejected
CORS Configuration¶
Default configuration allows all origins:
Production Recommendations:
Credential Storage¶
Current State¶
User credentials (API keys, etc.) are stored in the database with basic encryption:
Limitations:
- Not encrypted at rest
- Accessible to database readers
Recommendations¶
- Database Encryption:
- Use SQLCipher for encrypted SQLite
-
Encrypt sensitive columns
-
Key Management:
- Store encryption keys outside database
-
Use environment variables or key vault
-
Access Control:
- Restrict database file permissions
- Use separate credentials per service
Network Security¶
HTTPS¶
AI Code UI does not enforce HTTPS internally. For production:
-
Use a reverse proxy:
-
Or use Cloudflare Tunnel:
- See
cloudflared/directory for configuration
Firewall¶
Restrict access to necessary ports:
# Allow only local access
iptables -A INPUT -p tcp --dport 3001 -s 127.0.0.1 -j ACCEPT
iptables -A INPUT -p tcp --dport 3001 -j DROP
Docker Security¶
When running in Docker:
-
Use non-root user:
-
Read-only filesystem:
-
Resource limits:
Security Headers¶
Consider adding security headers via middleware:
app.use((req, res, next) => {
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-XSS-Protection', '1; mode=block');
res.setHeader('Strict-Transport-Security', 'max-age=31536000');
next();
});
Audit Logging¶
Current implementation has basic console logging. For production:
- Log authentication events
- Log tool approvals/denials
- Log file access
- Store logs securely
Security Checklist¶
Before Deployment¶
- [ ] Set strong
JWT_SECRET - [ ] Configure HTTPS (reverse proxy or Cloudflare)
- [ ] Review CORS settings
- [ ] Set appropriate file permissions
- [ ] Configure firewall rules
- [ ] Disable platform mode unless needed
Ongoing¶
- [ ] Monitor logs for suspicious activity
- [ ] Keep dependencies updated
- [ ] Review access periodically
- [ ] Test authentication flows
- [ ] Backup database securely
Reporting Security Issues¶
If you discover a security vulnerability:
- Do not open a public issue
- Email security concerns privately
- Include:
- Description of vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (if any)
See Also¶
- Configuration - Environment variables
- Docker - Container deployment
- API Reference - Authentication endpoints