If you discover a security vulnerability in this project, please report it responsibly:
- DO NOT open a public issue
- Email the maintainer directly with details
- Allow reasonable time for a fix before public disclosure
NEVER commit sensitive data to version control:
- ✅ Use
.envfile for all secrets - ✅ Keep
.envin.gitignore - ✅ Use
.env.exampleas a template (without real values) - ❌ Never hardcode passwords, API keys, or secrets in code
Example .env structure:
SECRET_KEY=your-secret-key-here DEBUG=True EMAIL_HOST_PASSWORD=your-email-password
Generate a strong Django secret key:
from django.core.management.utils import get_random_secret_key print(get_random_secret_key())
- Minimum 50 characters
- Use random, unpredictable values
- Rotate regularly (especially after suspected compromise)
- Never reuse across environments
For Admin/User Accounts:
- Minimum 8 characters (enforced by Django validators)
- Mix of uppercase, lowercase, numbers, and symbols
- Avoid common passwords (Django checks against common password list)
- Use password managers for strong, unique passwords
Password Hashing:
- System uses Argon2 (if installed) or PBKDF2
- Passwords are never stored in plain text
- Password reset uses secure token-based system
Development:
- SQLite is fine for development
- Keep
db.sqlite3in.gitignore - Never commit database files with real user data
Production:
- Use PostgreSQL or MySQL
- Enable SSL/TLS for database connections
- Use strong database passwords
- Restrict database access to application server only
- Regular backups with encryption
Update config/settings.py or .env:
DEBUG=False SECRET_KEY=<new-production-secret-key> ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
- REQUIRED for production
- Obtain SSL certificate (Let's Encrypt is free)
- Configure web server (Nginx/Apache) for HTTPS
- Enable HSTS (HTTP Strict Transport Security)
The following settings are automatically enabled when DEBUG=False:
SECURE_SSL_REDIRECT = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True SECURE_HSTS_SECONDS = 31536000
Already configured in config/settings.py:
X-Frame-Options: DENY- Prevents clickjackingX-Content-Type-Options: nosniff- Prevents MIME sniffingX-XSS-Protection: 1; mode=block- XSS protectionReferrer-Policy: same-origin- Controls referrer information
- Enabled by default on all forms
- Use
{% csrf_token %}in all POST forms - AJAX requests must include CSRF token
Current configuration:
SESSION_COOKIE_AGE = 3600 # 1 hour SESSION_COOKIE_HTTPONLY = True # Prevent JavaScript access SESSION_COOKIE_SAMESITE = 'Lax' # CSRF protection
For production, sessions are secure (HTTPS only).
Gmail Configuration:
- Enable 2-Factor Authentication
- Use App Passwords (not your main password)
- Never commit email credentials
SendGrid/Other SMTP:
- Use API keys instead of passwords where possible
- Rotate API keys regularly
- Monitor for unauthorized usage
If implementing file uploads:
- Validate file types and extensions
- Limit file sizes
- Scan for malware
- Store uploads outside web root
- Use unique, random filenames
The system includes basic rate limiting middleware:
- Login attempts are limited
- Account lockout after failed attempts
- Protects against brute force attacks
- Always use Django ORM (never raw SQL)
- If raw SQL is necessary, use parameterized queries
- Never concatenate user input into SQL
Good:
User.objects.filter(email=user_email)
Bad:
cursor.execute(f"SELECT * FROM users WHERE email='{user_email}'")
- Django auto-escapes template variables
- Use
|safefilter only for trusted content - Sanitize user input before display
- Admin: Full access
- Manager: Business operations
- User: Limited access
- Viewer: Read-only
Enforce permissions in views:
from django.contrib.auth.decorators import login_required from apps.accounts.decorators import role_required @login_required @role_required(['Admin', 'Manager']) def sensitive_view(request): # Only Admin and Manager can access pass
- Validate all user input
- Use Django forms for automatic validation
- Sanitize data before processing
- Never expose stack traces to users (set
DEBUG=False) - Log errors securely
- Use custom error pages (400, 403, 404, 500)
- Log security events (failed logins, permission denials)
- Protect log files (don't commit to version control)
- Rotate logs regularly
- Keep Django and packages updated
- Run
pip list --outdatedregularly - Monitor security advisories
- Use
pip-auditto check for vulnerabilities:
pip install pip-audit pip-audit
Before deploying to production:
-
DEBUG=Falsein production - Strong, unique
SECRET_KEY -
ALLOWED_HOSTSconfigured correctly - HTTPS/SSL enabled
- Database using PostgreSQL with strong password
- Email configured with secure credentials
- Static files collected (
python manage.py collectstatic) - Media files stored securely
- Backups configured and tested
- Monitoring and logging enabled
- Security headers verified
- Dependencies updated
-
.envfile secured (not in version control) - Admin scripts with hardcoded passwords removed
- Rate limiting configured
- Error pages customized (no debug info)
- Review access logs for suspicious activity
- Check for failed login attempts
- Update dependencies
- Review user accounts and permissions
- Test backup restoration
- Security audit
- Rotate secrets and API keys
- Review and update security policies
❌ Bad:
admin_password = 'admin123' EMAIL_HOST_PASSWORD = 'mypassword'
✅ Good:
admin_password = os.getenv('ADMIN_PASSWORD') EMAIL_HOST_PASSWORD = os.getenv('EMAIL_HOST_PASSWORD')
❌ Bad:
DEBUG = True # In production
✅ Good:
DEBUG = os.getenv('DEBUG', 'False') == 'True'
❌ Bad:
- admin/admin
- password123
- 12345678
✅ Good:
- Use password generators
- Minimum 12 characters for admin accounts
- Mix of character types
❌ Bad:
- Committing
.envto GitHub - Hardcoding
SECRET_KEYin settings.py - Sharing secrets in chat/email
✅ Good:
- Use environment variables
- Use secret management tools
- Rotate keys regularly
If a security breach occurs:
-
Immediate Actions:
- Take affected systems offline if necessary
- Change all passwords and secrets
- Review access logs
-
Investigation:
- Determine scope of breach
- Identify vulnerability
- Document timeline
-
Remediation:
- Fix vulnerability
- Update security measures
- Notify affected users (if applicable)
-
Post-Incident:
- Update security policies
- Implement additional safeguards
- Train team on lessons learned
For security concerns, please contact the project maintainer.
Remember: Security is everyone's responsibility! 🔒