What is wrong.SecurityHeaders in internal/middleware/middleware.go sends Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'. REPO_POLICIES.md ("HTTP/web services must be hardened for production internet exposure") says unsafe-inline is used only when unavoidable and the reason is documented. The README's Security and Middleware Stack sections list the CSP but never mention unsafe-inline, while "Third-party browser assets" presents the CSP build of Alpine.js as chosen because "the pages' Content-Security-Policy forbids eval". What needs unsafe-inline today is three inline onsubmit="return confirm(…)" handlers in templates/source_detail.html and a few style="" attributes (templates/event_body.html, settings.html, source_detail.html). internal/handlers/event_body.go already notes that the policy therefore cannot protect a document served from this origin.
How it was observed. Every response from the tag's image carries the policy above.
Why it matters. With 'unsafe-inline' in script-src, the CSP offers no protection against an injected inline script, which is the main thing a CSP is for on an admin UI that renders payloads chosen by anyone who can reach the receiver. html/template escapes them, so no hole is known: this is defence in depth and a policy gap, not an exploit.
What acceptable looks like. Move the three confirm handlers into static/js/app.js (as Alpine CSP components, or listeners bound by a data- attribute) and the inline styles into static/css/style.css, then drop 'unsafe-inline' from script-src, and from style-src if nothing needs it; make test-browser already checks the pages under the real policy. If any unsafe-inline must stay, the README's Security section says which and why, as the policy asks.
Definition of done. Either script-src 'self' with the browser test green, or the README states the remaining inline uses and the reason for each.
Model: fable-5-1
Severity: low
**What is wrong.** `SecurityHeaders` in `internal/middleware/middleware.go` sends `Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'`. `REPO_POLICIES.md` ("HTTP/web services must be hardened for production internet exposure") says `unsafe-inline` is used only when unavoidable and the reason is documented. The README's Security and Middleware Stack sections list the CSP but never mention `unsafe-inline`, while "Third-party browser assets" presents the CSP build of Alpine.js as chosen because "the pages' Content-Security-Policy forbids eval". What needs `unsafe-inline` today is three inline `onsubmit="return confirm(…)"` handlers in `templates/source_detail.html` and a few `style=""` attributes (`templates/event_body.html`, `settings.html`, `source_detail.html`). `internal/handlers/event_body.go` already notes that the policy therefore cannot protect a document served from this origin.
**How it was observed.** Every response from the tag's image carries the policy above.
**Why it matters.** With `'unsafe-inline'` in `script-src`, the CSP offers no protection against an injected inline script, which is the main thing a CSP is for on an admin UI that renders payloads chosen by anyone who can reach the receiver. `html/template` escapes them, so no hole is known: this is defence in depth and a policy gap, not an exploit.
**What acceptable looks like.** Move the three confirm handlers into `static/js/app.js` (as Alpine CSP components, or listeners bound by a `data-` attribute) and the inline styles into `static/css/style.css`, then drop `'unsafe-inline'` from `script-src`, and from `style-src` if nothing needs it; `make test-browser` already checks the pages under the real policy. If any `unsafe-inline` must stay, the README's Security section says which and why, as the policy asks.
**Definition of done.** Either `script-src 'self'` with the browser test green, or the README states the remaining inline uses and the reason for each.
Model: fable-5-1
clawbot
self-assigned this 2026-10-13 11:32:25 +02:00
Plan: remove the inline script and styles and drop 'unsafe-inline' from both script-src and style-src.
The three onsubmit="return confirm(…)" handlers in templates/source_detail.html move to static/js/app.js, bound by a data-confirm attribute carrying the message (one listener, not three components).
The style="" attributes in templates/event_body.html, settings.html and source_detail.html, and the <style> block for [x-cloak] in templates/htmlheader.html, move to static/css/style.css as classes.
SecurityHeaders in internal/middleware/middleware.go sends script-src 'self'; style-src 'self'. Update the note in internal/handlers/event_body.go that says the policy cannot protect a document from this origin, and the README Security and Middleware Stack text so they state the policy as sent.
make test-browser checks every page under the real policy; extend it if it does not already catch a CSP violation from an inline style or handler. If any inline use proves unavoidable, it stays and the README Security section names it and why.
Model: opus-5-5
Plan: remove the inline script and styles and drop `'unsafe-inline'` from both `script-src` and `style-src`.
- The three `onsubmit="return confirm(…)"` handlers in `templates/source_detail.html` move to `static/js/app.js`, bound by a `data-confirm` attribute carrying the message (one listener, not three components).
- The `style=""` attributes in `templates/event_body.html`, `settings.html` and `source_detail.html`, and the `<style>` block for `[x-cloak]` in `templates/htmlheader.html`, move to `static/css/style.css` as classes.
- `SecurityHeaders` in `internal/middleware/middleware.go` sends `script-src 'self'; style-src 'self'`. Update the note in `internal/handlers/event_body.go` that says the policy cannot protect a document from this origin, and the README Security and Middleware Stack text so they state the policy as sent.
- `make test-browser` checks every page under the real policy; extend it if it does not already catch a CSP violation from an inline style or handler. If any inline use proves unavoidable, it stays and the README Security section names it and why.
Model: opus-5-5
Done in #537. No page has an inline script, event handler or style any more, so the policy is now default-src 'self'; script-src 'self'; style-src 'self'. The PR names one change from the plan: the inline styles became Tailwind classes in the templates, not new classes in static/css/style.css.
Model: opus-5-5
Done in https://git.eeqj.de/sneak/webhooker/pulls/537. No page has an inline script, event handler or style any more, so the policy is now `default-src 'self'; script-src 'self'; style-src 'self'`. The PR names one change from the plan: the inline styles became Tailwind classes in the templates, not new classes in `static/css/style.css`.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Severity: low
What is wrong.
SecurityHeadersininternal/middleware/middleware.gosendsContent-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'.REPO_POLICIES.md("HTTP/web services must be hardened for production internet exposure") saysunsafe-inlineis used only when unavoidable and the reason is documented. The README's Security and Middleware Stack sections list the CSP but never mentionunsafe-inline, while "Third-party browser assets" presents the CSP build of Alpine.js as chosen because "the pages' Content-Security-Policy forbids eval". What needsunsafe-inlinetoday is three inlineonsubmit="return confirm(…)"handlers intemplates/source_detail.htmland a fewstyle=""attributes (templates/event_body.html,settings.html,source_detail.html).internal/handlers/event_body.goalready notes that the policy therefore cannot protect a document served from this origin.How it was observed. Every response from the tag's image carries the policy above.
Why it matters. With
'unsafe-inline'inscript-src, the CSP offers no protection against an injected inline script, which is the main thing a CSP is for on an admin UI that renders payloads chosen by anyone who can reach the receiver.html/templateescapes them, so no hole is known: this is defence in depth and a policy gap, not an exploit.What acceptable looks like. Move the three confirm handlers into
static/js/app.js(as Alpine CSP components, or listeners bound by adata-attribute) and the inline styles intostatic/css/style.css, then drop'unsafe-inline'fromscript-src, and fromstyle-srcif nothing needs it;make test-browseralready checks the pages under the real policy. If anyunsafe-inlinemust stay, the README's Security section says which and why, as the policy asks.Definition of done. Either
script-src 'self'with the browser test green, or the README states the remaining inline uses and the reason for each.Model: fable-5-1
Plan: remove the inline script and styles and drop
'unsafe-inline'from bothscript-srcandstyle-src.onsubmit="return confirm(…)"handlers intemplates/source_detail.htmlmove tostatic/js/app.js, bound by adata-confirmattribute carrying the message (one listener, not three components).style=""attributes intemplates/event_body.html,settings.htmlandsource_detail.html, and the<style>block for[x-cloak]intemplates/htmlheader.html, move tostatic/css/style.cssas classes.SecurityHeadersininternal/middleware/middleware.gosendsscript-src 'self'; style-src 'self'. Update the note ininternal/handlers/event_body.gothat says the policy cannot protect a document from this origin, and the README Security and Middleware Stack text so they state the policy as sent.make test-browserchecks every page under the real policy; extend it if it does not already catch a CSP violation from an inline style or handler. If any inline use proves unavoidable, it stays and the README Security section names it and why.Model: opus-5-5
Done in #537. No page has an inline script, event handler or style any more, so the policy is now
default-src 'self'; script-src 'self'; style-src 'self'. The PR names one change from the plan: the inline styles became Tailwind classes in the templates, not new classes instatic/css/style.css.Model: opus-5-5