Closed Bug 2056579 Opened 2 months ago Closed 2 months ago

Firefox built-in VPN does not set media.peerconnection.ice.proxy_only while active, so WebRTC STUN over UDP bypasses the proxy and exposes the user's real IP, defeating the feature's stated IP-protection with no user warning

Categories

(Firefox :: IP Protection, defect)

Firefox 155
Unspecified
macOS
defect

Tracking

()

RESOLVED DUPLICATE of bug 2026571

People

(Reporter: mihalis.haatainen, Unassigned)

References

Details

(4 keywords, Whiteboard: [client-bounty-form])

Attachments

(1 file)

Attached file webrtc_ip_leak.html β€”

Description

The Firefox built-in VPN (launched Firefox 149, March 2026) is marketed as an IP-protection feature. Mozilla's own descriptions state it "routes your traffic through a proxy server, so websites see a different IP address instead of your real one" (firefox.com) and is "a new IP-protection feature designed to keep you even more private while you browse" (blog.mozilla.org).

The feature is implemented as a browser-layer HTTPS proxy. WebRTC ICE gathering uses STUN requests over UDP, which the HTTPS proxy does not tunnel. As a result, when the built-in VPN is active, WebRTC still reflects the user's real public IP address via a server-reflexive (srflx) ICE candidate, while HTTP(S) traffic correctly shows the proxy exit IP.

The practical effect: a user who enables the built-in VPN believing it masks their IP has their real IP silently exposed to any website that runs a few lines of RTCPeerConnection JavaScript, with no camera/microphone prompt and no warning.

Relationship to bug 959893

I am aware of bug 959893, which covers the general WebRTC IP-exposure mechanism and was resolved as conformant to the RTCWEB spec, with mitigation left to opt-in prefs (media.peerconnection.ice.proxy_only / proxy_only_if_behind_proxy) and mDNS for local addresses.

This report is narrower and concerns the new product, not the engine default. 959893 is about Firefox's default WebRTC behavior for a user who has not configured any proxy. This report is about the built-in VPN feature, when explicitly enabled by the user, failing to activate the pref that already exists to close this exact hole. The user has taken an explicit action (toggling on an "IP-protection" feature) and has a reasonable, Mozilla-stated expectation that their real IP is now masked. The feature does not set proxy_only, so that expectation is silently violated.

In other words: the mechanism is known (959893), but the product-integration decision to ship an IP-protection feature without enabling the available WebRTC mitigation is the issue here.

Steps to reproduce

  1. Enable the Firefox built-in VPN (toolbar VPN icon).
  2. Confirm the proxy is active: visit an IP-check site; it shows the proxy exit IP (ISP "Mozilla Corporation" / Fastly).
  3. On any page, run:
const pc = new RTCPeerConnection({iceServers:[{urls:'stun:stun.l.google.com:19302'}]});
pc.onicecandidate = e => { if (e.candidate) console.log(e.candidate.candidate); };
pc.createDataChannel('x');
pc.createOffer().then(o => pc.setLocalDescription(o));

or

run poc.

  1. Observe the srflx candidate.

Actual results

With the built-in VPN active:

  • HTTP(S) exit IP (IP-check site): 45.58.232.100 (Mozilla / Fastly proxy exit)
  • WebRTC srflx candidate: ...(my real ISP public IP, confirmed identical to the IP shown with the VPN disabled)
    Host candidates were correctly mDNS-obfuscated (.local), so the local LAN IP did not leak. The issue is specifically the real public IP leaking via the srflx candidate while the VPN is on.

Expected results

When the built-in VPN is active, WebRTC should not expose the real public IP that the feature is masking for all other browser traffic. Enabling the VPN should also constrain WebRTC (for example by setting media.peerconnection.ice.proxy_only, or proxy_only_if_behind_proxy, or otherwise forcing ICE through the proxy / relay-only) so that the real IP is not reflected. If a trade-off with WebRTC functionality is unavoidable, the limitation should at minimum be disclosed to the user when the VPN is enabled, rather than silently leaking.

Impact

