Initial commit - Project start (July 17, 2025)
Mirror to GitHub / mirror (push) Successful in 26s
Test and Lint / backend-test (push) Successful in 1m11s
continuous-integration/drone/push Build is passing
Test and Lint / frontend-test (push) Successful in 2m28s
Version and Release / version-bump (push) Successful in 32s
Version and Release / trigger-drone (push) Has been skipped

Original: feat: enhance security logging and ensure rate limit blocks are properly tracked

- Add comprehensive logging for rate limit blocks with full request details
  - IP address (with proper proxy detection), user agent, headers, timestamps
  - Rate limit info (current count, limit, remaining, reset time)
  - Separate tracking for auth vs general endpoints

- Enhance authentication failure logging
  - JWT validation failures with detailed error info
  - Admin auth attempts without token
  - Failed token validation with user context
  - All events include IP, path, method, user agent

- Improve Winston logger configuration for production
  - Add automatic log rotation (10MB errors, 50MB combined)
  - Create separate security.log for auth/rate limit events
  - Ensure logs directory exists automatically
  - Add structured JSON format for log aggregation
  - Support container logging with LOG_TO_CONSOLE env var

- Create comprehensive documentation
  - Security logging guide with examples
  - Monitoring recommendations
  - Configuration reference

- Add test script to verify logging functionality

