Files
BanGUI/Docs/Security.md
Lukas 400ab1a3f1 Add security headers middleware and documentation
- Add SecurityHeadersMiddleware to backend/app/main.py
  - Implements Content-Security-Policy: default-src 'self'
  - Implements X-Frame-Options: DENY (clickjacking protection)
  - Implements X-Content-Type-Options: nosniff (MIME-sniffing protection)
  - Implements X-XSS-Protection: 1; mode=block (browser XSS filters)
- Add CSP meta tag to frontend/index.html for defense-in-depth
- Create Docs/Security.md with comprehensive security headers documentation
- Add test suite (backend/tests/test_security_headers_middleware.py) with 5 tests
  - Tests verify headers are present on success and error responses
  - Tests ensure all four security headers are correctly set
- All existing tests continue to pass

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-30 21:33:08 +02:00

4.2 KiB

Security — Guidelines and Implementation

Security considerations and implementation details for BanGUI.


HTTP Security Headers

BanGUI implements defense-in-depth against client-side attacks by sending security-related HTTP response headers on all responses.

Headers Implemented

Header Value Purpose
Content-Security-Policy default-src 'self' Prevents XSS attacks by restricting script, style, font, image, and other resource origins to self only. Browsers refuse to load resources from other origins.
X-Frame-Options DENY Prevents clickjacking attacks by forbidding the page from being embedded in <iframe> tags on any origin.
X-Content-Type-Options nosniff Prevents MIME-type sniffing attacks by forcing browsers to respect the declared Content-Type. Blocks execution of misidentified scripts.
X-XSS-Protection 1; mode=block Enables browser XSS filters (legacy header for older browsers). Modern browsers prioritize CSP.

Implementation

Backend: The SecurityHeadersMiddleware in backend/app/main.py adds these headers to every HTTP response, including error responses and non-API routes.

response.headers["Content-Security-Policy"] = "default-src 'self'"
response.headers["X-Frame-Options"] = "DENY"
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-XSS-Protection"] = "1; mode=block"

Frontend: The <meta http-equiv="Content-Security-Policy" content="default-src 'self'" /> tag in frontend/index.html provides an additional defense layer in case the backend headers are ever stripped (e.g., by a proxy).

CSP Policy Details

The current policy default-src 'self' means:

  • Allowed: Inline scripts, stylesheets, fonts, images, and other resources from the same origin (self)
  • Blocked: Resources from external domains, inline event handlers, eval(), and setTimeout(string)

Why no 'unsafe-inline'?

  • 'unsafe-inline' defeats CSP's primary purpose (XSS prevention) by allowing arbitrarily-embedded scripts
  • All scripts and styles must be in separate files (never inline), which is best practice anyway
  • The frontend build system (Vite) automatically handles asset bundling and file separation

If external CDN resources are needed:

  1. Explicitly add the CDN origin to the CSP policy, e.g.: default-src 'self' https://cdn.example.com
  2. Document the CDN addition with a justification comment
  3. Ensure the CDN certificate chain is valid and trusted
  4. Consider using Subresource Integrity (SRI) to verify resource authenticity

Verification

To verify headers are being sent correctly:

  1. Chrome DevTools:

    • Open DevTools (F12)
    • Go to Network tab
    • Reload the page
    • Click on any request and open the Response Headers section
    • Look for Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, X-XSS-Protection
  2. Command line (curl):

    curl -I http://localhost:8000/
    curl -I http://localhost:5173/
    
  3. Online tools:

Future Improvements

  • Stricter CSP: If functionality allows, tighten to default-src 'none' and explicitly allow individual resources
  • SRI (Subresource Integrity): Add integrity attributes to external script/style tags to prevent tampering
  • Preload headers: Use Link: <...>; rel=preload to optimize critical resource delivery
  • HSTS: Consider adding Strict-Transport-Security for production deployments to force HTTPS

Session Security

See backend/app/middleware/csrf.py and backend/app/middleware/rate_limit.py for CSRF protection and rate limiting.


Password Security

  • Passwords are hashed with SHA256 on the frontend before transmission
  • The backend never stores plain-text passwords
  • See backend/app/services/auth.py for authentication implementation

Database Security

  • The SQLite database contains no sensitive data (no passwords, API keys, or tokens stored)
  • Database queries use parameterized statements to prevent SQL injection
  • See backend/app/repositories/ for data access patterns