The feature's entire stated purpose is masking the user's IP. A user on public Wi-Fi, or a user trying not to link activity across sites (both use cases Mozilla names explicitly in its announcement), can be deanonymized by any site running trivial WebRTC JavaScript, despite having the VPN enabled and believing they are protected. The gap is invisible: there is no prompt, no indicator, and the HTTP-level IP check that a user might perform to "verify" the VPN shows the proxy IP, giving false confidence.

Suggested fix

When the built-in VPN is enabled, set media.peerconnection.ice.proxy_only (or proxy_only_if_behind_proxy) for the duration, so WebRTC ICE is forced through the proxy and the real IP is not gathered as a candidate. This is a small, targeted change scoped to the VPN feature's active state; it does not change default WebRTC behavior for users who are not using the built-in VPN. Alternatively, surface the WebRTC limitation clearly in the VPN UI/support documentation.

Flags: sec-bounty?

Confirmed in about:config: with the built-in VPN active, media.peerconnection.ice.proxy_only is false.

So the mitigation that exists specifically to keep WebRTC from reflecting the real IP is not enabled while the VPN is on. The feature masks HTTP(S) through the Fastly proxy but leaves WebRTC ICE gathering on the direct path, which is why the srflx candidate returns the real public IP.

This is the whole gap in one line: the pref that would close it ships false while an IP-protection feature is active. Setting it true for the duration of the VPN session (scoped to the feature, no change to default behavior for non-VPN users) closes it.

OS: Unspecified → macOS
Version: unspecified → Firefox 155
Attached image Screenshot 2026-07-21 at 17.44.47.png (obsolete) β€”
Attached image Screenshot 2026-07-21 at 17.44.24.png (obsolete) β€”
Group: core-security
Component: Security → WebRTC
Product: Firefox → Core

Can someone from mozilla side, fix the bug... getting notification triage owner cant see this ticket...

Hello, this bug is ~7 hours old and has not been triaged yet. Please be patient.

Group: core-security, firefox-core-security → media-core-security

It's probably more up to the "IP Protection" folks to modify prefs like this. The WebRTC engine itself doesn't necessarily know when that is active. I suppose you could argue it either way.

Group: media-core-security → firefox-core-security
Status: UNCONFIRMED → NEW
Component: WebRTC → IP Protection
Ever confirmed: true
Product: Core → Firefox

Re the sec-low rating. The closest precedent for this bug class is bug 1657916 (CVE-2020-35111), and reading it through is what makes me think low is the wrong landing spot here.

In comment 5 of that bug, :freddy set the test up front: sec-low unless there is a way to trigger the load from web content, and if a leak from an evil website were found, sec-moderate. In comment 6 the reporter reported back that he could only reach it by flipping security.view-source.reachable-from-inner-protocol and adding user interaction, and correctly did not count that. In comment 11, :freddy stated the general rule plainly, that proxy bypasses triggered from web content in a non-webextension setting are generally considered sec-high, and said he had kept the bug private in case that path turned up.

It never turned up, so the bug settled at sec-low. The rating was a function of unreachability, not of the leak being unimportant.

This report satisfies the condition that one failed:

triggered from web content, any page, first load
no user interaction, no prompt, no pref changes
no extension involved, this is a first-party shipped feature
deterministic, five lines of script
what leaks is the user's real public IP, which is the specific value the enabled feature exists to mask

By the standard written into 1657916, content-triggerable puts this at sec-moderate at minimum.

On the shape of the defect: this is not a code fault so much as a protection that was not applied. Firefox already carries the mitigation. media.peerconnection.ice.proxy_only exists for exactly this leak and ships false while IP Protection is on. Worth noting that bug 1677047, adding H323, PPTP and RTSP ports to the restricted list, was also a missing-protection issue with no external exploit attached, and it was keyworded sec-moderate. A gap in a defensive measure has been rated moderate here before.

I am not pushing for high. I am asking that it not be rated below the level the team itself set for the content-triggerable version of this exact leak.

I thought bug 2026571 was meant to have fixed this - Basti?

Flags: needinfo?(sstreich)
See Also: → CVE-2026-6782

Yes it should. Using the webrtc_ip_leak.html while vpn-on this does just seem to timeout on my machine using FF-154.
While the vpn is active we do set proxy_only_if_behind_proxy, unless a user has touched the pref value, in which case we leave it at whatever the user had.

