Closed Bug 1791322 (CVE-2025-8042) Opened 3 years ago Closed 8 months ago

Iframe sandbox on Android do not prevent downloads from different sites

Categories

(GeckoView :: General, defect, P2)

defect

Tracking

(firefox139 wontfix, firefox140 wontfix, firefox141+ fixed)

RESOLVED FIXED
141 Branch
Tracking Status
firefox139 --- wontfix
firefox140 --- wontfix
firefox141 + fixed

People

(Reporter: haxatron1, Assigned: calu)

References

(Blocks 1 open bug)

Details

(Keywords: reporter-external, sec-moderate, Whiteboard: [see comment 13][reporter-external] [client-bounty-form] [verif?][geckoview:m110?] [geckoview:m113?][group4][adv-main141+])

Attachments

(4 files, 1 obsolete file)

Attached file iframe-download.html

Despite MDN webdocs specifying that allow-downloads attribute is enabled on Firefox for Android since v82, Firefox for Android still continues to download files even when an iframe is sandboxed without the allow-downloads attributes set. This is a problem, because a malicious sandboxed advertisement may serve malicious APK to a site that a user trusts, bypassing the sandbox. The origin of the download site is not displayed too, leading users to believe that the victim site is the one serving the download.

STR

  1. Open iframe-download.html on Firefox Android, prompt to download occurs (the download is the zipped source code for mozilla-mobile/fenix.)
  2. Click "Download", the file is downloaded onto the Android system even with the iframe being sandboxed without allow-downloads present.
  3. On contrast, loading iframe-download.html on Firefox for Desktop, Chrome for Desktop and Chrome for Android does not trigger the download.
Flags: sec-bounty?
Group: firefox-core-security → mobile-core-security
Component: Security → Security: Android
Product: Firefox → Fenix
Component: Security: Android → General
Product: Fenix → GeckoView

I don't know why Android GeckoView would be any different in this regard than normal Gecko. Isn't <iframe sandbox> pretty core?

Status: UNCONFIRMED → NEW
Ever confirmed: true
Keywords: sec-moderate

There's a pref about whether we block this, but it's true on all platforms. but it's called from a classifyURL function that maybe GV skips? Or maybe it's being called from a System Privileged context (wrong triggering principal?)?

https://searchfox.org/mozilla-central/source/dom/security/nsContentSecurityUtils.cpp#1537

It looks like we do have some WPT tests that test various aspects of downloads getting blocked by iframes... but as far as I can see, they're all marked as failing on Android. In fact, it looks like one of the initial landings got backed out for changing WPTs and failing, then the final landing marked some of these tests as failing on Android. I don't see any discussion in the bug about that change, and I didn't see any other bugs filed with followup work, so I'm not sure what's going on there.

See Also: → 1558394

Per comment 3, it feels like this is probably more of a platform issue than a Fenix issue, but maybe it'll turn out that Fenix is invoking this check incorrectly somehow.

Group: mobile-core-security → core-security
Component: General → DOM: Security
Product: GeckoView → Core
Group: core-security → dom-core-security

The severity field is not set for this bug.
:freddy, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(fbraun)
Flags: needinfo?(fbraun)

The severity field is not set for this bug.
:freddy, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(fbraun)

csadilek says this is more likely a GeckoView bug.

Component: DOM: Security → Extensions
Flags: needinfo?(fbraun)
Product: Core → GeckoView

Christian and I looked at this today, and we think the problem lies in GeckoViewExternalAppService, because that is the spot where the desktop code diverges from Android. We might need to do similar work to what has been done here (see this comment with links to the commits) in GV or somehow consolidate the code paths.

Whiteboard: [reporter-external] [client-bounty-form] [verif?] → [reporter-external] [client-bounty-form] [verif?][geckoview:m109?]

The severity field is not set for this bug.
:cpeterson, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(cpeterson)
Group: dom-core-security → mobile-core-security
Component: Extensions → Core
Severity: -- → S3
Flags: needinfo?(cpeterson)
Priority: -- → P2
Whiteboard: [reporter-external] [client-bounty-form] [verif?][geckoview:m109?] → [reporter-external] [client-bounty-form] [verif?]
Whiteboard: [reporter-external] [client-bounty-form] [verif?] → [reporter-external] [client-bounty-form] [verif?][geckoview:m110?]
Rank: 110

Mobile sec triage - we would like to be able to act on sandboxed iframe events. See also bug 1791312.

Whiteboard: [reporter-external] [client-bounty-form] [verif?][geckoview:m110?] → [reporter-external] [client-bounty-form] [verif?][geckoview:m110?] [geckoview:m113?]
Duplicate of this bug: 1818600
Duplicate of this bug: 1840266

When support for restricting sandboxed downloads was implemented in bug 1558394 we already knew it didn't work on Android as shown by annotating the Web-platform tests for this feature as "known failure" on android. It would have been better/clearer if sstreich had filed task bugs to fix those tests later.

