From 123da36b5b90ce2ea101c09d52e6a1c31534971e Mon Sep 17 00:00:00 2001 From: Ronni Skansing Date: Thu, 4 Jun 2026 10:15:24 +0200 Subject: [PATCH] added security headers to admin Signed-off-by: Ronni Skansing --- backend/main.go | 2 ++ backend/middleware/securityHeaders.go | 14 ++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 backend/middleware/securityHeaders.go diff --git a/backend/main.go b/backend/main.go index 1630bcd..dd0ab53 100644 --- a/backend/main.go +++ b/backend/main.go @@ -27,6 +27,7 @@ import ( "github.com/phishingclub/phishingclub/database" "github.com/phishingclub/phishingclub/errs" "github.com/phishingclub/phishingclub/install" + "github.com/phishingclub/phishingclub/middleware" "github.com/phishingclub/phishingclub/model" "github.com/phishingclub/phishingclub/repository" "github.com/phishingclub/phishingclub/seed" @@ -323,6 +324,7 @@ func main() { ) } adminRouter.Use(middlewares.IPLimiter) + adminRouter.Use(middleware.SecurityHeaders()) // read the seeded victim WS path for the remote browser endpoint rbWSPath := "rbws" // fallback - real value is seeded at first startup diff --git a/backend/middleware/securityHeaders.go b/backend/middleware/securityHeaders.go new file mode 100644 index 0000000..6a0dad2 --- /dev/null +++ b/backend/middleware/securityHeaders.go @@ -0,0 +1,14 @@ +package middleware + +import "github.com/gin-gonic/gin" + +func SecurityHeaders() gin.HandlerFunc { + return func(c *gin.Context) { + c.Header("Content-Security-Policy", "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self'; frame-src data:; font-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none';") + c.Header("X-Content-Type-Options", "nosniff") + c.Header("Strict-Transport-Security", "max-age=63072000") + c.Header("Referrer-Policy", "strict-origin-when-cross-origin") + c.Header("Permissions-Policy", "camera=(), microphone=(), geolocation=(), payment=()") + c.Next() + } +}