Closed Bug 1980302 Opened 6 months ago Closed 4 months ago

Firefox shows the wrong prompt when redirecting to local IP address captive-portal page, when connecting to library open-wifi hotspot with 198.18..* ip-address scheme (redirect blocked with `NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED`)

Categories

(Core :: Networking: HTTP, defect, P2)

defect

Tracking

()

RESOLVED FIXED
147 Branch
Tracking Status
firefox-esr115 --- unaffected
firefox-esr128 --- unaffected
firefox-esr140 --- unaffected
firefox141 --- unaffected
firefox142 --- unaffected
firefox143 --- disabled
firefox144 --- disabled
firefox145 + disabled
firefox146 --- fixed
firefox147 --- fixed

People

(Reporter: dholbert, Assigned: valentin)

References

(Blocks 1 open bug, Regression)

Details

(Keywords: regression, Whiteboard: [necko-triaged][necko-priority-next])

Attachments

(6 files)

STR:

  1. Visit my local library
  2. Connect to the open WiFi network
  3. Open Firefox and try to reach the captive-portal, e.g. by visiting a HTTP site like http://example.org/ to trigger the captive-portal redirector.

ACTUAL RESULTS:
I see a redirector page from the captive portal that says "Please wait...", but I never make it off of that page. As a result, I'm unable to connect to WiFi (unless I switch browsers).
[EDIT: In recent Nightlies, I also get a prompt that I can click through, but the prompt is about letting the site access my device, which doesn't seem right]

EXPECTED RESULTS:
Should have successfully redirected.
[EDIT: Or, we should have shown a prompt that's more-clearly-relevant for this redirect/captive-portal situation.]

Network DevTools show that there was a failed GET request to this URL

http://198.18.32.1/reg.php?ah_goal=rwc_eula.html&ah_login=true&url=E2B8F3578D88E9B73A87F85782920F97D02C50

In the "Transferred" column, it shows the reason for failure:

NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED

I get ACTUAL RESULTS in a fresh profile with current Nightly.
I get EXPECTED RESULTS from Chrome and from Firefox release 136.0.2 (which happened to be the release version I had handy on this machine). So this is a regression with respect to that release.

Searching searchfox for the error code, I suspect this is related to the LNA aka "local network access" feature.

Here's a profile of the issue, with network-logging enabled:
https://share.firefox.dev/3IRaJfn

The network track shows the request to http://198.18.32.1/reg.php?ah_goal=rwc_eula.html&ah_login=true&url=E2B8F3578D88E9B73A87F85782920F97D02C50 which gets blocked with NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED

Summary: Firefox is unable to redirect to local IP address captive-portal page, to connect to library open-wifi hotspot → Firefox is unable to redirect to local IP address captive-portal page, to connect to library open-wifi hotspot (redirect blocked with `NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED`)

When testing with latest Nightly and a fresh profile via mozregression just now, I got the displayed prompt asking me if I'd like to allow example.org to access other apps and services on this device.

When I clicked "Allow" in that dialog, Firefox successfully redirected to the login page, so I guess that's the way through this right now, though:
(a) I didn't get this prompt the first few times that I tried this, for some reason.
(b) the prompt itself (about granting access to things on this device) isn't clear that it might be related to the open-wifi captive-portal redirect, i.e. accessing things on my network.

mozregression:
INFO: Last good revision: 1f8bd7536973c92275380383289e3b8c512ba8d3
INFO: First bad revision: bcfe73462e29fc9f31e82cb32351d8c37c8914aa
INFO: Pushlog:
https://hg.mozilla.org/integration/autoland/pushloghtml?fromchange=1f8bd7536973c92275380383289e3b8c512ba8d3&tochange=bcfe73462e29fc9f31e82cb32351d8c37c8914aa

I'm guessing regression from "Bug 1972350 - Local Network Permission UI impl." but maybe another related change in that push.

Sunil, could you take a look here? I wonder how this feature is supposed to work with this sort of captive-portal detection?

[Tracking Requested - why for this release]: new regression, preventing folks from connecting to the internet on certain public wifi hotspots.

Keywords: regression
Regressed by: 1972350

:smayya, since you are the author of the regressor, bug 1972350, could you take a look? Also, could you set the severity field?

For more information, please visit BugBot documentation.

Flags: needinfo?(smayya)

The prompt from comment 3 appears reliably in latest Nightly -- it wasn't appearing for me in comment 0 because I was on a slightly-older Nightly at that point I guess.

I did some mozregression --find-fix testing to see when that prompt appeared, and it seems to have started appearing (for my STR) in this pushlog:
https://hg.mozilla.org/mozilla-central/pushloghtml?fromchange=1d8c4ad21ed7547360c15615b93baaf5a09e78d2&tochange=d7eb324b222d504f43ff0edbc431daac6df35581

The only relevant bug in that pushlog is Bug 1979758 so I'm assuming the changes there are what caused the prompt to start appearing.

So: Given that we now have a prompt, this is better than the ACTUAL RESULTS in comment 0; but the language in the dialog still doesn't seem appropriate/accurate for a captive-portal scenario...

Also: looking at that bug, it seems this behavior is behind a Nightly-only pref network.lna.blocking, so maybe we don't need to track this for v143 after all (since presumably this won't ride to release until we lift the Nightly guard from that pref).

(I confirmed that I get EXPECTED RESULTS (insta-redirect) -- even in latest Nightly 2025-07-30 -- with network.lna.blocking set to false.)

(In reply to Daniel Holbert [:dholbert] from comment #0)

STR:

  1. Visit my local library
    I am afraid I need to cross multiple continents to visit your local library :D

With Bug 1979758 closed, we should see prompts reliably and the user action should allow/deny the request. I am glad you dont have connectivity issue.
Regarding the prompt, I am not sure why you are seeing localhost prompt (we have local network prompt for accessing devices on your wifi/private network) . This means someone in the public or private (wifi) network is accessing your computer. Could you please share devtools screenshot when the prompt is requested

Flags: needinfo?(smayya) → needinfo?(dholbert)

The bug is marked as tracked for firefox143 (nightly). We have limited time to fix this, the soft freeze is in 14 days. However, the bug still isn't assigned.

:ghess, could you please find an assignee for this tracked bug? Given that it is a regression and we know the cause, we could also simply backout the regressor. If you disagree with the tracking decision, please talk with the release managers.

For more information, please visit BugBot documentation.

Flags: needinfo?(ghess)

(In reply to BugBot [:suhaib / :marco/ :calixte] from comment #10)

The bug is marked as tracked for firefox143 (nightly). We have limited time to fix this, the soft freeze is in 14 days. However, the bug still isn't assigned.

We can untrack given this is behind a nightly guard (I didn't know there was a pref when I requested tracking).

(In reply to Sunil Mayya from comment #9)

Regarding the prompt, I am not sure why you are seeing localhost prompt (we have local network prompt for accessing devices on your wifi/private network) . This means someone in the public or private (wifi) network is accessing your computer

That's of course possible, but given how reliably I saw this when we attempted to redirect to the 192.* splash page, I suspect it was related to the blocked redirect and we were getting our wires crossed somehow.

Could you please share devtools screenshot when the prompt is requested

Will do (or better yet, a pernosco trace). Might be a few days before I'm back there, though I might swing by this afternoon.

Flags: needinfo?(ghess)
Flags: needinfo?(dholbert)
Flags: needinfo?(dholbert)

(updating title to reflect the fact that the issue here is the wrong prompt, not that the redirect is blocked anymore)

Summary: Firefox is unable to redirect to local IP address captive-portal page, to connect to library open-wifi hotspot (redirect blocked with `NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED`) → Firefox shows the wrong prompt when redirecting to local IP address captive-portal page, when connecting to library open-wifi hotspot (redirect blocked with `NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED`)
Could you please share devtools screenshot when the prompt is requested

Here's a screencast with devtools open, showing when the prompt opens.

And here's the profile that I captured during this screencast, with network logging enabled:
https://share.firefox.dev/4oehJ68

Here's the full HTML of the redirector page that spawns the prompt here:

<html>
<head>
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-store, no-cache, must-revalidate, max-age=0"> 
<META HTTP-EQUIV="expires" CONTENT='0'>
<title>REDIR</title>
</head>
<body onLoad='redirTimer()'>Please wait...<SCRIPT LANGUAGE='JavaScript'>
redirTime = '500';
redirURL = 'http://198.18.32.1:80/reg.php?ah_goal=rwc_eula.html&ah_login=true&url=E2B8F3578D88E9B73A87F85782920F97D02C50';
function redirTimer() { 
       self.setTimeout('self.location.href = redirURL;',redirTime); 
}
</script> 
<br>If you cannot see the login page, close and then reopen your browser and try again.</font></div></body></html>

Maybe this is reproducible on any arbitrary network with a testcase like that^, hosted from a remote web server, which redirects to your own local router's IP address? (will test later)

Flags: needinfo?(dholbert)

(In reply to Daniel Holbert [:dholbert] from comment #14)

Maybe this is reproducible on any arbitrary network with a testcase like that^, hosted from a remote web server, which redirects to your own local router's IP address? (will test later)

Nope, just tested the HTML from comment 14 as a testcase hosted on my own web server, with my own router's IP address in redirURL, and I end up getting a request "to access apps and services on devices connected to your local network" which is the correct/expected message to show.

So, I don't yet have a way to repro the unwanted "on this device" message outside of my local library. Hopefully the screencast & profile in comment 13 are useful; I can still try to capture a pernosco trace next time I'm there (didn't have time today).

Looks like the relevant differentiator might be here:
https://searchfox.org/mozilla-central/rev/67c9592293e8d9f143e6053c8cfd6b7723207e3c/netwerk/protocol/http/nsHttpChannel.cpp#8020-8023

auto permissionKey = mTransaction->GetTargetIPAddressSpace() ==
                             nsILoadInfo::IPAddressSpace::Local
                         ? LOCAL_HOST_PERMISSION_KEY
                         : LOCAL_NETWORK_PERMISSION_KEY;

The two "PERMISSION_KEY" options there ultimately select between the two different permission-prompt flavors, here:
https://searchfox.org/mozilla-central/rev/67c9592293e8d9f143e6053c8cfd6b7723207e3c/browser/components/permissions/ContentPermissionPrompt.sys.mjs#63-67

So I might be able to learn something from just breaking at that line in gdb (when back at the library).

Working backward from there, I think the TargetIPAddressSpace member gets set here:
https://searchfox.org/mozilla-central/rev/67c9592293e8d9f143e6053c8cfd6b7723207e3c/netwerk/protocol/http/nsHttpTransaction.cpp#3678-3690

bool nsHttpTransaction::AllowedToConnectToIpAddressSpace(
    nsILoadInfo::IPAddressSpace aTargetIpAddressSpace) {
  // skip checks if LNA feature is disabled
  if (!StaticPrefs::network_lna_enabled()) {
    return true;
  }

  // store targetIpAddress space which is required later by nsHttpChannel for
  // permission prompts
  {
    mozilla::MutexAutoLock lock(mLock);
    if (mTargetIpAddressSpace == nsILoadInfo::Unknown) {
      mTargetIpAddressSpace = aTargetIpAddressSpace;

So that's probably a better spot to break in gdb.

I've got a pernosco trace processing (no link yet), but from poking at rr locally, I think (?) I may have figured this out...

tl;dr I think the issue is that we happen to classify the target IP address here, 198.18.32.1, as a "benchmarking address" -- i.e. addr->IsBenchMarkingAddress() returns true:
https://searchfox.org/mozilla-central/rev/6e2b186c296474e032d9ae2e000b7c870396775c/netwerk/dns/DNS.cpp#174-178

bool NetAddr::IsBenchMarkingAddress() const {
  // check for 198.18.0.0/15
  if (this->raw.family == AF_INET) {
    uint32_t addr = ntohl(this->inet.ip) >> 17;
    return addr == (0xC612 >> 1);

And since IsBenchMarkingAddress() returns true, that makes NetAddr::GetIpAddressSpace() treat the ip address as a local address [this seems wrong??] by returning IPAddressSpace::Local (same as if it were the loopback address), here:

https://searchfox.org/mozilla-central/rev/6e2b186c296474e032d9ae2e000b7c870396775c/netwerk/dns/DNS.cpp#240,254-256

nsILoadInfo::IPAddressSpace NetAddr::GetIpAddressSpace() const {
...
  if (addr->IsBenchMarkingAddress() || addr->IsLoopbackAddr() ||
      addr->IsIPAddrAny()) {
    return nsILoadInfo::IPAddressSpace::Local;

That value then gets passed into a !httpTrans->AllowedToConnectToIpAddressSpace( check here:
https://searchfox.org/mozilla-central/rev/6e2b186c296474e032d9ae2e000b7c870396775c/netwerk/protocol/http/nsHttpConnection.cpp#573-575
...which gets stored in mTargetIpAddressSpace, with semantics documented there:
https://searchfox.org/mozilla-central/rev/6e2b186c296474e032d9ae2e000b7c870396775c/netwerk/protocol/http/nsHttpTransaction.cpp#3694-3699
( "local" representing "local host resources")
...which ultimately results in the prompt shown for local-machine-access, despite the fact that we were in fact trying to access 198.18.32.1.

smayya: do you know why we've got this IsBenchMarkingAddress() check configured to be treated as local-access? That seems to be the problem here -- can we remove that?

Flags: needinfo?(smayya)

I see that we're explicitly testing for 192.18.*.* and 192.19.*.* being treated as "local" here:
https://searchfox.org/mozilla-central/rev/6e2b186c296474e032d9ae2e000b7c870396775c/netwerk/test/gtest/TestLocalNetworkAccess.cpp#22,41-42

(I suspect we were assuming that routers don't actually use IP addresses in that range in the wild, but it seems my library at least is evidence to the contrary.)

Summary: Firefox shows the wrong prompt when redirecting to local IP address captive-portal page, when connecting to library open-wifi hotspot (redirect blocked with `NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED`) → Firefox shows the wrong prompt when redirecting to local IP address captive-portal page, when connecting to library open-wifi hotspot with 198.18..* ip-address scheme (redirect blocked with `NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED`)

pernosco trace if it's helpful, seeked to the moment where we call IsBenchMarkingAddress:
https://pernos.co/debug/ce8xVv_ZLB1MJbL7thTKWw/index.html#f{m[CXSs,A5cE_,t[VQ,BVWl_,f{e[CXSs,A5b+_,s{aeGZ54AAA,bDSI,uAlCWog,oAlZZuw___/

(This is a stock mozilla-central build, aside from some added NS_WARNING("***dholbert [...]"); logging that I added in a few relevant spots.)

Note that since captive portal requests/pages are likely to be intercepted, we could give them the permission automatically?
We already exclude it from TRR and other checks.

smayya: do you know why we've got this IsBenchMarkingAddress() check configured to be treated as local-access? That seems to be the problem here -- can we remove that?

Thanks for the analysis Daniel! Sorry for the delay in responding.
This is as per the spec -> https://wicg.github.io/private-network-access/#ip-address-space-heading
So in this case we are behaving as per that. I understand that this can be confusing, but the idea is (I guess) that it is more "private" than the other addresses in this category. I will confirm with the spec authors again.

Flags: needinfo?(smayya) → needinfo?(dholbert)

(In reply to Valentin Gosu [:valentin] (he/him) {{ AFK in July }} from comment #21)

Note that since captive portal requests/pages are likely to be intercepted, we could give them the permission automatically?
We already exclude it from TRR and other checks.

Great idea. I think it would make sense that if we have detected captive portal to skip LNA checks. Will add it to list of enhancements.

This is a reminder regarding comment #10!

The bug is marked as tracked for firefox143 (nightly). We have limited time to fix this, the soft freeze is in 8 days. However, the bug still isn't assigned.

(In reply to Sunil Mayya from comment #23)

Great idea. I think it would make sense that if we have detected captive portal to skip LNA checks. Will add it to list of enhancements.

100% - I filed bug 1981514 on that.

(In reply to Sunil Mayya from comment #22)

This is as per the spec -> https://wicg.github.io/private-network-access/#ip-address-space-heading
So in this case we are behaving as per that. I understand that this can be confusing, but the idea is (I guess) that it is more "private" than the other addresses in this category. I will confirm with the spec authors again.

I see that this IP 192.168.18.* range is technically "reserved for benchmarking"; however I think there's a broad perception on the web that the whole 192.168.* address-block (including this sub-range) is reserved for local-network addressing (e.g. https://www.avast.com/c-ip-address-public-vs-private#:~:text=And%20don%27t%20be%20surprised,network%20routers%20around%20the%20globe. ) So my strong suspicion is that any actual Firefox user with a 192.168.18.* ip-address is almost certainly just on a network that happens to use that local network addressing scheme, rather than a user doing some networking benchmarking on their local device with that range...

Maybe this is less of an issue once we've got the captive-portal situation sorted out, but I can imagine other situations too (e.g. homeassistant and other IOT dashboards) which might be hosted at some domain name (whether homeassistant.local or a public domain-name), and might have links or embedded frames that use IP addresses on your local network - in this situation, users would probably be pleased to see a prompt to grant local-network-access but would be surprised to see an "allow this site to access services on this device" prompt...

Flags: needinfo?(dholbert)

This is a reminder regarding comment #10!

The bug is marked as tracked for firefox143 (nightly). We have limited time to fix this, the soft freeze is in 2 days. However, the bug still isn't assigned.

(In reply to Daniel Holbert [:dholbert] from comment #25)

I see that this IP 192.168.18.* range is technically "reserved for benchmarking"; however I think there's a broad perception on the web that the whole 192.168.* address-block (including this sub-range) is reserved for local-network addressing (

Whoops, sorry for conflating two different IP-address ranges -- up until just now, I was misreading this bug's 198.18.*.* address-block as if it were 192.168.18.* - given that this is a public-wifi network, my brain just autocompleted/substituted to assume that it'd use addresses inside the 192.168.* range (and was e.g. some special sub-range that had its own specially-reserved purpose). But I'm now seeing the addresses involved here are 198.18.* which are completely different, so it makes a bit more sense for them to have a special reserved purpose.

Even so: apparently folks [e.g. my library system] do (ab)use this 198.18.* ip-address-range for internal-network addressing (which is not a "local device" thing), so it's still worth thinking how to account for that somehow.)

Assigning to Sunil

Assignee: nobody → smayya
Severity: -- → S3
Priority: -- → P2
Whiteboard: [necko-triaged]

Set release status flags based on info from the regressing bug 1972350

Dan, I believe this bug is Nightly-only based on the regressing bug. Can you confirm that Beta 143 builds aren't impacted? Thanks!

Flags: needinfo?(dholbert)

That's my understanding as well. Just to be sure, I'll test beta143 on my next visit to my local library [leaving ni open].

(But absent confirmation to the contrary, I think we can safely consider this 'disabled' for 143, given my pref-toggle-testing of the relevant pref in comment 8, and given the fact that that pref is still only enabled-by-default on Nightly)

ryan, daniel, our current plan in to enable LNA for 50% of our 143 beta users. We will plan rollout experiment soon.

Flags: needinfo?(ryanvm)

(In reply to Sunil Mayya from comment #23)

(In reply to Valentin Gosu [:valentin] (he/him) {{ AFK in July }} from comment #21)

Note that since captive portal requests/pages are likely to be intercepted, we could give them the permission automatically?
We already exclude it from TRR and other checks.

Great idea. I think it would make sense that if we have detected captive portal to skip LNA checks. Will add it to list of enhancements.

Filed Bug 1984105

(In reply to Sunil Mayya from comment #33)

ryan, daniel, our current plan in to enable LNA for 50% of our 143 beta users. We will plan rollout experiment soon.

Thanks. Per slack, it sounds like we're still planning to have this off-by-default for release 143, so status-firefox143: disabled still seems accurate (for release-tracking purposes at least).

(In reply to Daniel Holbert [:dholbert] from comment #31)

Just to be sure, I'll test beta143 on my next visit to my local library [leaving ni open].

I just tested beta -- Firefox 143.0b2 (64-bit) -- with a fresh user-profile, at my local library, and the bug did not reproduce. http sites successfully redirected to the captive-portal auth page (at IP address http://198.18.32.1/) without being blocked by any sort of LNA prompt.

Flags: needinfo?(dholbert)
Flags: needinfo?(ryanvm)

Sunil, aiui there is a plan to enable LNA for Fx145. Is this on track to be fixed before Fx145 release?

As of now, for navigational loads we do not apply LNA to match Chrome's implementation, hence we shouldnt see this with nightly users as well.

This will change soon with 146 or once we decide to apply this for navigational loads.

Sunil, aiui there is a plan to enable LNA for Fx145. Is this on track to be fixed before Fx145 release?

This bug should be closed with https://bugzilla.mozilla.org/show_bug.cgi?id=1984105

Flags: needinfo?(smayya) → needinfo?(dholbert)
Flags: needinfo?(dmeehan)

Thanks, we should follow up once Bug 1984105 lands

Flags: needinfo?(dmeehan)

(In reply to Sunil Mayya from comment #38)

As of now, for navigational loads we do not apply LNA to match Chrome's implementation

(for reference, it looks like this^ behavior was added in bug 1988525)

hence we shouldnt see this with nightly users as well.

To clarify: are you saying that the STR shouldn't repro the issue anymore (for now at least), in Nightlies after bug 1988525?

(Note that the 192.18.*.* pageload here comes from a JS-initiated redirect, where the site assigns location.href, per comment 14; I don't know offhand if that's "navigational" for the purposes of bug 1988525's checks or not.)

Update: I confirmed that bug 1988525 does address this for me on Nightly (confirming first line of comment 38).

Specifically:

  • If I start Nightly 145.0a1 (2025-09-24) and visit http://example.org, I'm successfully redirected to the network's captive-portal accept-our-terms page (which is still hosted at http://198.18.32.1/ )
  • ...but I can bring force the bug to reproduce by toggling about:config pref network.lna.allow_top_level_navigation to false (intentionally reverting bug 1988525, basically) -- at that point if I try to visit example.org, then I do see the unwanted prompt (which still references "services on this device").

So: on my specific library public-wifi network, this issue is addressed/mitigated by bug 1988525.

It's probably still worth considering whether we want to continue to give 192.18.. IP-addreses special treatment, though, for the use-cases where we do show this dialog. I'll defer to Sunil on whether to spin off a followup bug on that. (not sure if we ended up getting anywhere with spec authors about this special case per comment 22)

Flags: needinfo?(dholbert)

I'm closing this as FIXED by bug 1988525 per previous comment.

Status: NEW → RESOLVED
Closed: 4 months ago
Depends on: 1988525
Resolution: --- → FIXED
Target Milestone: --- → 145 Branch

(In reply to Daniel Holbert [:dholbert] from comment #27)

Even so: apparently folks [e.g. my library system] do (ab)use this 198.18.* ip-address-range for internal-network addressing (which is not a "local device" thing), so it's still worth thinking how to account for that somehow.)

Ted Campbell just encountered another case of this (on a business's guest-Wi-Fi router, where some DNS lookups were returning IP addresses in this range and spawning LNA "local device" prompts as a result - not sure whether for captive portal reasons or other reasons)

Including Ted's full description

I'm seeing LNA prompts all over the place, including on gmail/gcal. Target urls including https://fonts.googleapis.com/css2?family=Google+Sans+Text:wght@400;500;700 and https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css?ver=1.4.4
I'm on currently on hotel Wifi that is going through British Telecom. My DNS for fonts.googleapis.com and cdnjs.cloudflare.com are resolving to 198.18.X.X :disappointed:

So there's a middlebox on the network and the DNS server is resolving these CDN domains to the internal IP of the middle box.
Apparently the certificates for the requests validate correctly, which means it's probably forwarding the TCP connection to the target domain.
So it's either doing SNI inspection, and deciding whether to block specific domains (unlikely, since it could very well be blocking at the DNS level instead?) or more likely it's acting as a caching proxy when the requests are over unencrypted http.

I think once we get some telemetry about which target domains are involved, we can exclude some of them.
Specifically, I think excluding https://fonts.googleapis.com/* and https://cdnjs.cloudflare.com/* is 0-risk - since your router or other devices don't have valid certs for these domains. But we should make sure that happens only for HTTPS, not HTTP.

(In reply to Sunil Mayya from comment #22)

This is as per the spec -> https://wicg.github.io/private-network-access/#ip-address-space-heading
So in this case we are behaving as per that. I understand that this can be confusing, but the idea is (I guess) that it is more "private" than the other addresses in this category. I will confirm with the spec authors again.

Note, it looks like this spec ("local-network-access") has replaced that one^ ("private-network-access"):
https://wicg.github.io/local-network-access/#non-public-ip-address-blocks

That spec still classifies 198.18.0.0/15 as "loopback" which is this updated spec's term that loosely refers to addresses-assumed-to-refer-to-the-local-device.

@smayya did you end up hearing back from the spec authors (and/or would you mind following up with them again)? I think they're Chromium engineers (or Chromium-adjacent) -- does Chrome actually treat 198.18.*.* specially here? (Ted explored their code a bit and didn't find anywhere where they might give this range special treatment -- he ran across https://source.chromium.org/chromium/chromium/src/+/main:services/network/public/cpp/ip_address_space_util.cc;l=246-298;drc=8e3c3db1bd3da6c8949c40f2ad673183457cdbe2 which has four IPAddressSpace::kLoopback ranges, and none of them are 198.18.*.*

Flags: needinfo?(smayya)

er sorry, I think Sunil's away for a bit.

But I see Chromium engineer titouan has an account here on bugzilla and worked on the chromium code that I linked in comment 45, based on the blame UI shown on the page there -- hi titouan! Do you know if actually Chrome treats 198.18.*.* as loopback addresses as the spec seems to say it should ?

(If not, do you know if that spec-vs-implementation difference is known, and is that gap planned to be closed in one direction or the other?)

Flags: needinfo?(smayya) → needinfo?(titouan)
See Also: → 1984105

Reopening to maybe address comment 44

Assignee: smayya → nobody
Whiteboard: [necko-triaged] → [necko-triaged][necko-priority-next]
Status: RESOLVED → REOPENED
Resolution: FIXED → ---

Hi @dholbert, it looks like we missed that address range in our implementation: https://source.chromium.org/chromium/chromium/src/+/main:services/network/public/cpp/ip_address_space_util.cc;l=260;drc=c6bec1e42f9eefac5e46f29bcca1bafef8bc8b31

Adding @cthomp@chromium.org who is now driving LNA in Chromium. We likely need to file a bug for this?

Flags: needinfo?(titouan) → needinfo?(cthomp)

Thanks for flagging! I've made a note in https://crbug.com/427437805#comment4 that we are missing this and I'll get a CL up to make us match the spec.

Flags: needinfo?(cthomp)

Regarding the notion of excluding certain target domains:

I think once we get some telemetry about which target domains are involved, we can exclude some of them.
Specifically, I think excluding https://fonts.googleapis.com/* and https://cdnjs.cloudflare.com/* is 0-risk - since your router or other devices don't have valid certs for these domains. But we should make sure that happens only for HTTPS, not HTTP.

Do we think this is sufficient to avoid making this a hole for DNS rebinding attacks?

Additionally, in the enterprise case, it's entirely possible that these resources could be served using private root certificates, and thus proxied to different or privileged local servers in a way that potentially exposes them to arbitrary requests from public sites.

(In reply to Chris Thompson from comment #49)

Thanks for flagging! I've made a note in https://crbug.com/427437805#comment4 that we are missing this and I'll get a CL up to make us match the spec.

Thanks! Do we actually want to match the spec on this, though? Or do we want to just change the spec?

I personally don't see any value from treating 198.18.*.* as "local machine/loopback" given that we have evidence that some routers treat that range like any other public IP range (assigning addresses from it).

(I think the only reason the spec gives this range special treatment is that it's technically reserved for "for use in benchmark tests of network interconnect devices" per https://datatracker.ietf.org/doc/html/rfc5735 ; but that's irrelevant to browser users when a site attempts to load a resource whose IP happens to be in this range [because a router/network-operator used this range without realizing it was reserved, or they used it because it was reserved and hence available-to-them]. And there's no reason that I see to consider that IP address as being loopback-like.)

Flags: needinfo?(cthomp)

It's definitely reserved and shouldn't be globally routable, but I don't have strong feelings on if it should be treated as loopback or local. If we see these commonly being misused for local networks that seems like reason enough, and re-reading the RFC I agree that it does not give enough specifics to restrict this CIDR to just loopback.

Longer term it is maybe better to proactively identify which addresses are actually assigned to the local machine (such as discussed in https://github.com/WICG/local-network-access/issues/14 and https://github.com/WICG/local-network-access/issues/13), which would account for cases where these addresses were used on the loopback interface.

(For local network I think we can add the user's local subnet to set of local addresses, but we can't exclusively rely on that as it doesn't sufficiently take into account more complicated network topologies.)

Flags: needinfo?(cthomp)

(In reply to Chris Thompson from comment #52)

It's definitely reserved and shouldn't be globally routable, but I don't have strong feelings on if it should be treated as loopback or local. If we see these commonly being misused for local networks that seems like reason enough, and re-reading the RFC I agree that it does not give enough specifics to restrict this CIDR to just loopback.

Thanks. Yeah, I think at-most we should classify it as Local (similar to 10.0.0.0/8), if we give it any special treatment at all. Definitely doesn't feel worthy of calling "loopback" given the usage we've observed and the RFC.

(For local network I think we can add the user's local subnet to set of local addresses, but we can't exclusively rely on that as it doesn't sufficiently take into account more complicated network topologies.)

FWIW: in both of the cases where we've encountered this address-range causing unexpected LNA dialogs, the user has been on a distinct local subnet; rather, the router is just using 198.18.*.* addresses as some sort of auxiliary reserved range for hosting internal-facing resources (a captive-portal page in one case, and as a sort of CDN in other cases).

In both of these cases, I think it'll still be (perhaps needlessly?) confusing for a LNA prompt to appear. It'll be slightly less-alarming to have the prompt refer to the local network rather than on your local device (assuming we reclassify it as local-but-not-loopback), but it's still pretty weird to see an alert saying that some well-known website is trying to access your local resources, simply because it uses https://fonts.googleapis.com/ (for example) and your router happens to do some CDN/forwarding-shenanigans for that domain as in comment 44...

I don't think we have a way to distinguish that from actual attacks/malicious network probing though, so maybe there's an argument that we should just block the requests entirely instead of triggering the permission prompt? But then we risk real breakage for situations like we've seen for Zscaler / corporate VPNs / etc. (this sounds roughly identical to usage of CG-NAT addresses we've seen).

(In reply to Chris Thompson from comment #54)

I don't think we have a way to distinguish that from actual attacks/malicious network probing though, so maybe there's an argument that we should just block the requests entirely instead of triggering the permission prompt?

Let's not block entirely... That's what Firefox did back when I filed this bug -- we blocked the request entirely -- and as a result, my local public-library system's guest-WiFi network was completely inaccessible to me until I figured out what was going wrong.

(tl;dr their captive-portal returns the same HTML file for all http requests, shown in comment 14, which says "Please wait" and attempts to redirect you to an accept-the-terms page hosted on http://198.18.32.1. So, per actual-results in comment 0: when I first encountered a problem, Firefox was blocking the redirect-to-198.18.32.1 network-request entirely, leaving me stuck at the "Please wait..." screen. Then we started prompting whether to let example.org [or whatever site you had attempted-to-load] access resources from your local device, which provided a workaround but was perplexing; and now we allow top-level navigations per bug 1988525, which fortunately bypasses the problem entirely in this specific case, but might [?} be violating the spirit of LNA, I'm not sure)

Speculating as to why network middleware devices are using this range in the first place.... I would guess it's because:
(1) they're confident it's not in use on the public internet (since it's reserved)
(2) they're reasonably confident that their customers aren't using it for their own internal network-addressing (since their customers are doing the right thing and using true internal network addresses, which could be anything in the 192.168.8.* or 10.* range, for example)
...so, this 198.18.*.* range must look temptingly guaranteeed-to-be-unused and hence "just right" to (ab)use for middleware devices/services.

From that perspective, I suppose it's reasonable to assume that 198.18.*.* is indeed a flavor of local-network-address (attached in some way to the user's intranet), just as 192.168.*.* would be. And whatever trouble we have with local-resources hosted on one range, we could just as easily have the same trouble with local-resources hosted on the other; so probably it makes sense to treat them the same and to share the same intuition for any mitigations or interventions across these local-ish IP ranges.

A bit of an aside, but seems worth expanding on this a bit, in case it helps with assessing the risks here:

we allow top-level navigations per bug 1988525, which fortunately bypasses the problem entirely in this specific case, but might [?} be violating the spirit of LNA, I'm not sure)

I think any form of trying to apply LNA to main frame navigations will necessarily take a bit different shape (e.g., some sort of navigational interstitial that can provide much more context) and at least Chrome has no current plans for pursuing it (https://wicg.github.io/local-network-access/#issue-0daaba5a). One possible approach might be to break the opener relationship for main frame local network navigations, which would address most of the type of risk we are thinking of for main frame navs (things like doing semi-silent CSRF by opening a popup window and then immediately closing it).

This address space is reserved, but seems to be used for different things in the wild.
Chrome currently has no special handling, so this pref disables treating it as a local
address space. In the future we might treat it as a private address space instead.

Assignee: nobody → valentin.gosu

firefox-beta Uplift Approval Request

  • User impact if declined: Some captive portal networks use this IP address range. If we treat it as local, users might be seeing unexpected LNA prompts that are not actionable and do not show up in Chrome.
  • Code covered by automated testing: yes
  • Fix verified in Nightly: no
  • Needs manual QE test: no
  • Steps to reproduce for manual QE testing:
  • Risk associated with taking this patch: low
  • Explanation of risk level: Just excludes this address range from triggering LNA permission prompts
  • String changes made/needed: none
  • Is Android affected?: yes
Attachment #9528960 - Flags: approval-mozilla-beta?

This address space is reserved, but seems to be used for different things in the wild.
Chrome currently has no special handling, so this pref disables treating it as a local
address space. In the future we might treat it as a private address space instead.

Original Revision: https://phabricator.services.mozilla.com/D273966

Status: REOPENED → RESOLVED
Closed: 4 months ago2 months ago
Closed: 2 months ago4 months ago
Resolution: --- → FIXED

Since nightly and release are affected, beta will likely be affected too.
For more information, please visit BugBot documentation.

(In reply to Valentin Gosu [:valentin] (he/him) from comment #47)

Reopening to maybe address comment 44

[I'm adjusting the old fixed statuses to disabled to better-reflect reality, and to avoid implying that the patch that we ended up landing here somehow landed on those older branches]

And we do probably want to uplift this to beta 146 -- setting ni=valentin as a reminder, though it's probably already on his radar. (Not sure when the last beta uplifts are accepted, but it's likely later this week, since next week beta turns into release-candidate.)

Flags: needinfo?(valentin.gosu)

(In reply to Daniel Holbert [:dholbert] from comment #65)

And we do probably want to uplift this to beta 146 -- setting ni=valentin as a reminder, though it's probably already on his radar. (Not sure when the last beta uplifts are accepted, but it's likely later this week, since next week beta turns into release-candidate.)

This already has a beta uplift request (Comment 59), I was waiting for it to land in central before uplifting.

Flags: needinfo?(valentin.gosu)
Attachment #9528960 - Flags: approval-mozilla-beta? → approval-mozilla-beta+
Target Milestone: 145 Branch → 147 Branch
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: