ContextPilot implements multiple layers of security to protect your data and ensure safe operation.
All user inputs are validated before processing:
- Content Length Limits: Content is limited to 10,000 characters by default
- Tag Validation: Maximum 20 tags, each up to 50 characters
- Character Sanitization: Control characters and null bytes are removed
- Empty Input Rejection: Empty or whitespace-only inputs are rejected
All text inputs are automatically sanitized:
- Removal of null bytes (
\x00) - Removal of control characters (except newlines and tabs)
- Trimming of leading/trailing whitespace
- Preservation of valid Unicode characters
Cross-Origin Resource Sharing (CORS) is configurable via environment variables:
CONTEXTPILOT_CORS_ORIGINS=["http://localhost:3000", "https://yourdomain.com"]Security Best Practice: Never use ["*"] in production. Always specify exact allowed origins.
Enable API key authentication for production deployments:
CONTEXTPILOT_ENABLE_AUTH=true
CONTEXTPILOT_API_KEY=your-secure-random-key-here
CONTEXTPILOT_API_KEY_HASH=When enabled, all API requests must include the header:
X-API-Key: your-secure-random-key-here
Generating a Secure API Key:
python -c "import secrets; print(secrets.token_urlsafe(32))"Rotating API Keys (recommended):
- Endpoint:
POST /security/api-key/rotate - Auth: current
X-API-Keyis required when auth is enabled - Optional signing: respects request-signing enforcement when enabled
- Response: returns a new plaintext key exactly once
Rotation persists only the SHA256 hash in settings storage (api_key_hash) and records lifecycle metadata:
api_key_created_atapi_key_last_rotated_atapi_key_last_used_at
After rotation, clients must switch to the returned key immediately.
ContextPilot supports optional HMAC request signing for mutating methods (POST, PUT, DELETE by default).
Enable request signing:
CONTEXTPILOT_ENABLE_REQUEST_SIGNING=true
CONTEXTPILOT_REQUEST_SIGNING_SECRET=your-shared-signing-secret
CONTEXTPILOT_REQUEST_SIGNING_MAX_AGE_SECONDS=300
CONTEXTPILOT_REQUEST_SIGNING_METHODS=["POST","PUT","DELETE"]When enabled, signed requests must include:
X-Request-Signature: <hex hmac sha256>
X-Request-Timestamp: <unix epoch seconds>
Signing payload format:
METHOD\nPATH\nTIMESTAMP\nSHA256(BODY)
If signing is enabled but the signing secret is missing, mutating endpoints return 503 until configuration is fixed.
Built-in limits prevent abuse:
- Maximum contexts per request: 20 (configurable)
- Maximum content length: 10,000 characters (configurable)
- Maximum tags per context: 20 (configurable)
Configure via environment variables:
CONTEXTPILOT_MAX_CONTEXTS_PER_REQUEST=20
CONTEXTPILOT_MAX_CONTENT_LENGTH=10000
CONTEXTPILOT_MAX_TAG_COUNT=20ContextPilot now attaches defensive HTTP response headers by default:
X-Content-Type-Options: nosniffX-Frame-Options: DENYReferrer-Policy: strict-origin-when-cross-originPermissions-Policy: geolocation=(), microphone=(), camera=()Content-Security-Policybaseline
For HTTPS requests (X-Forwarded-Proto: https), HSTS is added:
Strict-Transport-Security: max-age=<configured>; includeSubDomains
Configuration:
CONTEXTPILOT_ENABLE_SECURITY_HEADERS=true
CONTEXTPILOT_HSTS_MAX_AGE_SECONDS=31536000ContextPilot persists security outcomes to the security_events database table for auditability.
Recorded categories include:
- API key auth outcomes (
missing_key,invalid_key,valid_key) - Request-signing outcomes (
missing_headers,invalid_timestamp,invalid_signature,valid_signature,misconfigured) - API key rotation outcomes (
success,auth_disabled)
Query recent events via:
GET /security/events?limit=50&offset=0&event=api_key_auth&outcome=invalid_key
The endpoint supports filters for event, outcome, and request_id.
Copy .env.example to .env and configure:
# Security Settings
CONTEXTPILOT_ENABLE_AUTH=true
CONTEXTPILOT_API_KEY=your-secure-key
CONTEXTPILOT_ENABLE_REQUEST_SIGNING=true
CONTEXTPILOT_REQUEST_SIGNING_SECRET=your-shared-signing-secret
CONTEXTPILOT_ENABLE_SECURITY_HEADERS=true
CONTEXTPILOT_HSTS_MAX_AGE_SECONDS=31536000
# CORS Settings
CONTEXTPILOT_CORS_ORIGINS=["https://yourdomain.com"]
# Rate Limits
CONTEXTPILOT_MAX_CONTENT_LENGTH=10000
CONTEXTPILOT_MAX_CONTEXTS_PER_REQUEST=20Never commit API keys or secrets to version control:
# .gitignore example
.env # Contains API keys, never commit
.env.local # Local overrides
backend/.env # Backend-specific secretsIf you accidentally commit secrets:
- Immediately rotate the compromised key in the provider's dashboard
- Scan git history to ensure previous commits are clean:
git log --all -- .env | head -20 # View history
- Remove the file from git history (if committed):
git filter-branch --tree-filter 'rm -f .env' -- --all git push origin --force --all
Ensure these sensitive items are never in version control:
- OpenAI API Key: Used for GPT models
- Anthropic API Key: Used for Claude models
- Ollama URL: If hosting remote Ollama instance
Store these in:
- Environment variables (development)
.envfile (local development only - .gitignored)- Secrets management system (production):
- AWS Secrets Manager
- HashiCorp Vault
- GitHub Secrets
- GitLab CI/CD Secrets
The backend/valid_models.json file defines available models but does not contain any secrets:
- Safe to commit to version control
- Used by sync_models.py to keep lists in sync
- Contains only model names and metadata, no API keys
See MODEL_SYNCHRONIZATION.md for details.
- Enable authentication (
ENABLE_AUTH=true) - Generate and set a secure API key
- Enable request signing for mutating endpoints
- Configure signing secret and timestamp window
- Configure specific CORS origins (no wildcards)
- Set appropriate rate limits
- Use HTTPS/TLS in production
- Keep dependencies updated
- Enable logging and monitoring
- Regular security audits
✅ Input Injection: All inputs are validated and sanitized
✅ Content Length Attacks: Strict length limits enforced
✅ Unauthorized Access: Optional API key authentication
✅ CORS Violations: Configurable allowed origins
✅ Malformed Unicode: Proper unicode handling
Always deploy behind HTTPS in production:
server {
listen 443 ssl;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:8000;
}
}Deploy behind nginx or similar for:
- Rate limiting
- SSL termination
- Request filtering
- Static file serving
Keep dependencies updated:
pip list --outdated
pip install -U <package>Monitor for suspicious activity:
- Failed authentication attempts
- Unusual request patterns
- Input validation failures
If you discover a security vulnerability, please email: security@example.com
Do not open public GitHub issues for security vulnerabilities.
- Data is stored in-memory by default (no persistence)
- No data is sent to external services (except model downloads)
- Embeddings are generated locally
If storing personal data:
- Implement data deletion on request
- Consider data encryption at rest
- Implement access logging
- Add consent mechanisms