feat: add Content-Security-Policy header with nonce for inline bootstrap#147
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThe Flask app now generates per-response CSP nonces for HTML responses, exposes them to templates, and removes inline event handlers across affected pages. Client scripts bind interactions through DOM listeners, while tests validate CSP headers, nonce propagation, and JSON API behavior. ChangesCSP nonce rollout
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Browser
participant FlaskHooks
participant TemplateRenderer
Browser->>FlaskHooks: request HTML page
FlaskHooks->>FlaskHooks: generate request nonce
FlaskHooks->>TemplateRenderer: render with csp_nonce
TemplateRenderer-->>FlaskHooks: nonce-protected HTML
FlaskHooks-->>Browser: HTML and CSP header
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/test_csp_header.py`:
- Around line 27-34: Extend test_html_page_nonce_matches_inline_script with a
second client.get("/search") request, extract its Content-Security-Policy nonce
using _extract_csp_nonce, and assert it differs from the first response’s nonce
while preserving the existing inline-script and policy assertions.
- Around line 27-34: Update test_html_page_nonce_matches_inline_script to assert
that the extracted nonce appears on a nonce-bearing script element rendered by
templates/search.html, rather than merely anywhere in the HTML. Preserve the
existing CSP equality assertion and response checks.
- Around line 21-34: Update the CSP tests around
test_html_page_nonce_matches_inline_script to define the expected policy
directives explicitly in the test and assert their parsed tokens are present,
rather than relying on substring checks or comparing against
build_content_security_policy(nonce). Keep nonce extraction and the assertion
that the HTML inline script uses that nonce, while ensuring the expected CSP is
independent of the production helper.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 7d628bdb-efc3-414d-a0e1-7d3c5b64f250
📒 Files selected for processing (10)
app.pystatic/js/app.jsstatic/js/download.jsstatic/js/theme-bootstrap.jstemplates/base.htmltemplates/config.htmltemplates/index.htmltemplates/search.htmltemplates/workspace.htmltests/test_csp_header.py
bradjin8
left a comment
There was a problem hiding this comment.
Nice to have: add /config to CSP header tests
test_html_page_has_content_security_policy_header covers / and workspace covers /workspace/global, but /config is the only remaining page route without an explicit CSP assertion. Quick addition for full page-route coverage.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
tests/test_csp_header.py (1)
105-108: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick winValidate the workspace CSP directives, not only header presence.
A malformed or nonce-less policy on
/workspace/globalcould pass while the other route tests remain green. Extract the nonce and reuse_assert_expected_csp_directiveshere.Proposed assertion
assert csp + nonce = _extract_csp_nonce(csp) + _assert_expected_csp_directives(csp, nonce)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_csp_header.py` around lines 105 - 108, Update test_workspace_page_has_content_security_policy_header to extract the CSP nonce from the response and pass it to _assert_expected_csp_directives, validating the expected directives rather than only asserting header presence. Preserve the existing status-code assertion and use the response’s Content-Security-Policy header as the assertion input.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/test_csp_header.py`:
- Around line 82-96: Update test_html_page_nonce_matches_inline_script to
validate the second response body as well: call _assert_expected_csp_directives
with second_csp and second_nonce, then call _assert_inline_script_nonce with
second.get_data(as_text=True) and second_nonce, while preserving the existing
first-response assertions.
---
Outside diff comments:
In `@tests/test_csp_header.py`:
- Around line 105-108: Update
test_workspace_page_has_content_security_policy_header to extract the CSP nonce
from the response and pass it to _assert_expected_csp_directives, validating the
expected directives rather than only asserting header presence. Preserve the
existing status-code assertion and use the response’s Content-Security-Policy
header as the assertion input.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
Closes #141
adds a content-security-policy header on html pages only. each response gets a random nonce; inline scripts in the page templates use it, and the head theme bootstrap moved to static/js/theme-bootstrap.js so script-src stays tight. json api routes don't get the header.
pulled all onclick/onchange handlers out of the templates and wired them with addeventlistener instead, including sidebar click delegation in workspace.html. policy allows self plus cdnjs for scripts and styles; style-src keeps unsafe-inline because highlight.js themes need it.
tests/test_csp_header.py checks the header on page routes, nonce matches the inline script, and /api/workspaces has no csp. pytest tests/test_csp_header.py passes.
Summary by CodeRabbit