Skip to content

WT-536: improve our CSP unsafe-inline config by making it tighter and more specific#16994

Open
stevejalim wants to merge 3 commits intomainfrom
WT-536--unsafe-inline--two-paths
Open

WT-536: improve our CSP unsafe-inline config by making it tighter and more specific#16994
stevejalim wants to merge 3 commits intomainfrom
WT-536--unsafe-inline--two-paths

Conversation

@stevejalim
Copy link
Contributor

This changeset is an additional fixup around https://mozilla-hub.atlassian.net/browse/WT-536

It does a few things. My recommendation is to read the code first, then the rest of this description, so you are not swayed (and in case I've not got this right)

  1. for script-src, it only allows unsafe-inline for the Wagtail admin pages which are only enabled for the CMS deployment. This does not appear to affect anything else, but we really need to be sure (eg Transcend, GA, cookie banner)

  2. for style-src we had code that enabled unsafe-inline specifically for Transcend, but a few lines above we also had unsafe-inline set as a default. This changeset moves it so that style-src: unsafe-inline is only available if transcend is enabled.

Testing

I'd welcome a Slack chat about approaches here. I've pushed this branch to www-demo6.allizom.org where we can drive around and also try the CMS, but Transcend isn't enabled there - maybe we could enable it in demos too, tbc on @stephendherrera's blessing

…nd is enabled

Note that the previous cut of the code didn't add style-src: unsafe inline only
in Transcend mode: it was enabled all the time
@stevejalim stevejalim requested a review from a team as a code owner January 16, 2026 13:26
@codecov
Copy link

codecov bot commented Jan 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.42%. Comparing base (2ed16f3) to head (95a6a89).
⚠️ Report is 22 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #16994      +/-   ##
==========================================
+ Coverage   80.36%   81.42%   +1.06%     
==========================================
  Files         163      162       -1     
  Lines        9100     8474     -626     
==========================================
- Hits         7313     6900     -413     
+ Misses       1787     1574     -213     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Collaborator

@janbrasna janbrasna left a comment

Choose a reason for hiding this comment

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

I think this might make sentry noise again, unless transcend was reconfigured in the meantime:

(I still believe transcend's/airgap's defaults should not necessitate any unsafe inline exclusions; maybe it's just not configured to what bedrock sets for them — as they also have functionality to be managing and setting CSP on their own — perhaps they think they're setting it?…)

@@ -109,12 +109,12 @@
"www.googletagmanager.com",
"www.youtube.com",
csp.constants.UNSAFE_EVAL,
Copy link
Collaborator

@janbrasna janbrasna Jan 16, 2026

Choose a reason for hiding this comment

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

[unrelated] Wondering whether to be adding UNSAFE_EVAL only if DEV? (Is there a risk of missing any legit use when this would always be allowed in dev, incl. demos, but never in prod/stage?)

Comment on lines -117 to 119
CSP_ASSETS_HOST,
csp.constants.UNSAFE_INLINE,
"cdn.transcend.io", # Transcend Consent Management
"transcend-cdn.com", # Transcend Consent Management
Copy link
Collaborator

Choose a reason for hiding this comment

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

So, it was added for transcend. I still believe that has to be some misconfiguration, but… I don't see it added anywhere later for transcend — only for wagtail admin. (yay! but…)

Copy link
Collaborator

@janbrasna janbrasna Jan 19, 2026

Choose a reason for hiding this comment

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

… but after reading the description again and looking around the lines yes transcend's already covered there:

# Transcend Consent Management UI uses CSS-in-JS which requires inline styles.
if TRANSCEND_AIRGAP_URL: # noqa: F405
_csp_style_src.add(csp.constants.UNSAFE_INLINE)

right 🤦‍♂️ — so airgap shouldn't break. And it's well before the RO deepcopy so it'll also silence any RO noise.

So what this PR does is, where UNSAFE_INLINE was removed only from RO before, then recently refactored out even from there, this actually finally enforces it (but will most likely be relaxed back via env where airgap's enabled, but only based on that) — so the sentry reports should be watched esp. in deployments that don't enable airgap yet — like prod — that should be restricted now more than some others. EDIT: Prod has transcend linked, so it'll also be unsafe-inline; not sure which deployments currently don't link it, so those might be the noisy ones if there's still some violation unaddressed… but prod won't break.

Comment on lines 210 to 219
CMS_ADMIN_IMAGES_CSP_RO = csp_ro_report_uri and _override_csp(CONTENT_SECURITY_POLICY_REPORT_ONLY, append={"img-src": {"blob:"}})
# The CMS admin frames itself for page previews.
CMS_ADMIN_CSP = _override_csp(CONTENT_SECURITY_POLICY, replace={"frame-ancestors": {csp.constants.SELF}})


# The CMS admin frames itself for page previews and needs script-src: allow-inline
CMS_ADMIN_CSP = _override_csp(
CONTENT_SECURITY_POLICY,
replace={"frame-ancestors": {csp.constants.SELF}},
append={"script-src": {csp.constants.UNSAFE_INLINE}},
)
CMS_ADMIN_CSP_RO = csp_ro_report_uri and _override_csp(CONTENT_SECURITY_POLICY_REPORT_ONLY, replace={"frame-ancestors": {csp.constants.SELF}})
Copy link
Collaborator

Choose a reason for hiding this comment

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

You probably want to either have RO matching the prod, or… start with the rules in RO-only for now, and let it sit for a bit and see whether it would trigger anything before blocking things?

@stevejalim stevejalim requested a review from Copilot January 26, 2026 11:45
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR tightens the Content Security Policy (CSP) configuration by making unsafe-inline directives more targeted and specific. Instead of allowing unsafe-inline broadly across the application, it restricts these permissions to only the contexts where they are actually needed.

Changes:

  • Removed blanket unsafe-inline from default script-src CSP, adding it only for CMS admin pages
  • Removed default unsafe-inline from style-src CSP (appears to rely on Transcend-specific addition)
  • Updated CMS admin CSP configuration to explicitly include script-src: unsafe-inline with explanatory comment

"www.youtube.com",
csp.constants.UNSAFE_EVAL,
csp.constants.UNSAFE_INLINE,
# Don't allow csp.constants.UNSAFE_INLINE wholesale in the default CSP. Be more targetted with it
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

Corrected spelling of 'targetted' to 'targeted'.

Suggested change
# Don't allow csp.constants.UNSAFE_INLINE wholesale in the default CSP. Be more targetted with it
# Don't allow csp.constants.UNSAFE_INLINE wholesale in the default CSP. Be more targeted with it

Copilot uses AI. Check for mistakes.
Comment on lines 115 to 120
_csp_style_src = {
csp.constants.SELF,
CSP_ASSETS_HOST,
csp.constants.UNSAFE_INLINE,
"cdn.transcend.io", # Transcend Consent Management
"transcend-cdn.com", # Transcend Consent Management
}
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

The removal of unsafe-inline from _csp_style_src may break styling functionality if Transcend or other components require inline styles. The PR description mentions that unsafe-inline should only be available if Transcend is enabled, but this code doesn't show conditional logic for that. Consider verifying that inline styles are properly handled either through nonces or that all inline styles have been eliminated.

Copilot uses AI. Check for mistakes.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
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.

2 participants