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 <[email protected]>
This commit is contained in:
2025-07-24 16:57:07 +02:00
co-authored by Claude
commit 1773ed5f95
354 changed files with 61508 additions and 0 deletions
+119
View File
@@ -0,0 +1,119 @@
/**
* Rate Limiting Security Utilities
* Provides secure rate limiting that prevents bypass attempts
*/
const jwt = require('jsonwebtoken');
const logger = require('./logger');
/**
* Safely check if a request has a valid admin token
* Used to determine if rate limiting should be skipped
*
* IMPORTANT: This prevents the bypass vulnerability where
* invalid tokens could skip rate limiting
*
* @param {Object} req - Express request object
* @returns {boolean} - True only if token is valid AND admin type
*/
function hasValidAdminToken(req) {
try {
// Only check admin paths
if (!req.path.startsWith('/api/admin/')) {
return false;
}
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
return false;
}
const token = authHeader.substring(7); // Remove 'Bearer ' prefix
// Critical: Verify token is valid before skipping rate limit
// This prevents invalid tokens from bypassing rate limiting
const decoded = jwt.verify(token, process.env.JWT_SECRET);
// Additional validation
if (!decoded || typeof decoded !== 'object') {
return false;
}
// Must be admin type to skip rate limiting
if (decoded.type !== 'admin') {
logger.warn('Non-admin token attempted to bypass rate limit', {
path: req.path,
tokenType: decoded.type,
ip: req.ip
});
return false;
}
// Optional: Check token age (prevent old tokens)
const tokenAge = Date.now() - (decoded.iat * 1000);
const maxAge = 24 * 60 * 60 * 1000; // 24 hours
if (tokenAge > maxAge) {
logger.warn('Old admin token attempted to bypass rate limit', {
path: req.path,
tokenAge: Math.floor(tokenAge / 1000 / 60) + ' minutes',
ip: req.ip
});
return false;
}
// Valid admin token - can skip rate limiting
return true;
} catch (error) {
// Any error means token is invalid
// Log attempts with invalid tokens (potential attacks)
if (error.name === 'JsonWebTokenError') {
logger.warn('Invalid token attempted to bypass rate limit', {
path: req.path,
error: error.message,
ip: req.ip
});
}
// Apply rate limiting for any invalid token
return false;
}
}
/**
* Create a skip function for rate limiter that prevents bypass
* @returns {Function} Skip function for express-rate-limit
*/
function createSecureSkipFunction() {
return (req) => {
// In development, be more lenient with public settings
if (process.env.NODE_ENV === 'development' && req.path === '/api/public/settings') {
return true;
}
// Only skip for valid admin tokens
return hasValidAdminToken(req);
};
}
/**
* Log rate limit hits for security monitoring
* @param {Object} req - Express request object
* @param {Object} res - Express response object
*/
function logRateLimitHit(req, res) {
logger.warn('Rate limit exceeded', {
ip: req.ip,
path: req.path,
userAgent: req.headers['user-agent'],
remaining: res.getHeader('X-RateLimit-Remaining'),
limit: res.getHeader('X-RateLimit-Limit')
});
}
module.exports = {
hasValidAdminToken,
createSecureSkipFunction,
logRateLimitHit
};