Disclaimer: This app is a helper tool and not a substitute for professional medical advice. Always consult a dermatologist for severe allergies.
This document outlines security best practices for the Skincare Allergy Filter application, particularly for production deployments.
Never commit sensitive configuration values to version control. Use environment variables to manage secrets and environment-specific settings.
This project uses django-environ for environment variable management, which provides a clean, type-safe interface for configuration.
uv add django-environ
.env file in your project root (never commit this file):# .env
DEBUG=True
SECRET_KEY=your-secret-key-here
ALLOWED_HOSTS=localhost,127.0.0.1
DATABASE_URL=sqlite:///db.sqlite3
# For production PostgreSQL:
# DATABASE_URL=postgres://user:password@localhost:5432/dbname
.env to .gitignore:# Environment variables
.env
.env.local
.env.*.local
.env.example as a template (safe to commit):# .env.example
DEBUG=False
SECRET_KEY=generate-a-secure-key-for-production
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
DATABASE_URL=postgres://user:password@localhost:5432/dbname
settings.py to use django-environ (see implementation in settings.py):import environ
from pathlib import Path
# Build paths
BASE_DIR = Path(__file__).resolve().parent.parent
# Initialize environ
env = environ.Env(
DEBUG=(bool, False), # Default to False for safety
)
# Read .env file
environ.Env.read_env(BASE_DIR / '.env')
# Security settings from environment
SECRET_KEY = env('SECRET_KEY')
DEBUG = env('DEBUG')
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=[])
# Database configuration
DATABASES = {
'default': env.db('DATABASE_URL', default=f'sqlite:///{BASE_DIR / "db.sqlite3"}')
}
The SECRET_KEY is used for cryptographic signing and must be kept secret in production.
# Generate a new secret key
uv run python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
SECRET_KEY to version controlThe DEBUG setting should always be False in production.
# Development
DEBUG=True
# Production
DEBUG=False
ALLOWED_HOSTS prevents HTTP Host header attacks and must be configured in production.
# Development
ALLOWED_HOSTS=localhost,127.0.0.1
# Production (single domain)
ALLOWED_HOSTS=example.com,www.example.com
# Production (multiple domains)
ALLOWED_HOSTS=example.com,www.example.com,api.example.com
# Heroku
ALLOWED_HOSTS=yourapp.herokuapp.com
# DigitalOcean
ALLOWED_HOSTS=your-droplet-ip,yourdomain.com
# AWS EC2
ALLOWED_HOSTS=ec2-xx-xxx-xxx-xx.compute-1.amazonaws.com,yourdomain.com
# Render
ALLOWED_HOSTS=yourapp.onrender.com,yourdomain.com
SQLite is suitable for development but not recommended for production due to:
For production, use PostgreSQL with proper credentials:
# .env
DATABASE_URL=postgres://username:secure_password@hostname:5432/database_name
# Or with connection pooling:
DATABASE_URL=postgres://username:secure_password@hostname:5432/database_name?conn_max_age=600
Always use HTTPS in production to encrypt data in transit.
# settings.py (production only)
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000 # 1 year
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
Add to your .env:
# .env (production)
SECURE_SSL_REDIRECT=True
SESSION_COOKIE_SECURE=True
CSRF_COOKIE_SECURE=True
Django provides a comprehensive set of security settings for production deployments. These settings should be configured in settings.py with conditional logic based on the DEBUG setting.
# settings.py
import os
from pathlib import Path
# ... existing settings ...
# Production Security Settings (conditional on DEBUG=False)
if not DEBUG:
# HTTPS/SSL Configuration
SECURE_SSL_REDIRECT = env.bool('SECURE_SSL_REDIRECT', default=True)
SESSION_COOKIE_SECURE = env.bool('SESSION_COOKIE_SECURE', default=True)
CSRF_COOKIE_SECURE = env.bool('CSRF_COOKIE_SECURE', default=True)
# HTTP Strict Transport Security (HSTS)
SECURE_HSTS_SECONDS = env.int('SECURE_HSTS_SECONDS', default=31536000) # 1 year
SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool('SECURE_HSTS_INCLUDE_SUBDOMAINS', default=True)
SECURE_HSTS_PRELOAD = env.bool('SECURE_HSTS_PRELOAD', default=True)
# Security Headers
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
X_FRAME_OPTIONS = 'DENY'
# Referrer Policy
SECURE_REFERRER_POLICY = 'same-origin'
# Session Security
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Lax'
# CSRF Protection
CSRF_COOKIE_HTTPONLY = True
CSRF_COOKIE_SAMESITE = 'Lax'
Update your production .env file (see .env.example for complete template):
# .env (production)
DEBUG=False
SECRET_KEY=your-unique-production-secret-key-50-plus-characters
ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
# Database
DATABASE_URL=postgres://username:secure_password@hostname:5432/dbname
# Security Settings (optional overrides)
SECURE_SSL_REDIRECT=True
SESSION_COOKIE_SECURE=True
CSRF_COOKIE_SECURE=True
SECURE_HSTS_SECONDS=31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS=True
SECURE_HSTS_PRELOAD=True
Before deploying to production, always run Django’s built-in security check:
# Verify production security configuration
uv run python manage.py check --deploy
# Example output shows missing/incorrect settings:
# WARNINGS:
# ?: (security.W004) You have not set a value for SECURE_HSTS_SECONDS.
# ?: (security.W008) Your SECURE_SSL_REDIRECT setting is not set to True.
Fix all warnings before deploying. This command checks for:
SECURE_* settingsSECRET_KEYDEBUG=True in productionALLOWED_HOSTS configurationThe security configuration requires django-environ for environment variable management:
# Install django-environ (REQUIRED, not optional)
uv add django-environ
This package is required for this project (already used in settings.py) but may be missing from your dependencies. After installation, run:
# Sync dependencies
uv sync
# Verify installation
uv run python -c "import environ; print('django-environ installed successfully')"
Before production deployment:
DEBUG=False in production .envSECRET_KEY (50+ characters, high entropy)ALLOWED_HOSTS configured with actual domain(s)SECURE_* settings enabled (SSL_REDIRECT, HSTS, etc.)SESSION_COOKIE_SECURE, CSRF_COOKIE_SECURE)X_FRAME_OPTIONS, CONTENT_TYPE_NOSNIFF)uv run python manage.py check --deploy passes with no warningsdjango-environ installed and configured.env file excluded from version control (in .gitignore)Setting security flags in development: Only enable SECURE_SSL_REDIRECT and secure cookies when HTTPS is properly configured. Development servers (e.g., runserver) use HTTP by default.
HSTS without testing: Once SECURE_HSTS_PRELOAD=True is enabled and your site is added to the HSTS preload list, browsers will permanently refuse HTTP connections. Test thoroughly before enabling.
Missing django-environ: The project uses django-environ in settings.py but it may not be in your dependency list. Install with uv add django-environ.
Incorrect ALLOWED_HOSTS: Must include all domains/subdomains where your app is accessible. Wildcard patterns (e.g., *.example.com) are supported.
This project includes automated security scanning in CI/CD. Run these tools locally before committing:
Scans for common security issues in Python code:
uv run bandit -r allergies users skincare_project -ll
Checks dependencies for known security vulnerabilities:
uv run safety check
Prevents committing secrets to version control:
# Install gitleaks first
# Windows: choco install gitleaks
# macOS: brew install gitleaks
# Linux: see https://github.com/gitleaks/gitleaks
gitleaks detect --verbose
# Run all security checks locally (same as CI)
uv run bandit -r allergies users skincare_project -ll && \
uv run safety check && \
gitleaks detect --verbose
In production, serve static files through a web server (Nginx, Apache) or CDN, not Django.
# settings.py (production)
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATIC_URL = '/static/'
# Collect static files before deployment
# uv run python manage.py collectstatic --noinput
Consider adding these security headers in production:
# settings.py (production)
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
X_FRAME_OPTIONS = 'DENY'
For enterprise deployments, consider using dedicated secrets management:
Before deploying to production:
DEBUG = FalseSECRET_KEY (50+ characters)ALLOWED_HOSTS configured with actual domain(s).env file excluded from version controlIf you discover a security vulnerability, please email RJSimpson1004@gmail.com with:
Do not create public GitHub issues for security vulnerabilities.