Files
ServerKit/backend/app/middleware/security.py
T
Juan Denis 9138a8b178 Backend fixes, API renames, and style utilities
Multiple coordinated changes: backend
- Ensure JWT identity is stringified (PyJWT 2.10+ compatibility).
- Allow relaxed CSP in debug (unsafe-inline + localhost/ws) for Vite dev tooling.
- Rename CloudServer.metadata -> server_metadata and update usages to avoid property conflicts.
- Enhance MigrationService to auto-add missing columns (SQLite-aware type mapping), create missing tables and log results.
- Add run_command helper that returns a simple stdout/stderr/returncode dict.

Frontend
- Rename numerous ApiService methods for clarity (e.g. getGitStatus -> getGitServerStatus, triggerDeploy -> triggerAppDeploy/triggerGitDeploy, getProcesses -> getSystemProcesses, nginx advanced test/reload renamed) and update pages to call the new APIs.
- Import Activity icon in WorkflowBuilder.

Styles
- Add Tailwind-like utilities.less and import it in main.less.
- Add spacing/color aliases to variables.less, new badge component styles, and layout/sidebar tweaks (page-container, header helpers, spacing/opac adjustments).

Overall: fixes compatibility issues, improves schema migration resiliency, clarifies API method names, and adds utility styles for newer pages.
2026-03-23 21:25:40 -04:00

55 lines
1.9 KiB
Python

"""Security middleware for adding security headers to responses."""
from flask import Flask
def register_security_headers(app: Flask):
"""Register security headers as an after_request handler."""
@app.after_request
def add_security_headers(response):
# Prevent clickjacking
response.headers['X-Frame-Options'] = 'DENY'
# Prevent MIME type sniffing
response.headers['X-Content-Type-Options'] = 'nosniff'
# XSS Protection (legacy but still useful for older browsers)
response.headers['X-XSS-Protection'] = '1; mode=block'
# Referrer Policy
response.headers['Referrer-Policy'] = 'strict-origin-when-cross-origin'
# Content Security Policy
# In debug mode, allow inline styles/scripts for Vite dev tooling
if app.debug:
csp_directives = [
"default-src 'self'",
"script-src 'self' 'unsafe-inline'",
"style-src 'self' 'unsafe-inline'",
"img-src 'self' data: https:",
"font-src 'self'",
"connect-src 'self' ws: wss: http://localhost:* http://127.0.0.1:*",
"frame-ancestors 'none'",
]
else:
csp_directives = [
"default-src 'self'",
"script-src 'self'",
"style-src 'self'",
"img-src 'self' data: https:",
"font-src 'self'",
"connect-src 'self' ws: wss:",
"frame-ancestors 'none'",
]
response.headers['Content-Security-Policy'] = '; '.join(csp_directives)
# Permissions Policy (formerly Feature-Policy)
response.headers['Permissions-Policy'] = 'geolocation=(), microphone=(), camera=()'
# HSTS - only in production and on HTTPS
if not app.debug:
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains'
return response