The bug also report only mentioned Firefox 149, we shipped the fix in 150.

Flags: needinfo?(sstreich)
Attached image Screenshot 2026-07-27 at 16.00.05.png (obsolete) β€”

155.0a1 (2026-07-27) (aarch64)

seems working fine

Attached image Screenshot 2026-07-27 at 16.01.59.png (obsolete) β€”

And so does on 153.0 (aarch64)

(In reply to Mihalis Haatainen from comment #10)

Created attachment 9616735 [details]
Screenshot 2026-07-27 at 16.00.05.png

155.0a1 (2026-07-27) (aarch64)

seems working fine

So I'll close this as a dupe, then? I'm confused why you filed this if you also tested this before and it was already fixed... 149/150 are now several months old...

Status: NEW → RESOLVED
Closed: 2 months ago
Duplicate of bug: CVE-2026-6782
Resolution: --- → DUPLICATE

No, I mean :Gijs bypass working fine..

So its not yet fixed... dont close it, or some how the fix is incomplete, cause it leaks real ip...

Flags: needinfo?(sstreich)
Status: RESOLVED → REOPENED
No longer duplicate of bug: CVE-2026-6782
Resolution: DUPLICATE → ---

Can someone give me access to => https://bugzilla.mozilla.org/show_bug.cgi?id=2026571 so I can investigate why the ip leak still works..

Status: REOPENED → RESOLVED
Closed: 2 months ago → 2 months ago
Resolution: --- → INVALID

Why did you re-close this as invalid?

Flags: needinfo?(mihalis.haatainen)

(In reply to Mihalis Haatainen from comment #15)

Can someone give me access to => https://bugzilla.mozilla.org/show_bug.cgi?id=2026571 so I can investigate why the ip leak still works..

It's basically exactly the same kind of report as this one. The report will be opened up once fixed versions have been public for a while.

The fix here (which by our open source nature is already public) was https://hg.mozilla.org/mozilla-central/rev/27e9dcd7d2fa , if that's helpful at all.

The relevant file is :) https://searchfox.org/firefox-main/source/toolkit/components/ipprotection/IPPSessionPrefManager.sys.mjs

Thank you for the screenshot! We do set proxy_only_if_behind_proxy.
In your screenshot you are loding the site via localhost. As per IPPExceptionsManager [1], localhost is always excluded therefore the pref does not go into affect here. Given your localhost page was not loaded using the vpn, that is correct behavior imho.

Could you demonstrate loading this using a remote url, that is not excluded from the vpn? i.e loading your attachment: https://bugzilla.mozilla.org/attachment.cgi?id=9613900

[1] https://searchfox.org/firefox-main/source/toolkit/components/ipprotection/IPPExceptionsManager.sys.mjs#346-348

Flags: needinfo?(sstreich)

You're right, my bad.
I was testing the PoC from localhost, which is always excluded from the VPN (IPPExceptionsManager). That's why the real IP still appeared.
When I load the exact same page from a remote origin (e.g. the Cloudflare Worker version or the Bugzilla attachment itself) with the built-in VPN active, the srflx candidate no longer shows the real public IP. The media.peerconnection.ice.proxy_only_if_behind_proxy preference is correctly applied and the leak is blocked.

So the fix from bug 2026571 is working as intended for normal (non-localhost) pages. Sorry for the noise / reopening.
Thanks for the clarification, Sebastian.

Flags: needinfo?(mihalis.haatainen)

All good! thank you for hunting bugs :)

Always! so far best program to hunt! :)

Btw, can someone remove the attachments, so wont dox my ip to world....

(In reply to Mihalis Haatainen from comment #22)

Btw, can someone remove the attachments, so wont dox my ip to world....

I don't know if they can be deleted but I've marked them private, this is typically how we handle sensitive attachments. Only a subset of Mozilla employees with security access will be able to see them now.

Duplicate of bug: CVE-2026-6782
Resolution: INVALID → DUPLICATE
Flags: sec-bounty? → sec-bounty-
Group: firefox-core-security
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: