Security hardening and performance improvements

- Add visibility check to attachment downloads (prevents unauthorized access)
- Fix ticket ID collision with uniqueness verification loop
- Harden CSP: replace unsafe-inline with nonce-based script execution
- Add IP-based rate limiting (supplements session-based)
- Add visibility checks to bulk operations
- Validate internal visibility requires groups
- Optimize user activity query (JOINs vs subqueries)
- Update documentation with design decisions and security info

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-28 20:27:15 -05:00
parent a08390a500
commit fa40010287
17 changed files with 457 additions and 128 deletions

View File

@@ -5,12 +5,29 @@
* Applies security-related HTTP headers to all responses.
*/
class SecurityHeadersMiddleware {
private static $nonce = null;
/**
* Generate or retrieve the CSP nonce for this request
*
* @return string The nonce value
*/
public static function getNonce() {
if (self::$nonce === null) {
self::$nonce = base64_encode(random_bytes(16));
}
return self::$nonce;
}
/**
* Apply security headers to the response
*/
public static function apply() {
$nonce = self::getNonce();
// Content Security Policy - restricts where resources can be loaded from
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self';");
// Using nonce for inline scripts instead of unsafe-inline for better security
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{$nonce}'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self';");
// Prevent clickjacking by disallowing framing
header("X-Frame-Options: DENY");