Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow "localhost" as long as it actually resolves to a localhost address #43

Closed
enygren opened this issue Aug 1, 2016 · 9 comments
Closed
Assignees
Milestone

Comments

@enygren
Copy link

enygren commented Aug 1, 2016

RFC 6761 does claim "Users may assume that IPv4 and IPv6 address queries for localhost names will always resolve to the respective IP loopback address." which would imply that it should be reasonable for "localhost" to be "potentially trustworthy".

Having 127/8 and ::1 but not localhost in the "potentially trustworthy" set seems to have the risk of encouraging hard-coding of breaking the name/IP abstraction boundary and hard-coding client-side addresses in to URLs on the server without knowing client capabilities. It will be unfortunate if clients need to keep around their IPv4 stack or manually rewrite 127.0.0.1 to ::1 just for these sorts of use-cases. Both rfc1900 and rfc2616 explicitly discourage using addresses. ("The use of IP addresses
in URLs SHOULD be avoided whenever possible" in rfc2616 and rfc1900 is harsher.)

It seems like a better result would be to allow "localhost" (and encourage it over hard-coding an address) as long as it resolves to either 127.0.0.0/8 or ::1 ? Security considerations should of course mention that some implementations are buggy and clients should either verify the resolution to a loopback address (or perhaps should consider hard-coding the translation?)

@mikewest mikewest added this to the CR milestone Aug 2, 2016
@mikewest mikewest self-assigned this Aug 2, 2016
@mikewest
Copy link
Member

mikewest commented Aug 2, 2016

Thanks for following up on our conversation, Erik!

RFC 6761 does claim "Users may assume that IPv4 and IPv6 address queries for localhost names will always resolve to the respective IP loopback address." which would imply that it should be reasonable for "localhost" to be "potentially trustworthy".

Based on discussions with @sleevi and @estark37, implementers are treating that "may" as a "MAY", and ignoring it in some cases. I don't know enough about the details to have an intelligent conversation about them, but I'm reliably informed that they exist.

From my perspective, I'm happy to treat localhost as a secure context if we can ensure that it always resolves to the loopback address. I think it would be confusing and bad if the origin could flip back and forth depending on the configuration of the network you've happened to connect to. (As an aside, avoiding this kind of mutation is the reason that we're not looking at the IP address we actually connect to for other kinds of DNS names. While it's totally possible for me to point mikewest.org at the loopback address, it's equally possible for me to be DNS-poisoned into such a configuration, etc.)

I'm not sure the 127.0.0.1/8 => loopback requirement is something we can reasonably make part of the requirements of this specification, though.

/cc @hillbrad @mnot for more opinions.

It will be unfortunate if clients need to keep around their IPv4 stack or manually rewrite 127.0.0.1 to ::1 just for these sorts of use-cases.

I don't understand the impact here. Do you consider it at all likely that 127.0.0.1 is going away?

@sleevi
Copy link

sleevi commented Aug 2, 2016

Users may assume it does, but application software clearly cannot :) The goal is to make sure things are actually secure, and not just assumed to be secure.

Here, the meaningful difference is the set of obligations placed on name resolution APIs for localhost, as captured in https://tools.ietf.org/html/rfc6761#section-6.3

Name resolution APIs and libraries are only at a SHOULD level, and we know very large implementations did not implement the SHOULD from item 3. As such, items 4 and 5 mean there is real security risk.

In order to treat localhost as secure, applications implementing the secure context spec MUST recognize it as special (per item 2) prior to treating it as a secure context.

In Chrome, we've experimented with that, but the end result is that it causes new bugs and issues. For example, if the application software is special recognizing it, then it means the common pattern of overriding localhost to NOT resolve to loop back (e.g. Via /etc/hosts) no longer works. While we could argue that is a violation of the RFC, it's an RFC, not a cop, so it doesn't really prevent that.

Hence the pragmatic decision to not mandate that every browser special recognize and special case localhost, at least for the time being.

In effect, the weak language of the RFC makes it unreliable from a security standpoint, hence the decision to fail closed.

@mikewest
Copy link
Member

mikewest commented Aug 2, 2016

I agree with @sleevi about the status quo; as the world is today, I think the spec makes sense. That said:

In Chrome, we've experimented with that, but the end result is that it causes new bugs and issues. For example, if the application software is special recognizing it, then it means the common pattern of overriding localhost to NOT resolve to loop back (e.g. Via /etc/hosts) no longer works.

How common is this "common pattern"? Like, how sad would the world become if we broke it? I, for one, would not be sad if we could more closely align the things that users may assume with the way that software does behave. I continue to be surprised that localhost can resolve to anything other than loopback, and my impression is that I'm not the only one. Surprising users is bad, so maybe let's stop doing it?

If it would be helpful to write a tiny ID that says "Hey, don't do that thing we said you shouldn't do!", I can do that (but it sounds like the formal definitions aren't actually the problem).

@sleevi
Copy link

sleevi commented Aug 2, 2016

@mikewest
They could equally point foo.localhost to 127.0.0.1 and bar.localhost to 127.0.0.2, which would keep both on loopback, but be a meaningfully different configuration.

I don't have strong feelings regarding this, should there be consensus that it's the right thing to do, but it certainly feels like it breaks the name/IP abstraction that @enygren was concerned about, as it adds to the growing since of logic that must move from name resolution libraries and into applications. It's not unreasonable, it just sits weird...

@mikewest
Copy link
Member

mikewest commented Aug 4, 2016

They could equally point foo.localhost to 127.0.0.1 and bar.localhost to 127.0.0.2, which would keep both on loopback, but be a meaningfully different configuration.

How about "MUST NOT resolve localhost names to a non-loopback address"?

I don't have strong feelings regarding this, should there be consensus that it's the right thing to do, but it certainly feels like it breaks the name/IP abstraction that @enygren was concerned about, as it adds to the growing since of logic that must move from name resolution libraries and into applications. It's not unreasonable, it just sits weird...

I guess I'm less concerned about the layering, and more concerned about the surprising result. shrug

@jungkees
Copy link

TPAC note: the spec is in CR, and I'd want Service Worker folks to check out whether we have any concern or suggestion around this issue.

/cc @jakearchibald @slightlyoff @mkruisselbrink @annevk @wanderview @aliams

@mikewest
Copy link
Member

Ok. @sleevi, @enygren: please tear https://tools.ietf.org/html/draft-west-let-localhost-be-localhost apart in the interests of making it sane.

@mikewest
Copy link
Member

I this this has been resolved: https://w3c.github.io/webappsec-secure-contexts/#localhost says that localhost MAY be considered totally awesome iff folks promise to resolve it to a loopback address as per the IETF draft noted above.

@equalsJeffH
Copy link

fyi/fwiw, IETF draft noted above is now: https://tools.ietf.org/html/draft-ietf-dnsop-let-localhost-be-localhost

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

No branches or pull requests

5 participants