Open Bug 1247529 Opened 8 years ago Updated 2 years ago

Exception (NS_ERROR_FAILURE) [nsIPrincipal.origin] in SessionStorage.jsm when loading URI

Categories

(Firefox :: Session Restore, defect)

42 Branch
defect

Tracking

()

People

(Reporter: bugzilla.mozilla.org, Unassigned)

References

Details

(Keywords: regression)

Attachments

(1 file)

When navigating a site with a custom authority-less URI scheme, created by an addon I'm working on, I'm seeing the following exception in the browser console:

NS_ERROR_FAILURE: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIPrincipal.origin] SessionStorage.jsm:77:0

It seems like the principal.origin getter does not handle authority-less uris well.
Any testcase with a minimal add-on?
Stripping down the addon would be a bit of an effort, maybe the current development snapshot will do.

1. install attached XPI
2. go to addons -> ipfs gateway redirect -> options
3. enable the following option: "display fs:/ URIs as-is instead of rewriting to http://"
4. open the following URI: fs:/ipfs/QmTAsnXoWmLZQEpvyZscrReFzqxP3pvULfGVgpJuayrp1w

This should load an image and log the exception in the browser console
I forgot: also turn off e10s. That particular part is not yet tested with e10s on.
I tested with FF47, this URI fs:/ipfs/QmTAsnXoWmLZQEpvyZscrReFzqxP3pvULfGVgpJuayrp1w doesn't load any image, I get the error message in the tab:
"Unable to connect
Firefox can't establish a connection to the server at 127.0.0.1:8080."

is it normal?
Ah, sorry, you also have to disable the "Use custom gateway" option in the addon settings.
I tested with Nightly, I don't see anymore this error message, so it has been already fixed somewhere in next versions. Could you test with FF47?
I tested with

Name 	Firefox
Version 	47.0a1
Build ID 	20160210071115

the message still occurs there

are you sure you looked at the *browser console*, not the *web console*?
Ah sorry, I forgot to check "display fs:/ URIs as-is instead of rewriting to http://" in my Nightly profile. :)
Regression range:
https://hg.mozilla.org/integration/mozilla-inbound/pushloghtml?fromchange=443582420f2c6643112ebe3869c75294478c3f0b&tochange=fb346b9b9f9878df57fef570612ef043c7d2ba4e

Suspected:
Michael Layzell — Bug 1172080 - Part 2: Use ^ instead of ! to delimit originAttributes from the URI in nsIPrincipal.origin, r=bholley
Michael Layzell — Bug 1172080 - Part 1: Throw when requesting origin for poorly behaved URIs, r=bholley
Blocks: 1172080
Status: UNCONFIRMED → NEW
Ever confirmed: true
Flags: needinfo?(michael)
Keywords: regression
OS: Unspecified → All
Hardware: Unspecified → All
Summary: Exception in SessionStorage.jsm:77:0 → Exception (NS_ERROR_FAILURE) [nsIPrincipal.origin] in SessionStorage.jsm when loding URI
Version: Trunk → 42 Branch
Summary: Exception (NS_ERROR_FAILURE) [nsIPrincipal.origin] in SessionStorage.jsm when loding URI → Exception (NS_ERROR_FAILURE) [nsIPrincipal.origin] in SessionStorage.jsm when loading URI
This was intentional, for the reasons described in the bug.

