fix(auth): add a Content-Security-Policy to every Explorer page - #21
Merged
Merged
Conversation
TL;DR: Explorer pages now ship a Content-Security-Policy that lets only this origin's scripts plus the page's own nonced inline blocks run, allows styles only from this origin, and permits remote images because email bodies reference them. An injected script or event handler cannot execute even if some markup slips through. Problem: Explorer set X-Content-Type-Options, X-Frame-Options and Referrer-Policy but no CSP. It renders sanitized email bodies inline and holds a session cookie, which is exactly the page you want a script policy on. Auth got a nonce-based CSP in its first release; the applications did not. Fix: - security_headers middleware generates a per-response nonce, sets a page policy on text/html responses and a closed default-src 'none' policy on everything else. - Page policy: default-src 'self'; script-src 'self' plus the nonce; style-src 'self'; img-src 'self' data: https:; font-src and connect-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'. - The four inline <script> blocks (theme bootstrap and loading bar in base.html, inbox behaviour, detail behaviour) carry the nonce. The flatpickr vendor script loads from /static and needs none. - style-src is strict because the templates have no inline styles and the email sanitizer strips style attributes and <style> blocks; img-src allows https: and data: because sanitized email bodies keep <img src> over https, data and cid (cid never resolves). - No form-action: Elcano-mode logout is a form POST that redirects to the auth host, and browsers apply form-action to that redirect. Tests: - New: the inbox page's CSP names a nonce matching its inline scripts, the page has no bare <script>, inline handlers or style attributes, the nonce differs per response, and /health gets the closed policy. - Ran: pytest -q (full suite), ruff check, ruff format --check.
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.
TLDR
Every Explorer page ships a Content-Security-Policy: scripts only from this origin plus the page's nonced inline blocks, styles only from this origin, images from this origin plus
https:anddata:(sanitized email bodies keep<img src>),frame-ancestors 'none',object-src 'none',base-uri 'none'. Non-HTML responses getdefault-src 'none'.Why the policy can be strict on styles
The templates have no inline styles and
s3_email.pystripsstyleattributes and<style>blocks from email bodies before rendering, sostyle-src 'self'breaks nothing. Scripts: four inline blocks, all nonced; flatpickr loads from/static.Deliberate omission
No
form-action: Elcano-mode logout is a form POST that redirects to the auth host, and browsers applyform-actionto that redirect.Tests
Inbox page CSP nonce matches its inline scripts; no bare
<script>, inline handlers, or style attributes; nonce rotates per response;/healthgets the closed policy. Full suite, ruff check, ruff format green.