CSP-Flag
All checks were successful
Deploy KubeViz / deploy (push) Successful in 12s

This commit is contained in:
2026-03-01 11:45:20 +01:00
parent 58a10625c3
commit aafc95a551
6 changed files with 13 additions and 2 deletions

View File

@@ -67,6 +67,7 @@ Then open [http://localhost:8080](http://localhost:8080).
- `SESSION_TTL` (default `30m`)
- `MAX_UPLOAD_SIZE` (bytes, default `5242880`)
- `COOKIE_SECURE` (`true`/`false`, default `true`)
- `APP_CSP_ENABLED` (`true`/`false`, default `true`) - disable when CSP is enforced by reverse proxy
- `GIT_ALLOWED_HOSTS` (CSV allowlist, default `github.com,gitlab.com,bitbucket.org`)
- `LOG_LEVEL` (default `info`)

View File

@@ -86,6 +86,10 @@ Default workflow mode uses user services (`systemctl --user`) and rootless Podma
So no root sudo is required for normal deploy runs.
CSP hardening recommendation:
- Keep a single CSP source to avoid policy conflicts.
- In these templates, Traefik sets CSP and app-level CSP is disabled via `APP_CSP_ENABLED=false`.
Required sudo permissions for the Gitea runner user (example):
```text

View File

@@ -16,6 +16,7 @@ Environment=ADDR=:8080
Environment=SESSION_TTL=30m
Environment=MAX_UPLOAD_SIZE=5242880
Environment=COOKIE_SECURE=true
Environment=APP_CSP_ENABLED=false
Environment=LOG_LEVEL=info
Environment=GIT_ALLOWED_HOSTS=github.com,gitlab.com,gitea.smb-corp.de
@@ -40,7 +41,7 @@ Label=traefik.http.routers.kubeviz-websecure.tls.certresolver=le
Label=traefik.http.routers.kubeviz-websecure.middlewares=kubeviz-sec-headers,kubeviz-auth
Label=traefik.http.routers.kubeviz-websecure.service=kubeviz
Label=traefik.http.services.kubeviz.loadbalancer.server.port=8080
Label=traefik.http.middlewares.kubeviz-sec-headers.headers.customResponseHeaders.Content-Security-Policy=default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; script-src 'self'; script-src-elem 'self' 'unsafe-inline'; connect-src 'self' wss: https:; font-src 'self' data:; worker-src 'self' blob:;
Label=traefik.http.middlewares.kubeviz-sec-headers.headers.contentSecurityPolicy=default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'self'; script-src 'self'; script-src-elem 'self'; style-src 'self' 'unsafe-inline'; style-src-elem 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; worker-src 'self' blob:;
Label="traefik.http.middlewares.kubeviz-auth.basicauth.users=smb:$apr1$H6uskkkW$IgXLP6ewTrSuBkTrqE8wj/"
[Service]

View File

@@ -16,6 +16,7 @@ Environment=ADDR=:8080
Environment=SESSION_TTL=30m
Environment=MAX_UPLOAD_SIZE=5242880
Environment=COOKIE_SECURE=true
Environment=APP_CSP_ENABLED=false
Environment=LOG_LEVEL=info
Environment=GIT_ALLOWED_HOSTS=github.com,gitlab.com,bitbucket.org

View File

@@ -13,6 +13,7 @@ type Config struct {
SessionTTL time.Duration
MaxUploadSize int64
CookieSecure bool
AppCSPEnabled bool
LogLevel string
GitAllowedHosts []string
}
@@ -23,6 +24,7 @@ func Load() Config {
SessionTTL: durationEnvOrDefault("SESSION_TTL", 30*time.Minute),
MaxUploadSize: int64(intEnvOrDefault("MAX_UPLOAD_SIZE", 5*1024*1024)),
CookieSecure: boolEnvOrDefault("COOKIE_SECURE", true),
AppCSPEnabled: boolEnvOrDefault("APP_CSP_ENABLED", true),
LogLevel: envOrDefault("LOG_LEVEL", "info"),
GitAllowedHosts: csvEnvOrDefault("GIT_ALLOWED_HOSTS", []string{
"github.com",

View File

@@ -74,7 +74,9 @@ func (s *Server) middleware(next http.Handler) http.Handler {
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("Referrer-Policy", "same-origin")
w.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self';")
if s.cfg.AppCSPEnabled {
w.Header().Set("Content-Security-Policy", "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'self'; script-src 'self'; script-src-elem 'self'; style-src 'self' 'unsafe-inline'; style-src-elem 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; worker-src 'self' blob:;")
}
if r.TLS != nil || strings.EqualFold(r.Header.Get("X-Forwarded-Proto"), "https") {
w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
}