Repository navigation
Add a strict Content-Security-Policy app-wide - #2
Merged
Merged
Conversation
A second lock behind the HTML sanitiser for the reader, which prints third-party article markup. Every web page, the installer included, now sends a policy that allows scripts only from this origin or with a per-request nonce: no unsafe-inline, no unsafe-eval, no inline event handlers, javascript: URLs or style attributes, nothing framing the app and forms posting only to it. Stored article images keep their own tighter policy, and the Vite dev server is allowed while it runs. To work under it, Alpine is now its CSP build: the reader and bulk selection are registered components that read their config from data attributes, and the inline onclick/onsubmit/onchange attributes are replaced by data-* hooks handled in resources/js/behaviours.js. The unused Breeze modal and dropdown components are removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014DPvSBmPyHN2QVmXsQQVKe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This adds a second lock behind the HTML sanitiser. The reader prints third-party article markup unescaped. With this policy, even markup that slipped past the sanitiser couldn't run script.
The policy
ContentSecurityPolicymiddleware applies to every web page, including the installer:unsafe-inlineorunsafe-eval. The nonce is fresh per request and comes fromVite::useCspNonce(), which also stamps it on the built asset tags.https:host is allowed, because article images that weren't downloaded keep their remotesrc.default-src 'none'.npm run dev: while the Vite dev server runs, its origin, its websocket and inline styles are allowed.What had to change to live under it
@alpinejs/csp.readerand the newbulkSelectionare registered components that read their settings fromdata-*attributes; the views no longer build a config object in the markup.onclick,onsubmitandonchangeattributes are replaced bydata-*attributes, handled by one listener inresources/js/behaviours.js:data-confirmasks before submitting a form;data-autosubmitsubmits a form when its select changes;data-select-on-clickselects a field's text;data-bookmarklet-hintshows the "drag me" message instead of following the link.<style>block.style=""attributes: the reader's themed borders and swatches are CSS classes now.modal,dropdownanddropdown-link. The modal couldn't work under the CSP build.Testing
New
ContentSecurityPolicyTestchecks:<script>;styleattribute (it renders every page, the bookmarklet popup and the login screen);<style>nonce;Checked in headless Chromium against the built bundle under this exact policy, before pushing:
data-confirm, sort autosubmit, the bookmarklet hint and select-on-click;None of the app's own code triggered a CSP violation. An injected
onclick,onerror,<script>andjavascript:link were all blocked.Generated by Claude Code