nsIPrincipal is all about authority, and so generating one from an authority-less URI is kinda nonsensical and weakens our security invariants. Specifically, the idea is that a.origin == b.origin if and only if a.equals(b). There's no way to make this work for weird URI schemes, so we prevent .origin from returning anything at all.
(In reply to Bobby Holley (busy) from comment #10)
> This was intentional, for the reasons described in the bug.
> 
> nsIPrincipal is all about authority, and so generating one from an
> authority-less URI is kinda nonsensical and weakens our security invariants.
> Specifically, the idea is that a.origin == b.origin if and only if
> a.equals(b). There's no way to make this work for weird URI schemes, so we
> prevent .origin from returning anything at all.

bholley said it better than I would have ^.^. That being said, I think this is still a bug: that SessionStorage.jsm isn't written defensively in such a way that it handles nsIPrincipal.origin being unavailable, rather than in nsIPrincipal.origin not being present.
Flags: needinfo?(michael)
(In reply to Michael Layzell [:mystor] from comment #11)
> (In reply to Bobby Holley (busy) from comment #10)
> > This was intentional, for the reasons described in the bug.
> > 
> > nsIPrincipal is all about authority, and so generating one from an
> > authority-less URI is kinda nonsensical and weakens our security invariants.
> > Specifically, the idea is that a.origin == b.origin if and only if
> > a.equals(b). There's no way to make this work for weird URI schemes, so we
> > prevent .origin from returning anything at all.
> 
> bholley said it better than I would have ^.^. That being said, I think this
> is still a bug: that SessionStorage.jsm isn't written defensively in such a
> way that it handles nsIPrincipal.origin being unavailable, rather than in
> nsIPrincipal.origin not being present.

Oh yeah, I missed that part. Yeah Michael, can you include this in your SessionStorage.jsm fix?
Flags: needinfo?(michael)
(In reply to Bobby Holley (busy) from comment #10)
> This was intentional, for the reasons described in the bug.
> 
> nsIPrincipal is all about authority, and so generating one from an
> authority-less URI is kinda nonsensical and weakens our security invariants.
> Specifically, the idea is that a.origin == b.origin if and only if
> a.equals(b). There's no way to make this work for weird URI schemes, so we
> prevent .origin from returning anything at all.

Is there a way for addons to provide an origin when it cannot be derived from the verbatim uri? Chrome supports sub-origins which are derived from CSP headers, i.e. which are not part of the page uri itself.
(In reply to The 8472 from comment #13)
> (In reply to Bobby Holley (busy) from comment #10)
> > This was intentional, for the reasons described in the bug.
> > 
> > nsIPrincipal is all about authority, and so generating one from an
> > authority-less URI is kinda nonsensical and weakens our security invariants.
> > Specifically, the idea is that a.origin == b.origin if and only if
> > a.equals(b). There's no way to make this work for weird URI schemes, so we
> > prevent .origin from returning anything at all.
> 
> Is there a way for addons to provide an origin when it cannot be derived
> from the verbatim uri? Chrome supports sub-origins which are derived from
> CSP headers, i.e. which are not part of the page uri itself.

From raw XPCOM, origins are represented as nsIPrincipals, which have non-codebase variants (like nonce principals).

I don't know about WebExtensions. If chrome supports them, presumably they're part of the API, and we should (and maybe do) support them too.
(In reply to Bobby Holley (busy) from comment #14)
> (In reply to The 8472 from comment #13)
> > Is there a way for addons to provide an origin when it cannot be derived
> > from the verbatim uri? Chrome supports sub-origins which are derived from
> > CSP headers, i.e. which are not part of the page uri itself.
> 
> From raw XPCOM, origins are represented as nsIPrincipals, which have
> non-codebase variants (like nonce principals).

If that's an answer to my question I do not understand it.

My use-case is an authority-less uri scheme implemented through a nsIProtocolHandler and simple-uri instances. Through external means a synthetic origin (a unique ID) could be determined for (some) individual URIs. What I don't know how to do the uri -> principal-with-origin resolution for firefox, or whether it's possible at all.
(In reply to The 8472 from comment #15)
> (In reply to Bobby Holley (busy) from comment #14)
> > (In reply to The 8472 from comment #13)
> > > Is there a way for addons to provide an origin when it cannot be derived
> > > from the verbatim uri? Chrome supports sub-origins which are derived from
> > > CSP headers, i.e. which are not part of the page uri itself.
> > 
> > From raw XPCOM, origins are represented as nsIPrincipals, which have
> > non-codebase variants (like nonce principals).
> 
> If that's an answer to my question I do not understand it.
> 
> My use-case is an authority-less uri scheme implemented through a
> nsIProtocolHandler and simple-uri instances. Through external means a
> synthetic origin (a unique ID) could be determined for (some) individual
> URIs. What I don't know how to do the uri -> principal-with-origin
> resolution for firefox, or whether it's possible at all.

You could implement nsIURIWithPrincipal for your URI. The implementation of that could map between your URIs and a set of NullPrincipals (nonce origins), that you maintain by whatever means you like.

Note that these APIs aren't guaranteed to stay stable.
Thanks, I think that should cover most use-cases in the future, right now it's operating origin-less anyway (hence this bug).
Attempting to implement nsIURIWithPrincipal in javascript actually leads to the content process crashing in http://hg.mozilla.org/mozilla-central/annotate/918df3a0bc1c/ipc/glue/URIUtils.cpp#l47

The referenced nsIIPCSerializableURI type seems to have an IID that's not available in Components.interfaces, so can't be implemented in JS.

Am I missing something?
This generally sounds to me more like an incompatibility between JS-implemented URIs and IPC, rather than being related to the nsIURIWithPrincipal thing.

I'm not the expert here, but I've heard from various corners that we're trying to eliminate JS-implemented nsIURI implementations entirely, so you may not get a lot of traction making this work cross-process.

Sicking can confirm.
Flags: needinfo?(michael) → needinfo?(jonas)
Hrm, so it would have to be one of the existing implementations. From what I can tell nsHostObjectURI already derives from simple-uri and also implements nsIURIWithPrincipal. So it's pretty much what I would need. 

But I don't see a way to create it with a principal or set the principal after creation.
(In reply to Michael Layzell [:mystor] from comment #11)
> bholley said it better than I would have ^.^. That being said, I think this
> is still a bug: that SessionStorage.jsm isn't written defensively in such a
> way that it handles nsIPrincipal.origin being unavailable, rather than in
> nsIPrincipal.origin not being present.

Some additional exceptions i've found while attempting to get custom origins to work:

> NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS: [JavaScript Error: "can't access dead object" {file: "resource://app/modules/sessionstore/SessionHistory.jsm" line: 114}]'[JavaScript Error: "can't access dead object" {file: "resource://app/modules/sessionstore/SessionHistory.jsm" line: 114}]' when calling method: [nsIURI::spec] SessionHistory.jsm:114:0
> NS_ERROR_FAILURE: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIURI.host] autocomplete.xml:1903:0
> NS_ERROR_FAILURE: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIURI.host] SessionCookies.jsm:198:0
filed bug 1252204 for the e10s issue.
Regarding the specific issue raised in comment 19, yes, I'm trying to get to the point when addons don't implement their own nsIURIs. The reason for that is that it makes it dramatically harder to write multithreaded code.

That said, it currently should be possible to implement nsIURI from JS. As far as I know at least. But long term I'm hoping to instead make it possible for addons to simply use one of the existing nsIURI implementations.


Let me know if you have any other questions.
Flags: needinfo?(jonas)
I'm also hoping to deprecate nsIURIWithPrincipal. It's no longer needed since blob: URIs actually include the origin in the URI. So it should be possible to deduce the origin directly from the URI spec (i.e. from the URI string).
In this case the origin can indeed be extracted from the URI string, even with a simple regex. It just wouldn't be the host part.
But you also say addons shouldn't implement custom URIs.

Then my question is how would one create an URI where the origin is "deduced from the URI spec", but not the host, without also implementing nsIURI? Similar to blob URIs basically.
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: