Commit Graph
20 Commits
Author SHA1 Message Date
Keith SmithandClaude Sonnet 4.5 31a0c3c8c5 Add middleware to allow mobile app iframe embedding
Created Django middleware that detects requests from the KeepItGoing
mobile app (via User-Agent) and removes X-Frame-Options header to
allow iframe embedding.

Changes:
- Created tasks/middleware/mobile_app.py with AllowMobileAppFramingMiddleware
- Added middleware to settings after XFrameOptionsMiddleware
- Detects Capacitor WebView User-Agent patterns
- Removes X-Frame-Options only for mobile app, keeps protection for browsers

This allows the mobile app to embed the website in an iframe while
maintaining clickjacking protection for regular web browsers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 22:08:05 -07:00
Keith SmithandClaude Sonnet 4.5 de57befe3a Restore Django security headers for defense-in-depth
Re-added SECURE_CONTENT_TYPE_NOSNIFF and SECURE_BROWSER_XSS_FILTER
to Django settings. These don't conflict with NPM's "Block Common
Exploits" feature - they provide defense-in-depth by ensuring headers
are set even if the request bypasses NPM.

Security header strategy:
- NPM (primary): CSP, HSTS, Referrer-Policy, Permissions-Policy,
  X-Content-Type-Options, X-XSS-Protection via "Block Common Exploits"
- Django (backup): X-Frame-Options, X-Content-Type-Options,
  X-XSS-Protection for defense-in-depth

This follows security best practice of setting headers at multiple
layers rather than relying on a single point of control.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 18:17:34 -07:00
Keith SmithandClaude Sonnet 4.5 240a4de7ac Remove duplicate security headers - handled by NPM
Removed SECURE_CONTENT_TYPE_NOSNIFF and SECURE_BROWSER_XSS_FILTER
from Django settings to prevent duplicate headers. These headers are
now exclusively managed in Nginx Proxy Manager's Advanced config.

This fixes Mozilla Observatory error: "X-Content-Type-Options header
cannot be recognized" which was caused by the header being sent twice
(once from Django, once from NPM).

Security headers now managed in NPM:
- Content-Security-Policy
- X-Content-Type-Options
- X-XSS-Protection
- Referrer-Policy
- Permissions-Policy

X-Frame-Options kept in Django for defense-in-depth (doesn't conflict).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 18:13:32 -07:00
Keith SmithandClaude Sonnet 4.5 ec09baf9a5 Remove django-csp package - CSP now handled by NPM
Since Nginx Proxy Manager is handling Content Security Policy headers
at the reverse proxy level, removed django-csp from Django to avoid
duplication and simplify configuration.

Changes:
- Removed django-csp from requirements.txt
- Removed CSPMiddleware from middleware stack
- Removed CSP_* settings from selfhosted.py
- Added comment noting CSP is configured in NPM

CSP is now exclusively managed in NPM's Advanced configuration with:
- default-src 'self'
- script-src/style-src 'self' 'unsafe-inline' (for Django admin)
- img-src 'self' data: https:
- frame-ancestors 'none'
- And other security directives

This keeps configuration in one place (NPM) and eliminates
dependency on django-csp package.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:59:31 -07:00
Keith SmithandClaude Sonnet 4.5 e95369ffbf Add Content Security Policy (CSP) headers
Implements CSP to prevent XSS attacks and complete Mozilla Observatory
security requirements.

Changes:
- Added django-csp>=3.8 to requirements.txt
- Added CSPMiddleware to middleware stack
- Configured CSP directives in selfhosted.py:
  - default-src 'self' (only load resources from same origin)
  - script-src/style-src allow 'unsafe-inline' (needed for Django admin)
  - img-src allows https: and data: URIs
  - frame-ancestors 'none' (prevent clickjacking)
  - form-action 'self' (prevent form hijacking)

This policy balances security with Django admin functionality.
After deployment, Mozilla Observatory should show all green checks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:40:34 -07:00
Keith SmithandClaude Sonnet 4.5 00fca071bf Silence Django security warnings handled by NPM
Added SILENCED_SYSTEM_CHECKS to suppress warnings for:
- security.W004: HSTS (handled by NPM with HSTS Enabled)
- security.W008: SSL redirect (handled by NPM with Force SSL)

These warnings are intentionally suppressed because the security
features are properly configured at the reverse proxy level.

After redeploying, 'manage.py check --deploy' will show:
"System check identified no issues (0 silenced)."

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:36:13 -07:00
Keith SmithandClaude Sonnet 4.5 19ff672562 Update security settings for NPM SSL/HSTS handling
Since Nginx Proxy Manager handles SSL termination, Force SSL, and HSTS:
- Set SECURE_HSTS_SECONDS = 0 (NPM sends HSTS headers)
- Added SECURE_PROXY_SSL_HEADER to trust X-Forwarded-Proto from NPM
- Added SESSION_COOKIE_HTTPONLY for additional session security
- Documented NPM configuration: Force SSL = On, HSTS Enabled = On

This prevents duplicate HSTS headers and ensures Django correctly
detects HTTPS connections behind the reverse proxy.

Cookie security (SESSION/CSRF_COOKIE_SECURE) remains enabled as these
are application-level settings independent of the reverse proxy.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:34:03 -07:00
Keith SmithandClaude Sonnet 4.5 a06b4365ed Add production security settings for HTTPS/SSL
Fixes all 4 Django security warnings:
-  security.W004: Added SECURE_HSTS_SECONDS (1 year HSTS)
-  security.W008: Documented SECURE_SSL_REDIRECT=False (NPM handles SSL)
-  security.W012: Enabled SESSION_COOKIE_SECURE
-  security.W016: Enabled CSRF_COOKIE_SECURE

Additional security hardening:
- HSTS with subdomains and preload
- HttpOnly CSRF cookies
- XSS filter enabled
- Content type sniffing prevention
- Clickjacking protection (X-Frame-Options: DENY)

Note: SECURE_SSL_REDIRECT is intentionally False because Nginx Proxy
Manager handles SSL termination and HTTP→HTTPS redirects at the
reverse proxy level.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:33:07 -07:00
Keith SmithandClaude Sonnet 4.5 d1720bebb3 Add API root endpoint at /api/
Created /api/ endpoint that returns JSON with:
- API status
- Available endpoints
- Version information

This fixes the "Not Found" error when accessing /api/ and
provides a useful API discovery endpoint for clients.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:24:16 -07:00
Keith SmithandClaude Sonnet 4.5 695109e447 Add CSRF_TRUSTED_ORIGINS setting for self-hosted deployments
Django requires CSRF_TRUSTED_ORIGINS to be set for POST requests
(including login) when using HTTPS or non-standard ports. Without
this setting, login attempts fail with "CSRF verification failed".

The setting is now configurable via CSRF_TRUSTED_ORIGINS environment
variable, similar to CORS_ALLOWED_ORIGINS.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 17:10:14 -07:00
Keith SmithandClaude Sonnet 4.5 71399e54b8 Add Docker deployment configuration
- Add Dockerfile for production (multi-stage build)
- Add Dockerfile.dev for development with hot reload
- Add docker-compose.yml with 5 services (web, mariadb, redis, celery-worker, celery-beat)
- Add docker-compose.dev.yml for development overrides
- Add .dockerignore for optimized builds
- Add docker/entrypoint.sh startup script
- Add .env.docker.example template
- Add Makefile for common commands
- Add deploy.sh for one-command deployment
- Update config/settings/selfhosted.py to support MariaDB via DATABASE_URL
- Add mysqlclient to requirements.txt for MariaDB support
- Update .gitignore to exclude .env.docker

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 15:59:09 -07:00
Keith SmithandClaude Sonnet 4.5 e7fbef75e9 Fix HIGH Security Issue: Require ALLOWED_HOSTS in production
Added validation to ensure ALLOWED_HOSTS is explicitly set in production.

Changes:
- Check if ALLOWED_HOSTS environment variable is set
- Raise ValueError with helpful message if not set
- Use os.environ['ALLOWED_HOSTS'] instead of .get() to enforce requirement
- Prevents empty or missing ALLOWED_HOSTS from bypassing host validation

Security impact:
- Prevents host header injection attacks
- Blocks cache poisoning via host header manipulation
- Ensures production deployments have explicit allowed hosts configured
- Fails fast with clear error message if misconfigured

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 06:23:34 -07:00
Keith SmithandClaude Sonnet 4.5 5d9c901918 Fix HIGH Security Issue: Add file upload validation for avatars
Added comprehensive validation for avatar file uploads to prevent malicious file uploads.

Validation Checks:
- File extension: Only allow jpg, jpeg, png, gif
- File size: Maximum 5MB
- Content type: Verify MIME type matches allowed image types

Changes:

users/serializers.py:
- Added MAX_AVATAR_SIZE constant (5MB)
- Created validate_avatar() method in UserSerializer
- Validates file extension against whitelist
- Checks file size and provides helpful error messages
- Verifies content-type header matches allowed image types

config/settings/base.py:
- Added FILE_UPLOAD_MAX_MEMORY_SIZE = 5MB
- Added DATA_UPLOAD_MAX_MEMORY_SIZE = 5MB
- Enforces global upload limits at Django level

Security impact:
- Prevents upload of executables, malware, or scripts
- Mitigates DoS via large file uploads
- Ensures only valid image files can be uploaded
- Protects against MIME-type confusion attacks

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 06:23:11 -07:00
Keith SmithandClaude Sonnet 4.5 026259b4f4 Fix HIGH Security Issue: Add comprehensive security headers
Added comprehensive security headers to prevent XSS, clickjacking, and other attacks.

Security Headers Added:
- SECURE_BROWSER_XSS_FILTER: Enable XSS filter
- SECURE_CONTENT_TYPE_NOSNIFF: Prevent MIME-type sniffing
- X_FRAME_OPTIONS: DENY to prevent clickjacking
- SECURE_REFERRER_POLICY: Control referrer information

Cookie Security:
- SESSION_COOKIE_HTTPONLY: Prevent JavaScript access to session cookies
- SESSION_COOKIE_SAMESITE: Strict to prevent CSRF
- CSRF_COOKIE_HTTPONLY: Prevent JavaScript access to CSRF tokens
- CSRF_COOKIE_SAMESITE: Strict protection

Content Security Policy (CSP):
- CSP_DEFAULT_SRC: Only allow same-origin resources
- CSP_SCRIPT_SRC: Restrict script execution to same-origin
- CSP_STYLE_SRC: Restrict stylesheets to same-origin
- CSP_IMG_SRC: Allow images from same-origin, data URIs, and HTTPS
- CSP_FRAME_ANCESTORS: Prevent embedding in iframes ('none')
- CSP_FORM_ACTION: Restrict form submissions to same-origin

CSRF Protection:
- Added CSRF_TRUSTED_ORIGINS configuration for cross-origin requests

Security impact:
- Prevents clickjacking attacks
- Mitigates XSS vulnerabilities
- Blocks MIME-type confusion attacks
- Protects cookies from JavaScript theft
- Enforces strict CSP to prevent code injection

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 06:22:14 -07:00
Keith SmithandClaude Sonnet 4.5 0147b8644e Add tasks.firebugit.com to development server configuration
Added tasks.firebugit.com to:
- ALLOWED_HOSTS: Allow Django to serve requests from this domain
- CSRF_TRUSTED_ORIGINS: Allow CSRF-protected requests from https://tasks.firebugit.com

This enables testing the development server via the tasks.firebugit.com domain.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-23 06:08:39 -07:00
Keith SmithandClaude Sonnet 4.5 deabe6ab3d Fix Critical Security Issue: Implement rate limiting on API endpoints
Added comprehensive rate limiting to prevent abuse and DoS attacks:

Configuration (config/settings/base.py):
- Anon rate: 100 requests/hour for anonymous users
- User rate: 1000 requests/hour for authenticated users
- Login rate: 10 attempts/hour (prevents brute force)
- Register rate: 5 attempts/hour (prevents account spam)
- Sync rate: 100 requests/hour (prevents sync flooding)

Custom throttle classes (users/throttles.py):
- LoginRateThrottle: Strict limit for login endpoint
- RegisterRateThrottle: Strict limit for registration endpoint
- SyncRateThrottle: Moderate limit for sync endpoint

Applied throttling to sensitive endpoints:
- users.views.RegisterAPIView: 5/hour
- users.views.TokenObtainPairView: 10/hour
- sync.views.sync: 100/hour

All other API endpoints use default throttles (anon: 100/hour, user: 1000/hour).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 22:36:54 -07:00
Keith SmithandClaude Sonnet 4.5 b57321e1e4 Fix Critical Security Issue: Replace print() with proper logging
Replaced all debug print() statements with proper logging framework:
- tasks/views.py: 5 print statements → logger.debug()
- sync/views.py: 15 print statements → logger.debug()
- config/celery.py: 1 print statement → logger.debug()
- notifications/tasks.py: 2 print statements → logger.error()

Retained print() in settings files (development.py, selfhosted.py) as they are appropriate warnings to stderr for configuration issues.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 22:34:57 -07:00
Keith SmithandClaude Sonnet 4.5 a22c3eed50 Fix Critical Security Issue: Remove weak default SECRET_KEY
Security improvements:
- selfhosted.py: Require SECRET_KEY environment variable (raises ValueError if not set)
- selfhosted.py: Validate SECRET_KEY length (minimum 50 characters)
- selfhosted.py: Warn if DEBUG=True in self-hosted mode
- development.py: Auto-generate random SECRET_KEY on each startup if not provided
- development.py: Remove production domain from ALLOWED_HOSTS
- development.py: Make CSRF_TRUSTED_ORIGINS environment-only

This prevents weak/default SECRET_KEYs from being used in production.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 22:31:46 -07:00
Keith SmithandClaude Sonnet 4.5 21d9d01885 Add email verification, admin approval, and user profile enhancements
Implement comprehensive email verification and admin approval system for user registration. Users must verify their email before logging in, and admins must approve new users before they can access the system.

Major features:
- Email verification with UUID tokens (24hr expiry, one-time use)
- Admin approval workflow via Django admin interface
- Custom authentication backend enforcing verification and approval
- Password change functionality for authenticated users
- Enhanced profile page with proper styling and theme support
- Collect first name, last name, and timezone during registration
- Profile link added to header navigation

Email notifications:
- Verification email sent after registration
- Admin notification when users need approval
- Approval notification sent to users

Security features:
- Cryptographically secure UUID tokens
- Token expiration and one-time use enforcement
- Email enumeration protection
- Custom JWT token validation for API access
- Existing users auto-approved via data migration

Templates added:
- Email templates (verification, approval, admin notification)
- Web templates (password change, verification pages)
- Enhanced profile page with dark/light mode support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-22 18:13:38 -07:00
Keith SmithandClaude Sonnet 4.5 6a0b35c39c Initial commit: KeepItGoing task management server
Features:
- Django-based REST API with web interface
- Task management with tags, priorities, and due dates
- Time tracking with start/stop timers
- Subtasks support
- Task filtering (all, today, upcoming, overdue, completed)
- Tag-based organization with color coding
- Sorting by due date and priority
- Auto-assign tags when filtering
- Responsive 3-pane layout (sidebar, task list, detail panel)
- Task sharing between users
- Mobile-responsive design with dark mode support

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 17:41:29 -07:00