All rate limit settings remain configurable via admin panel:
- Window duration, max requests, auth limits
- Skip authenticated requests option
- Public endpoints only option

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-07-18 19:25:15 +02:00
commit 1773ed5f95
354 changed files with 61508 additions and 0 deletions
+164
View File
@@ -0,0 +1,164 @@
# Admin Setup Guide - Secure Password System
## Overview
PicPeak now uses a secure admin setup process that eliminates the default password vulnerability. When you first set up the application, a secure password is automatically generated for the admin account.
## Initial Setup Process
### 1. First Installation
When you run the database migrations for the first time:
```bash
cd backend
npm run migrate
```
The system will:
- Create an admin user with username `admin`
- Generate a secure, random password (e.g., `SwiftEagle3847!`)
- Display the credentials in the console
- Save the credentials to `ADMIN_CREDENTIALS.txt`
### 2. Retrieving Your Credentials
After setup, you can find your admin credentials in:
- **Console output** - Displayed immediately after setup
- **ADMIN_CREDENTIALS.txt** - File in the project root
**Example output:**
```
========================================
✅ Admin user created successfully!
========================================
Username: admin
Password: SwiftEagle3847!
⚠️ IMPORTANT:
1. Save these credentials securely
2. You will be required to change the password on first login
3. Credentials are also saved in: ADMIN_CREDENTIALS.txt
========================================
```
### 3. First Login
1. Navigate to the admin panel: `http://localhost:3001/admin`
2. Login with:
- Username: `admin`
- Password: (from ADMIN_CREDENTIALS.txt)
3. You will be prompted to change your password immediately
### 4. Password Requirements
When changing your password, it must meet these requirements:
- Minimum 12 characters long
- Contains uppercase letters (A-Z)
- Contains lowercase letters (a-z)
- Contains numbers (0-9)
- Contains special characters (!@#$%^&*()_+-=[]{}|;:,.<>?)
- Not a common password
## Security Features
### Generated Passwords
- Uses cryptographically secure random generation
- Human-readable format: `AdjectiveNoun####!`
- Example: `BrightMountain7823$`
### Password Storage
- Passwords are hashed using bcrypt with 12 rounds
- Original password is never stored in the database
- Credentials file should be deleted after noting the password
### Forced Password Change
- Admin must change password on first login
- System tracks `must_change_password` flag
- Cannot access admin features until password is changed
## Troubleshooting
### Lost Admin Password
If you lose the admin password before first login:
1. Delete the admin user from the database:
```sql
DELETE FROM admin_users WHERE username = 'admin';
```
2. Run migrations again:
```bash
npm run migrate
```
3. New credentials will be generated
### Password Change Issues
If you can't change your password:
- Ensure new password meets all requirements
- Check for detailed error messages
- Password strength validator provides specific feedback
### Can't Find Credentials File
If ADMIN_CREDENTIALS.txt is missing:
- Check the console output from when you ran migrations
- File is created in the backend directory root
- File might have been deleted for security (as recommended)
## Best Practices
1. **Immediate Action**
- Change the generated password on first login
- Use a password manager to store credentials
- Delete ADMIN_CREDENTIALS.txt after noting the password
2. **Password Security**
- Use unique passwords for each environment
- Rotate passwords regularly (every 90 days)
- Never share admin credentials
3. **Multiple Admins**
- Create separate admin accounts for each person
- Avoid sharing the main admin account
- Use role-based access control when available
## Migration from Old System
If upgrading from the old system with hardcoded `admin123`:
1. The system will detect existing admin user
2. You must manually reset the password:
```bash
# Run the password reset script
node scripts/reset-admin-password.js
```
3. Follow the new secure password process
## Environment-Specific Setup
### Development
- Generated passwords are suitable for development
- Consider using simpler passwords for convenience
- Always use strong passwords in staging/production
### Production
- Generate new admin account for production
- Use extremely strong passwords (20+ characters)
- Enable two-factor authentication when available
- Regularly audit admin access logs
## Security Checklist
- [ ] Retrieved generated password from ADMIN_CREDENTIALS.txt
- [ ] Logged in successfully with generated password
- [ ] Changed password to a strong, unique password
- [ ] Deleted ADMIN_CREDENTIALS.txt file
- [ ] Stored new password in password manager
- [ ] Tested login with new password
- [ ] Set up additional admin accounts if needed
- [ ] Configured password policies for organization
+109
View File
@@ -0,0 +1,109 @@
# JWT_SECRET Security Fix - Migration Guide
## Overview
A critical security vulnerability has been fixed where the application would fall back to a hardcoded JWT secret (`'your-secret-key'`) if the `JWT_SECRET` environment variable was not set. This has been addressed by:
1. Adding startup validation that requires `JWT_SECRET` to be set
2. Removing all hardcoded fallback values
3. Ensuring the secret meets minimum security requirements
## Changes Made
### 1. Added Environment Validation (`backend/src/config/validateEnv.js`)
- The server now validates critical environment variables at startup
- If `JWT_SECRET` is missing or set to the insecure default, the server will refuse to start
- Warns if `JWT_SECRET` is less than 32 characters (recommended minimum)
### 2. Updated Server Startup (`backend/server.js`)
- Added validation call immediately after loading environment variables
- Ensures all routes and middleware have access to validated configuration
### 3. Removed Hardcoded Fallbacks (`backend/src/routes/protectedImages.js`)
- Removed `|| 'your-secret-key'` fallback from lines 15 and 27
- Functions now rely on the validated `JWT_SECRET` from environment
## Migration Steps for Production
### Before Deployment
1. **Verify JWT_SECRET is set in production**:
```bash
# Check if JWT_SECRET is set
echo $JWT_SECRET
```
2. **Ensure JWT_SECRET is secure**:
- Must NOT be `'your-secret-key'`
- Should be at least 32 characters long
- Should be randomly generated
3. **Generate a secure JWT_SECRET if needed**:
```bash
# Generate a secure 64-character secret
openssl rand -hex 32
```
### Deployment Process
1. **Update environment variables** (if needed):
```bash
# Example for .env file
JWT_SECRET=your-secure-64-character-random-string-here
```
2. **Deploy the updated code**
3. **Monitor startup logs** to ensure no validation errors:
```
✓ Environment validation passed
✓ Server running on port 3000
```
### Rollback Plan
If the deployment fails due to missing `JWT_SECRET`:
1. **Quick Fix** (temporary):
- Set `JWT_SECRET` environment variable to a secure value
- Restart the application
2. **Full Rollback** (if needed):
- Revert to previous version
- Set `JWT_SECRET` properly before attempting deployment again
## Verification
After deployment, verify the fix is working:
1. **Check server logs** for successful startup
2. **Test authentication** to ensure JWT tokens are working
3. **Verify image protection** routes are functioning
## Security Considerations
- **Never** commit JWT_SECRET to version control
- **Rotate** JWT_SECRET periodically
- **Use different** secrets for different environments (dev, staging, production)
- **Monitor** for authentication failures that might indicate token issues
## Troubleshooting
### Server won't start
- **Error**: "Missing required environment variable: JWT_SECRET"
- **Solution**: Set the JWT_SECRET environment variable
### JWT_SECRET rejection
- **Error**: "JWT_SECRET is set to the insecure default value"
- **Solution**: Change JWT_SECRET from 'your-secret-key' to a secure value
### Authentication failures after deployment
- **Cause**: Existing tokens were signed with old secret
- **Solution**: Users will need to re-authenticate to get new tokens
## Support
If you encounter issues during migration:
1. Check the server logs for specific error messages
2. Verify environment variables are properly set
3. Ensure the JWT_SECRET value doesn't contain special characters that might need escaping
+179
View File
@@ -0,0 +1,179 @@
# Security Best Practices for PicPeak
## JWT Secret Management
### Generating Secure Secrets
Always generate cryptographically secure random secrets for JWT signing:
```bash
# Generate a 64-character hex string (256 bits)
openssl rand -hex 32
# Alternative: Generate a base64 string
openssl rand -base64 32
# Alternative: Using Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```
### Environment-Specific Secrets
**NEVER use the same JWT secret across different environments!**
- **Development**: Use the secure secret in `docker-compose.yml`
- **Staging**: Generate a unique secret for staging
- **Production**: Generate a unique secret for production
### Secret Requirements
1. **Minimum Length**: 32 characters (enforced by application)
2. **Recommended Length**: 64 characters (256 bits)
3. **Character Set**: Use hex or base64 encoding
4. **Uniqueness**: Each environment must have a unique secret
### What NOT to Do
**Never commit real secrets to version control**
```bash
# Bad - real secret in code
JWT_SECRET=my-actual-production-secret
```
**Never use predictable or weak secrets**
```bash
# Bad examples
JWT_SECRET=secret123
JWT_SECRET=mycompanyname
JWT_SECRET=password
JWT_SECRET=your-secret-key
```
**Never share secrets between environments**
```bash
# Bad - same secret everywhere
DEV_JWT_SECRET=same-secret
PROD_JWT_SECRET=same-secret
```
### Secure Secret Storage
#### For Local Development
- Docker Compose files can contain development secrets
- These should still be secure random values
#### For Production
1. **Environment Variables**
```bash
# Set via secure environment
export JWT_SECRET=$(openssl rand -hex 32)
```
2. **Secret Management Services**
- AWS Secrets Manager
- HashiCorp Vault
- Azure Key Vault
- Kubernetes Secrets
3. **CI/CD Integration**
- Store secrets in CI/CD platform's secret storage
- Never log or echo secrets in build scripts
### Secret Rotation
Implement a secret rotation strategy:
1. **Regular Rotation**: Rotate secrets every 90 days
2. **Incident Response**: Rotate immediately if compromised
3. **Graceful Rotation**: Support multiple valid secrets during transition
### Monitoring and Alerts
1. **Startup Validation**: Application refuses to start without proper JWT_SECRET
2. **Length Warnings**: Warnings for secrets shorter than 32 characters
3. **Default Detection**: Critical error if default secret is detected
## Additional Security Measures
### Password Requirements
- Minimum 12 characters
- Mix of uppercase, lowercase, numbers, and special characters
- Check against common password lists
- Implement password strength meter
### Session Security
- Implement token expiration (24 hours for admin, configurable for galleries)
- Add refresh token mechanism
- Implement token revocation
- Use secure session storage (Redis in production)
### API Security
- Rate limiting on all endpoints
- Extra strict limits on authentication endpoints
- CSRF protection for state-changing operations
- Input validation on all user inputs
### File Upload Security
- Validate file types by content, not just extension
- Implement virus scanning
- Limit file sizes
- Sanitize filenames
- Store files outside web root
### Database Security
- Use parameterized queries (Knex.js handles this)
- Validate and sanitize all inputs
- Implement query timeouts
- Use least-privilege database users
### HTTPS and Headers
- Always use HTTPS in production
- Implement security headers:
- Strict-Transport-Security
- X-Frame-Options
- X-Content-Type-Options
- Content-Security-Policy
- X-XSS-Protection
### Logging and Monitoring
- Log authentication attempts
- Monitor for suspicious patterns
- Never log sensitive data (passwords, tokens)
- Implement audit trails for admin actions
## Security Checklist for Deployment
- [ ] Generate unique JWT_SECRET for environment
- [ ] Verify JWT_SECRET meets minimum requirements
- [ ] Store secrets securely (not in code)
- [ ] Enable HTTPS
- [ ] Configure security headers
- [ ] Set up rate limiting
- [ ] Enable audit logging
- [ ] Test authentication flows
- [ ] Verify file upload restrictions
- [ ] Check database query security
## Incident Response
If a security incident occurs:
1. **Immediate Actions**
- Rotate all secrets
- Review access logs
- Disable compromised accounts
2. **Investigation**
- Analyze logs for unauthorized access
- Check for data exfiltration
- Review code changes
3. **Recovery**
- Deploy security patches
- Force password resets if needed
- Notify affected users
4. **Prevention**
- Update security practices
- Implement additional monitoring
- Conduct security audit
+59
View File
@@ -0,0 +1,59 @@
# Nginx Configuration Fix for Photo Authentication
If photos and thumbnails are not loading in gallery view but work in admin, it's likely that the Authorization header is being stripped by nginx or another reverse proxy.
## Common Issue
The `Authorization` header is often not passed through by default in nginx proxy configurations.
## Fix
Add these lines to your nginx configuration for the PicPeak location block:
```nginx
location / {
proxy_pass http://localhost:3001;
# Important: Pass the Authorization header
proxy_pass_header Authorization;
proxy_set_header Authorization $http_authorization;
# Other standard proxy headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
```
## Alternative Fix Using Traefik
If using Traefik, ensure headers are passed:
```yaml
services:
picpeak:
labels:
- "traefik.http.middlewares.picpeak-headers.headers.customrequestheaders.Authorization="
```
## Testing
1. Check if Authorization header is reaching the backend:
```bash
curl -H "Authorization: Bearer YOUR_TOKEN" https://picpeak.yourdomain.com/thumbnails/test.jpg -v
```
2. Check nginx logs to see if the header is present:
```bash
tail -f /var/log/nginx/access.log
```
## Docker Compose Fix
If using docker-compose with nginx proxy, add:
```yaml
environment:
- NGINX_PROXY_PASS_HEADER=Authorization
```
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 KiB