Skip to content

Add a Content-Security-Policy in Report-Only mode (refs #3041) - #3042

Merged
JacobCoffee merged 3 commits into
python:mainfrom
tonghuaroot:csp-report-only
Jul 29, 2026
Merged

Add a Content-Security-Policy in Report-Only mode (refs #3041)#3042
JacobCoffee merged 3 commits into
python:mainfrom
tonghuaroot:csp-report-only

Conversation

@tonghuaroot

Copy link
Copy Markdown
Contributor

Part of #3041 (adds the CSP in Report-Only mode; enforcing and origin tuning to follow).

What this does

www.python.org currently sends no Content-Security-Policy header. This adds one via django-csp as defense-in-depth against XSS.

It ships in Report-Only mode: responses carry Content-Security-Policy-Report-Only and no enforcing Content-Security-Policy, so nothing is blocked for users. The point of this first step is to collect violation reports and tune the allowlist before switching to an enforced policy.

Changes

  • pyproject.toml / uv.lock: add django-csp==4.0.
  • pydotorg/settings/base.py:
    • add csp.middleware.CSPMiddleware to MIDDLEWARE, alongside the existing XFrameOptionsMiddleware (which is how the site already sets a security header from Django).
    • add a CONTENT_SECURITY_POLICY_REPORT_ONLY policy with a strict starting set of directives.

Starting policy

default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:;
font-src 'self'; connect-src 'self'; frame-ancestors 'self'; base-uri 'self';
object-src 'none'; form-action 'self'

These are intentionally strict so the Report-Only telemetry surfaces every inline script/style and third-party origin that needs a nonce, hash, or allowlist entry. Follow-ups from #3041: add a report endpoint, tune the origins, wire nonces into the base templates, then flip Report-Only to enforcing.

Verification

Smoke-tested the config against django-csp 4.0 in isolation: it emits the Content-Security-Policy-Report-Only header with the directives above and no enforcing Content-Security-Policy header, so pages are never blocked.

@tonghuaroot
tonghuaroot requested a review from JacobCoffee as a code owner July 2, 2026 15:09
www.python.org currently sends no Content-Security-Policy header. This
adds one via django-csp as defense-in-depth against XSS, starting in
Report-Only mode so violations can be collected and the allowlist tuned
before the policy is enforced.

The middleware follows the existing XFrameOptionsMiddleware pattern.
Refs python#3041.

@sethmlarson sethmlarson left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, two comments:

Comment thread pydotorg/settings/base.py Outdated
Comment thread pydotorg/settings/base.py
@sethmlarson

Copy link
Copy Markdown
Contributor

@tonghuaroot Are you still interested in landing this PR?

@tonghuaroot

Copy link
Copy Markdown
Contributor Author

Yes, still keen to land it. Pushed both of your changes and it's ready for another look.

@JacobCoffee
JacobCoffee merged commit b39d327 into python:main Jul 29, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants