From 3d008b3017079c81bf03dd3e979b5e6eb21c30d8 Mon Sep 17 00:00:00 2001 From: clawbot <35+clawbot@noreply.example.org> Date: Sun, 4 Oct 2026 13:02:39 +0000 Subject: [PATCH] Remove unsafe-inline from the Content-Security-Policy (closes #125) script-src and style-src now allow only 'self'. The generator page's two inline onclick handlers, which selected the generated URL and copied it, move into internal/static/generator.js and are attached with addEventListener. The bundled Tailwind script, which built styles in the browser and injected them at runtime, is replaced by a small hand-written internal/static/style.css holding only the rules the login and generator pages use; the templates carry a few plain class names in place of Tailwind's. No build step. The pages keep their layout, not every pixel of it. Model: opus-5-5 --- README.md | 5 +- TODO.md | 9 ++ internal/middleware/middleware.go | 9 +- internal/server/routes.go | 2 +- internal/static/generator.js | 10 ++ internal/static/static.go | 2 +- internal/static/style.css | 190 ++++++++++++++++++++++++++++++ internal/static/tailwind.js | 83 ------------- internal/templates/generator.html | 88 +++++--------- internal/templates/login.html | 20 ++-- 10 files changed, 256 insertions(+), 162 deletions(-) create mode 100644 internal/static/generator.js create mode 100644 internal/static/style.css delete mode 100644 internal/static/tailwind.js diff --git a/README.md b/README.md index 6e3e2d1..fe05438 100644 --- a/README.md +++ b/README.md @@ -191,8 +191,9 @@ path under `/v1/` answers 200, in maintenance mode too. - `GET /.well-known/healthcheck.json` — JSON with `status` (`ok`), `now`, `uptime_seconds`, `uptime_human`, `version`, `appname` and `maintenance_mode`. Needs: nothing. Answers: 200, always. -- `GET /static/` — the script the login and generator pages load. Needs: - nothing. Answers: 200, or 404 for a file that does not exist. +- `GET /static/` — the stylesheet and script the login and generator + pages load. Needs: nothing. Answers: 200, or 404 for a file that does not + exist. - `GET /metrics` — Prometheus metrics (see Architecture). Needs: HTTP basic authentication with `metrics.username` and `metrics.password`. Answers: 200; 401 without them; 404 when they are not set, as the route then does not exist. diff --git a/TODO.md b/TODO.md index 11b5a2d..d4be840 100644 --- a/TODO.md +++ b/TODO.md @@ -58,6 +58,15 @@ P2: security: referer blacklist deprecation warning; its successor `gomodguard_v2` runs with the shared module block list, and `depguard` keeps `net/http/httptest` out of files that are not tests. The tree needed no code changes. +- 2026-10-04 the Content-Security-Policy allows no inline script or style + (closes #125): `script-src` and `style-src` are `'self'` only. The generator + page's two inline `onclick` handlers moved into + `internal/static/generator.js`, attached with `addEventListener`; the bundled + Tailwind script, which built styles in the browser, is replaced by a small + hand-written `internal/static/style.css` with only the rules the login and + generator pages use, the templates carrying a few plain class names in place + of Tailwind's. No build step. The pages keep their layout, not every pixel of + it. - 2026-10-04 deployment guide and example Caddy config (closes #89): "Deployment" in `README.md` says what the reverse proxy in front of pixa must do (terminate TLS; pass `Host`, `Origin` and `Referer` on unchanged; set diff --git a/internal/middleware/middleware.go b/internal/middleware/middleware.go index 358cbdc..aeddfd8 100644 --- a/internal/middleware/middleware.go +++ b/internal/middleware/middleware.go @@ -35,13 +35,10 @@ const HSTSValue = "max-age=31536000; includeSubDomains" // ContentSecurityPolicyValue is the Content-Security-Policy header value. // default-src 'self' is the baseline and frame-ancestors 'none' is the primary -// clickjacking control. 'unsafe-inline' is required in script-src and style-src -// because the served templates carry inline onclick handlers (generator page) -// and the bundled Tailwind asset injects a runtime