Security Overview
The platform implements:- Flask-Talisman - HTTPS enforcement and security headers
- Content Security Policy (CSP) - XSS protection
- Flask-Limiter - Rate limiting for API and routes
- Flask-Login - Session management and authentication
- WTForms CSRF - Cross-site request forgery protection
- ProxyFix - Correct header handling behind proxies
Flask-Talisman
Talisman enforces HTTPS and sets security headers automatically.Configuration
HTTPS enforcement setting.Behavior:
- Production:
true(HTTPS required) - Development:
false(HTTP allowed) - Testing:
false(HTTP allowed)
Enables HTTP Strict Transport Security (HSTS).When enabled, browsers will only connect via HTTPS for the specified duration.Headers set:
Security Headers
Talisman automatically sets these headers:| Header | Value | Purpose |
|---|---|---|
X-Frame-Options | SAMEORIGIN | Prevents clickjacking |
X-Content-Type-Options | nosniff | Prevents MIME sniffing |
X-XSS-Protection | 1; mode=block | Legacy XSS protection |
Referrer-Policy | strict-origin-when-cross-origin | Controls referrer info |
Content Security Policy (CSP)
CSP prevents XSS attacks by controlling which resources can load on your pages.CSP Directives
The platform uses a comprehensive CSP that allows required third-party resources:Default policy for all resource types.Only allows resources from the same origin.
Controls JavaScript sources.Allowed sources:
'self'- Same origin scripts'unsafe-inline'- Inline scripts (required for some libraries)'unsafe-eval'- eval() usage (dev/testing only, see below)https://cdn.jsdelivr.net- CDN for librarieshttps://cdnjs.cloudflare.com- Cloudflare CDNhttps://unpkg.com- NPM package CDNhttps://cdn.ckeditor.com- CKEditor assetshttps://polyfill.io- Browser polyfills
Controls whether Set this in your
'unsafe-eval' is allowed in script-src.Behavior:- Development:
true(allowed - CKEditor 4 needs this) - Testing:
true(allowed) - Production:
false(blocked by default)
CKEditor 4 and MathLive use
eval() and new Function(). If you need these in production, set:.env file or override in app/__init__.py.Controls CSS sources.Allowed sources:
'self''unsafe-inline'- Required for inline styles- CDNs: jsdelivr, cdnjs, Google Fonts, unpkg, CKEditor
Controls font sources.Allowed sources:
'self'https://fonts.gstatic.com- Google Fonts- CDNs: cdnjs, unpkg, CKEditor
data:- Data URIs for embedded fonts
Controls image sources.Allowed sources:
'self'data:- Data URIs (base64 images)blob:- Blob URLs (uploaded images)https://cdn.ckeditor.com
Controls AJAX, WebSocket, and fetch() endpoints.Allowed sources:
'self'- All CDNs used by the app
https://cke4.ckeditor.com- CKEditor API
- Production domain (from
SERVER_NAMEconfig)
Controls which sites can embed this app in iframes.Set to
'self' to prevent embedding on other domains.Blocks plugins like Flash.Set to
'none' for security.Custom CSP Configuration
To modify CSP, edit thecsp dictionary in app/__init__.py:121-158:
Rate Limiting
Flask-Limiter protects against brute force and DoS attacks.Default Limits
Global rate limits applied to all routes:Enable or disable rate limiting globally.Behavior:
- Development: Enabled
- Testing: Disabled (for fast test execution)
- Production: Enabled
Backend storage for rate limit counters.Options:
memory://- In-memory (default, lost on restart)redis://localhost:6379- Redis (recommended for production)memcached://localhost:11211- Memcached
Rate Limit Strategy
Algorithm for counting requests.Options:
fixed-window- Simple, fastmoving-window- More accurate, higher overhead
Function to identify clients.Default uses the client’s IP address from the request.
Custom Route Limits
Override limits for specific routes using decorators:Rate Limit Headers
Whenheaders_enabled=True, these headers are sent:
Proxy Configuration
For deployments behind reverse proxies (Nginx, Apache, load balancers):- Correct client IP detection for rate limiting
- Proper HTTPS detection behind SSL terminators
- Accurate host headers
CSRF Protection
WTForms provides automatic CSRF protection for all forms.Enable CSRF token validation.Behavior:
- Development: Enabled
- Testing: Disabled (for easier testing)
- Production: Enabled (required)
{{ form.csrf_token }} in templates.CSRF Token Usage
Health Check Endpoints
Two endpoints for monitoring without authentication:Basic liveness check.Response:Always returns 200 if the app is running.
Readiness check with database connectivity.Responses:Use this for Kubernetes readiness probes.
Production Security Checklist
- Set a strong
SECRET_KEYenvironment variable - Use PostgreSQL instead of SQLite
- Enable HTTPS on your hosting platform
- Set
FLASK_ENV=production - Configure
SERVER_NAMEfor your domain - Use Redis for rate limiting (
RATELIMIT_STORAGE_URI) - Review CSP directives for your needs
- Enable
LOG_TO_STDOUTif using Docker/Kubernetes - Set up database backups
- Change default admin password from init_db.py
- Review ProxyFix settings for your deployment
- Test rate limiting with expected traffic
Troubleshooting
CSP Violations
If resources are blocked:- Check browser console for CSP errors
- Identify the blocked resource URL
- Add the domain to appropriate CSP directive in
app/__init__.py
Rate Limit Issues
If legitimate users are blocked:- Check current limits in
app/__init__.py:21-26 - Adjust limits for specific routes
- Consider using Redis for distributed rate limiting
HTTPS Redirect Loop
If you see infinite redirects:- Check if your proxy is terminating SSL
- Verify ProxyFix configuration
- Set
X-Forwarded-Protoheader on your proxy
Next Steps
Environment Variables
Review all environment configuration options
Database Configuration
Set up secure database connections