Summary
Right now www.python.org does not send a Content-Security-Policy header (a quick check of the response headers shows only X-Frame-Options: SAMEORIGIN and HSTS). Adding a CSP would give the site meaningful defense-in-depth against XSS: even if user-influenced HTML is ever mis-sanitized, a strict script-src with no unsafe-inline stops injected scripts and javascript: URIs from executing.
This follows up on a request from @sethmlarson to propose a CSP for the python.org service.
Why Report-Only first
python.org serves some inline scripts/styles and pulls assets from a CDN plus a few third-party origins, so a strict policy dropped straight into enforcing mode would break pages. The safe path is to roll out in Content-Security-Policy-Report-Only mode first, collect violation reports, tune the allowlist, and only then switch to enforcing.
Proposed rollout
- Add
django-csp and enable its middleware.
- Wire a per-request nonce into the
<script> / <style> tags in the base templates.
- Ship a
Content-Security-Policy-Report-Only policy with a reporting endpoint and collect violations for a couple of weeks.
- Tighten the allowlist from the reports (CDN, analytics, fonts, donate/embed widgets, and so on).
- Flip Report-Only to enforcing once the reports are clean.
Starting policy (Report-Only, to be tuned from reports)
default-src 'self';
script-src 'self' 'nonce-{request_nonce}';
style-src 'self' 'nonce-{request_nonce}';
img-src 'self' data:;
font-src 'self';
connect-src 'self';
frame-ancestors 'self';
base-uri 'self';
object-src 'none';
form-action 'self';
This is only a starting point. The exact script-src / style-src / img-src / connect-src origins depend on which third-party services python.org actually loads, which the Report-Only telemetry will surface.
Open questions for maintainers
- Which third-party origins (CDN, analytics, fonts, embedded widgets, donation flow) need allowlisting?
- Nonces vs hashes for the existing inline scripts and styles?
- Preferred reporting endpoint (self-hosted report handler vs an external collector)?
Happy to open a Report-Only PR (django-csp plus nonce wiring and the starting policy above) once the approach looks right.
Summary
Right now www.python.org does not send a
Content-Security-Policyheader (a quick check of the response headers shows onlyX-Frame-Options: SAMEORIGINand HSTS). Adding a CSP would give the site meaningful defense-in-depth against XSS: even if user-influenced HTML is ever mis-sanitized, a strictscript-srcwith nounsafe-inlinestops injected scripts andjavascript:URIs from executing.This follows up on a request from @sethmlarson to propose a CSP for the python.org service.
Why Report-Only first
python.org serves some inline scripts/styles and pulls assets from a CDN plus a few third-party origins, so a strict policy dropped straight into enforcing mode would break pages. The safe path is to roll out in
Content-Security-Policy-Report-Onlymode first, collect violation reports, tune the allowlist, and only then switch to enforcing.Proposed rollout
django-cspand enable its middleware.<script>/<style>tags in the base templates.Content-Security-Policy-Report-Onlypolicy with a reporting endpoint and collect violations for a couple of weeks.Starting policy (Report-Only, to be tuned from reports)
This is only a starting point. The exact
script-src/style-src/img-src/connect-srcorigins depend on which third-party services python.org actually loads, which the Report-Only telemetry will surface.Open questions for maintainers
Happy to open a Report-Only PR (django-csp plus nonce wiring and the starting policy above) once the approach looks right.