participatory-planner / SECURITY.md
thadillo
Security hardening and HuggingFace deployment fixes
d038974
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| Latest | :white_check_mark: |
| < Latest| :x: |
We currently only support the latest version with security updates.
## Security Features
### Authentication & Authorization
- **Token-based authentication** for all users
- **Admin tokens** generated securely with `secrets.token_urlsafe()`
- **Rate limiting** on login (10 attempts/minute) and token generation (5/hour)
- **Session security**: HTTP-only, Secure, SameSite=None cookies with 24-hour lifetime
- **No hardcoded credentials**: All tokens are generated or loaded from environment variables
### Data Protection
- **Flask secret key validation**: Fails fast in production if not set securely
- **SQLite WAL mode**: Reduces database locking and improves concurrent access
- **Input validation**: All user inputs are validated and sanitized
- **CSRF protection**: Built-in Flask CSRF protection for forms
### Infrastructure Security
- **Environment variables**: All sensitive configuration stored in `.env` (never committed)
- **Credential helper**: Git credentials managed securely, not stored in repository
- **Docker isolation**: Production deployment uses containerization
- **HTTPS only**: All production deployments require HTTPS
## Reporting a Vulnerability
We take security seriously. If you discover a security vulnerability, please follow these steps:
### 1. **DO NOT** Create a Public Issue
Please do not report security vulnerabilities through public GitHub issues.
### 2. Report Privately
Send your report to: **[[email protected]]**
Include:
- Description of the vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (if any)
### 3. Response Timeline
- **Initial Response**: Within 48 hours
- **Status Update**: Within 7 days
- **Fix Timeline**: Depends on severity
- Critical: 1-7 days
- High: 7-14 days
- Medium: 14-30 days
- Low: 30-90 days
### 4. Disclosure Policy
- We follow **coordinated disclosure**
- We will work with you to understand and fix the issue
- Public disclosure only after fix is deployed
- Credit will be given to reporters (unless you prefer to remain anonymous)
## Security Best Practices for Deployment
### For Administrators
#### 1. Environment Variables
```bash
# Generate secure Flask secret key
python -c "import secrets; print(secrets.token_hex(32))"
# Generate secure admin token
python -c "import secrets; print(secrets.token_urlsafe(16))"
```
Set in `.env` file (NEVER commit this file):
```env
FLASK_SECRET_KEY=<your-secure-secret-key>
FLASK_ENV=production
ADMIN_TOKEN=<your-secure-admin-token>
```
#### 2. Admin Token Management
- **Change the admin token** on first deployment
- **Rotate tokens** every 90 days
- **Use different tokens** for dev/staging/production
- **Never share** admin tokens publicly
#### 3. HuggingFace Spaces Secrets
For HuggingFace deployment, set secrets in Space settings:
- `FLASK_SECRET_KEY`
- `ADMIN_TOKEN`
- `FLASK_ENV=production`
#### 4. Database Security
- Regular backups of `/data/app.db`
- Monitor database size and growth
- Review admin actions logs regularly
#### 5. Token Rotation
To rotate admin token:
1. Generate new token: `python -c "import secrets; print(secrets.token_urlsafe(16))"`
2. Delete old admin token from admin panel
3. Update `ADMIN_TOKEN` in `.env` or HF Spaces secrets
4. Restart application
5. Login with new token
### For Contributors
#### 1. Never Commit Secrets
- Always check `.gitignore` includes `.env`
- Never commit:
- `.env` files
- API keys or tokens
- Database files (`.db`, `.sqlite`)
- Credentials or passwords
#### 2. Use `.env.example`
Create `.env.example` with placeholder values:
```env
FLASK_SECRET_KEY=your_secret_key_here
ADMIN_TOKEN=your_admin_token_here
FLASK_ENV=development
```
#### 3. Code Review Security Checklist
- [ ] No hardcoded credentials
- [ ] Input validation on all user inputs
- [ ] SQL injection protection (use SQLAlchemy ORM)
- [ ] XSS protection (use Flask template escaping)
- [ ] CSRF tokens on all forms
- [ ] Rate limiting on sensitive endpoints
## Known Security Considerations
### 1. SQLite in Production
- SQLite is suitable for low-to-medium traffic deployments
- For high traffic (>100 concurrent users), consider PostgreSQL
- WAL mode enabled for better concurrent access
### 2. Token-Based Authentication
- Tokens are bearer tokens (possess token = authenticated)
- Keep tokens secure and never share
- Tokens stored in secure HTTP-only cookies
- No token expiration (manual revocation only)
### 3. Rate Limiting
- In-memory rate limiting (resets on restart)
- For production, consider Redis-backed rate limiting
- Current limits:
- Login: 10 attempts/minute per IP
- Token generation: 5 per hour per IP
- Global: 200 requests/day, 50/hour per IP
### 4. File Uploads
- No file upload functionality currently
- If added, implement strict validation:
- File type whitelist
- Size limits
- Virus scanning
- Storage in isolated directory
## Security Audit History
| Date | Type | Findings | Status |
|------|------|----------|--------|
| 2025-10-14 | Internal | Hardcoded ADMIN123 token | βœ… Fixed |
| 2025-10-14 | Internal | HF token in git config | βœ… Fixed |
| 2025-10-14 | Internal | Flask secret in git history | βœ… Rotated |
| 2025-10-14 | Internal | No rate limiting | βœ… Fixed |
## References
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [Flask Security Best Practices](https://flask.palletsprojects.com/en/latest/security/)
- [SQLAlchemy Security](https://docs.sqlalchemy.org/en/latest/core/tutorial.html#using-textual-sql)
## Contact
For security concerns: **[email protected]**
---
*Last Updated: 2025-10-14*