From 8bf5c9033fc1a15cd8bcf4f6769d11dfcd1453dc Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Sun, 15 Mar 2026 19:19:12 -0700 Subject: [PATCH] Bundle swagger-ui assets locally for /docs - Download swagger-ui-dist@5.32.0 and embed swagger-ui-bundle.js and swagger-ui.css into web/static/ so they are served from the same origin - Update docs.html to reference /static/ paths instead of unpkg.com CDN URLs - Add GET /static/swagger-ui-bundle.js and GET /static/swagger-ui.css handlers serving the embedded bytes with correct Content-Type headers - Fixes /docs breakage caused by CSP default-src 'self' blocking external CDN scripts and stylesheets Co-authored-by: Junie --- internal/server/server.go | 18 ++++++++++++++++++ web/static/docs.html | 4 ++-- web/static/swagger-ui-bundle.js | 2 ++ web/static/swagger-ui.css | 3 +++ 4 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 web/static/swagger-ui-bundle.js create mode 100644 web/static/swagger-ui.css diff --git a/internal/server/server.go b/internal/server/server.go index ca2207d..700f0b2 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -232,6 +232,14 @@ func (s *Server) Handler() http.Handler { if err != nil { panic(fmt.Sprintf("server: read openapi.yaml: %v", err)) } + swaggerJS, err := fs.ReadFile(staticFS, "swagger-ui-bundle.js") + if err != nil { + panic(fmt.Sprintf("server: read swagger-ui-bundle.js: %v", err)) + } + swaggerCSS, err := fs.ReadFile(staticFS, "swagger-ui.css") + if err != nil { + panic(fmt.Sprintf("server: read swagger-ui.css: %v", err)) + } // Security (DEF-09): apply defensive HTTP headers to the docs handlers. // The Swagger UI page at /docs loads JavaScript from the same origin // and renders untrusted content (API descriptions), so it benefits from @@ -246,6 +254,16 @@ func (s *Server) Handler() http.Handler { w.WriteHeader(http.StatusOK) _, _ = w.Write(specYAML) }))) + mux.Handle("GET /static/swagger-ui-bundle.js", docsSecurityHeaders(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/javascript") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(swaggerJS) + }))) + mux.Handle("GET /static/swagger-ui.css", docsSecurityHeaders(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "text/css") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(swaggerCSS) + }))) // Vault endpoints (exempt from sealed middleware and auth). unsealRateLimit := middleware.RateLimit(3, 5, trustedProxy) diff --git a/web/static/docs.html b/web/static/docs.html index 9d35abf..d42963f 100644 --- a/web/static/docs.html +++ b/web/static/docs.html @@ -4,11 +4,11 @@ MCIAS API Reference - +
- +