Flask is unopinionated by design. That freedom is powerful, but it also means security is your responsibility. This checklist covers the critical areas you need to harden before your app faces the public internet.
1. Use Environment Variables for Secrets
Never commit secrets to version control. Use .env files (loaded via python-dotenv) and ensure .env is in your .gitignore.
import os
from dotenv import load_dotenv
load_dotenv()
app.secret_key = os.environ.get('SECRET_KEY')
2. Enable Security Headers
Use flask-talisman to set strict transport security, content security policy, and other modern security headers.
from flask_talisman import Talisman
Talisman(app, force_https=True, content_security_policy={
'default-src': "'self'",
'script-src': ["'self'", "'unsafe-inline'"],
})
3. Protect Against SQL Injection
Always use parameterized queries. Never use Python string formatting or concatenation for SQL.
# WRONG
cursor.execute(f"SELECT * FROM users WHERE email = '{email}'")
# RIGHT
cursor.execute("SELECT * FROM users WHERE email = ?", (email,))
4. Escape Output to Prevent XSS
Jinja2 auto-escapes by default, but using |safe bypasses this. Only mark content as safe if you generated it yourself or sanitized it with bleach.
5. Implement Rate Limiting
Protect login and sensitive endpoints from brute-force attacks.
from flask_limiter import Limiter
limiter = Limiter(app, key_func=lambda: request.remote_addr)
@app.route('/login', methods=['POST'])
@limiter.limit("5 per minute")
def login():
...
6. Use HTTPS in Production
Obtain a free certificate from Let's Encrypt and redirect all HTTP traffic to HTTPS. Set SESSION_COOKIE_SECURE = True so cookies are only sent over TLS.
7. Validate and Sanitize All Input
Use WTForms with validators. Never trust client-side validation alone. Validate file uploads for type and size.
8. Keep Dependencies Updated
pip list --outdated
pip install --upgrade flask werkzeug jinja2
Summary
| Area | Tool / Approach |
|---|---|
| Secrets | python-dotenv |
| Headers | flask-talisman |
| SQL Injection | Parameterized queries |
| XSS | Jinja2 autoescape + bleach |
| Brute Force | flask-limiter |
| Transport | Let's Encrypt + HTTPS redirect |
Security is not a feature you add at the end. It is a habit you build into every line of code.
Comments (0)
No comments yet. Be the first!
Leave a Comment