Whiteboard: [reporter-external] [client-bounty-form] [verif?][geckoview:m110?] [geckoview:m113?] → [see comment 13][reporter-external] [client-bounty-form] [verif?][geckoview:m110?] [geckoview:m113?]
Flags: sec-bounty? → sec-bounty+
Component: Core → General
Duplicate of this bug: 1924826
Duplicate of this bug: 1933383

Hi Cathy, can you please add this one to your squad's queue?

Flags: needinfo?(calu)
Whiteboard: [see comment 13][reporter-external] [client-bounty-form] [verif?][geckoview:m110?] [geckoview:m113?] → [see comment 13][reporter-external] [client-bounty-form] [verif?][geckoview:m110?] [geckoview:m113?][group4]
Flags: needinfo?(calu)

I am able to reproduce this on Fenix and have been comparing the behavior between mobile and desktop. Desktop has implemented flags that trigger when attributes are in <iframe sandbox> but that implementation is missing on mobile. More details below:

When are the sandbox checks applied?
Took a look at GeckoViewExternalAppService, child of nsIExternalHelperAppService, and saw how android handles download requests differently from desktop. When DocumentLoadListener creates a listener, TryExternalHelperApp calls GeckoViewExternalAppservice createListener and creates a GeckoViewStreamListener, whereas desktop uses nsIExternalHelperAppService.
On the desktop side, nsIExternalHelperAppService onStartRequest calls classifyDownload where it then checks for triggering sandbox flags. On the geckoView side, onStartRequest is called by GeckoViewStreamListener and not the service. GeckoViewStreamListener does no such checks and is also a generic data stream handler for any external content. GeckoViewExternalAppService may also be too late to enforce sandbox restrictions since the download is already accepted and being streamed to the app.

Next is identifying where the sandbox flags are being applied, potentially at DocumentLoadListener::CreateDocumentLoadInfo.

During the nsContentSecurityUtils classifyDownloads check, downloads is blocked based on loadInfo->GetTriggeringSandboxFlags() and loadInfo->GetSandboxFlags(). Android has those flags available when the listener is created, before the download starts, and we just need to do the same check to the nsIChannel and its LoadInfo. Similar to desktop's usage of classifyDownloads here at nsExternalHelperAppService OnStartRequest, we should return early to cancel the download.

I included a patch with the fix.
Next steps are to fix and enable the web platform tests for Android.

Assignee: nobody → calu
Status: NEW → ASSIGNED

The fix works to block downloads without the proper attribute on navigation and on user click. It is included in the WIP. The WPT tests however are not working properly as it's still saying a download was completed. I find it strange that the GeckoView Test Runner page doesn't actually show the download button, and it also makes it difficult for me to debug outside of the automated test. Will be working on that this week.

Emilio shared with me using wpt.live, website version of all the html tests, and all the sandbox download tests pass on mobile with my fix now (except for an anchor test that also fails on desktop <a download> triggered download in sandbox is blocked before a request is made). None still pass on WPT so I just need to investigate the difference between wpt.live and ./mach wpt.

As for the above comment, the reason why the GeckoView Test Runner page is showing up blank is because the test opens a new about:blank tab and GeckoView Test Runner doesn't have tab switching functionality. The tests are still running though. This makes it difficult to test though, which is why it's a good sign it works on wpt.live.

Pushed by calu@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/3350c1e440f6 https://hg.mozilla.org/integration/autoland/rev/fa40cbf06b8e GeckoView should call classifyDownloads to sandbox downloads r=geckoview-reviewers,nika
Group: mobile-core-security → core-security-release
Status: ASSIGNED → RESOLVED
Closed: 8 months ago
Resolution: --- → FIXED
Target Milestone: --- → 141 Branch

:calu, is this safe for a beta uplift? Since it's a secbug, we could take it after some bake time in Nightly.

Flags: needinfo?(calu)

Thanks for asking, I think baking in nightly is good.

Flags: needinfo?(calu)

The patch landed in nightly and beta is affected.
:calu, is this bug important enough to require an uplift?

For more information, please visit BugBot documentation.

Flags: needinfo?(calu)
Flags: needinfo?(calu)

A patch has been attached on this bug, which was already closed. Filing a separate bug will ensure better tracking. If this was not by mistake and further action is needed, please alert the appropriate party. (Or: if the patch doesn't change behavior -- e.g. landing a test case, or fixing a typo -- then feel free to disregard this message)

QA Whiteboard: [sec] [qa-triage-done-c142/b141]
Whiteboard: [see comment 13][reporter-external] [client-bounty-form] [verif?][geckoview:m110?] [geckoview:m113?][group4] → [see comment 13][reporter-external] [client-bounty-form] [verif?][geckoview:m110?] [geckoview:m113?][group4][adv-main141+]

(In reply to Cathy Lu [:calu] from comment #21)

(except for an anchor test that also fails on desktop <a download> triggered download in sandbox is blocked before a request is made).

Is this already fixed now or should there be a follow-up bug?

Flags: needinfo?(calu)
Attached file advisory.txt (obsolete) —
Attached file advisory.txt
Attachment #9500499 - Attachment is obsolete: true

That test has been fixed with the latest patch updating the tests with a delay.

Flags: needinfo?(calu)
Alias: CVE-2025-8042
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: