Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

New Content Policy API

204 views
Skip to first unread message

Jonas Sicking

unread,
Sep 16, 2011, 5:14:51 PM9/16/11
to dev-platform
Hi All,

We had a impromptu meeting today discussing what a new Content Policy
API would look like. We have for a long time been suffering from an
API which provides very little convenience for code needing to do
security checks before opening a network connection, while also
providing very little support for people implementing the Content
Policy API in order to block certain network loads.

Additionally the existing API works very poorly in e10s since it's
fully synchronous and uses XPCOM component registration.

So below is what we are thinking. There's not a lot of detail yet,
more higher-level ideas. Please do ask questions if you have concerns
or ideas!

Here's how things would work from the point of view of someone
implementing a content policy:

First off, we want to use normal (but chrome-only) DOM events to
deliver the notifications. This works better with e10s as have been
discussed at [1]. Each content policy would then register to be an
event handler for this event.

When the event fires, a event handler can either do nothing if it
wants to let the load proceed as normal, or it can call a function on
the Event indicating that the load should be blocked. There should
also be a function to indicate "I don't have an answer yet, but I'll
call you back asynchronously to let you know my answer". We won't
start any network traffic until everyone that requested to reply
asynchronously has responded.

As a performance saving measure we can make the call to synchronously
block the load also call Event.stopImmediatePropagation, which would
prevent more of the content-policy-event-handlers from getting called.

When the event fires, we make the following information available:
* Load type. I.e. stylesheet, document, XHR, etc. [2] is the list of
types that we currently have
* URI. The uri we're about to load
* Node. The note initiating the load. In some cases when we can't
figure out the exact node it'll be the document where the load
happens.
* Channel. The channel we're about to start loading.

A big change here is that we provide the channel. This will make it
much easier to track a single load through the rest of necko. Another
thing to note is that since we provide a reference to the node the
event has to be fired in the e10s content process. This shouldn't be
too hard to deal with for addons though as we have good mechanisms for
registering event handlers in all e10s content processes as detailed
in [1]. The principal of the loader will be trivially accessible from
the Node.

If a redirect occurs we'll again fire an event looking exactly like
the first event which provides the same data and additionally the old
channel and old URI. This makes handling redirects *a lot* easier
compared to how things work today. Again the
content-policy-event-handler has the ability to respond synchronously
or asynchronously and we won't hit the network for the new URI until
everyone has responded.

We'll also provide a explicit API on the event to allow a content
policy to redirect a load to a new URI. When that happens we'll treat
this like a "normal" redirect and fire a new event on all content
policy just like for a http redirect. If multiple policies want to
redirect to different URIs we'll have to handle that somehow.

Once we have downloaded enough of the resource that we have things
like header data we fire a second, in place of the current
nsIContentPolicy.shouldProcess callback. Again content policies will
have the ability to respond synchronously or asynchronously. Not until
we have responses from all event handlers will we hand the result of
the network request to the client.


For someone wanting to call into the content policy API before
starting a network load here's what things would look like:

First the caller creates a channel for the load. The caller then calls
into the content policy API and provide the load type, the loading
node and the channel (the URI can be derived from the channel) and
flags. The flags are for things like:

* Do same-origin check
* Is data: considered same-origin
* Are loads from chrome: allowed
* Other checkloaduri flags [3]

The API takes care of doing the same-origin check if requested,
including on redirects. It also performs the CheckLoadURI check
according to flags. If those checks pass it'll notify the content
policy implementations by firing the above described event. Once all
the checks have passed, which could happen asynchronously, it'll fire
off the network load.

Even if the API doesn't synchronously know if it's safe to hit the
network it'll still have to call AsyncOpen on the channel
synchronously. Or at least it'll have make the channel act as if
AsyncOpen had been called. This is important as to allow the channel
to be canceled and to prevent SetRequestHeader and similar APIs from
being called.

Another important aspect is that the API has to fire the event off of
a scriptrunner. This to ensure that content-policy-event-handlers
doesn't take any actions that we're not prepared for due to being in
an inconsistent state.

Once we get the OnStartRequest notification from necko we'll fire the
second event. While waiting for the response to this event (which
could come asynchronously) we'll have to pause the channel to prevent
OnDataAvailable calls from coming in. We also don't call
OnStartRequest on the streamlistener.


Questions:
Is the above list of information enough to provide to the content
policy consumers? I.e. is channel, node, uri and load type enough? We
currently have some additional properties, but they seem mostly
useless. The reason we want to drop them is to have to carry around
less information in case a redirect happens.

Is the current list of load types that we have good? This is pretty
orthogonal to the other changes proposed here, but since we're
changing the API in backwards incompatible ways anyway, we have a good
opportunity to make improvements.

[1] http://groups.google.com/group/mozilla.dev.platform/browse_thread/thread/a0030ea69fa5fa1a/371558655716c965
[2] http://mxr.mozilla.org/mozilla-central/source/content/base/public/nsIContentPolicy.idl#57
[3] http://mxr.mozilla.org/mozilla-central/source/caps/idl/nsIScriptSecurityManager.idl#69

/ Jonas

Jorge Villalobos

unread,
Sep 16, 2011, 6:54:12 PM9/16/11
to Jonas Sicking, dev-platform
A couple of notes:

1) It is unclear to me how registration would look for consumers (would
it be a service you register to, would you need to implement an
interface, etc.). I guess that is still undefined.

2) Several add-on have a need to block a page load (for various reasons)
and display their UI instead. Since this new Content Policy API will
support redirects, it would be nice that it is also possible to redirect
to a chrome:, resource: or file: URL.

3) Remember the addon-compat flag! :)

- Jorge

Jorge Villalobos

unread,
Sep 16, 2011, 6:54:12 PM9/16/11
to Jonas Sicking, dev-platform
On 9/16/11 2:14 PM, Jonas Sicking wrote:

Jonas Sicking

unread,
Sep 16, 2011, 7:06:44 PM9/16/11
to Jorge Villalobos, Benjamin Smedberg, dev-platform
I'm not sure if this mechanism exists yet or not. I thought it did
though I could be wrong. The intent is that it'll use the same event
registration mechanism that we have for many types of events in e10s
as defined by [1] above.

> 2) Several add-on have a need to block a page load (for various reasons) and
> display their UI instead. Since this new Content Policy API will support
> redirects, it would be nice that it is also possible to redirect to a
> chrome:, resource: or file: URL.

That should be doable. Though don't we already have mechanisms for
intercepting page navigation?

> 3) Remember the addon-compat flag! :)

Indeed :)

/ Jonas

Benjamin Smedberg

unread,
Sep 16, 2011, 7:14:35 PM9/16/11
to dev-platform
On 9/16/11 3:54 PM, Jorge Villalobos wrote:
>
> 1) It is unclear to me how registration would look for consumers
> (would it be a service you register to, would you need to implement an
> interface, etc.). I guess that is still undefined.
It's just an event listener that you'd register like any other using
.addEventListener, hopefully in a content script.

We'll also have a "global event target" to aid with some internal
implementation, but I'm not sure that extensions will need to deal with
this at all.

--BDS

Jorge Villalobos

unread,
Sep 17, 2011, 3:37:53 AM9/17/11
to Benjamin Smedberg, dev-platform
Well, I think this is a pretty big deal. Content Policy is one of the
few APIs where you can try to intercept everything, or close to
everything, without having to track open windows and open tabs. Having a
global listener is critical for filtering add-ons like ABP, NoScript,
children protection filters, and others.

- Jorge

Jorge Villalobos

unread,
Sep 17, 2011, 3:37:53 AM9/17/11
to Benjamin Smedberg, dev-platform
On 9/16/11 4:14 PM, Benjamin Smedberg wrote:

Giorgio Maone

unread,
Sep 17, 2011, 10:24:16 AM9/17/11
to
On Sep 16, 11:14 pm, Jonas Sicking <jo...@sicking.cc> wrote:

> Is the above list of information enough to provide to the content
> policy consumers? I.e. is channel, node, uri and load type enough?

aMimeTypeGuess is currently used by NoScript to tentatively honor
user's preferences about, for instance, allowing Silverlight but
forbidding Java and Flash before hitting the network.

> Is the current list of load types that we have good?

I've found myself in need to discriminate CSS from XSLT, both reported
under the "STYLESHEET" umbrella.

While we're here and we're designing this API to be called both before
any network activity starts and after headers are available but no
data has been consumed yet, can we have an intermediate step when the
actual IP of the endpoint we're about to connect to is known but no
data has been sent yet (i.e. DNS resolution already happened, or we're
using the DNS cache or we're recycling a TCP connection)?

This would be very helpful in making decision depending on the network
topology, e.g. to implement defenses against cross-zone CSRF and DNS
rebinding attacks, and I had to invent infamous hacks to accomplish
this in NoScript within the current API limitations.

Jonas Sicking

unread,
Sep 17, 2011, 4:36:26 PM9/17/11
to Giorgio Maone, dev-pl...@lists.mozilla.org
On Sat, Sep 17, 2011 at 7:24 AM, Giorgio Maone <giorgi...@gmail.com> wrote:
> On Sep 16, 11:14 pm, Jonas Sicking <jo...@sicking.cc> wrote:
>
>> Is the above list of information enough to provide to the content
>> policy consumers? I.e. is channel, node, uri and load type enough?
>
> aMimeTypeGuess is currently used by NoScript to tentatively honor
> user's preferences about, for instance, allowing Silverlight but
> forbidding Java and Flash before hitting the network.

Can't you get that information by looking at the Node?

>  > Is the current list of load types that we have good?
>
> I've found myself in need to discriminate CSS from XSLT, both reported
> under the "STYLESHEET" umbrella.

Cool, that we can do.

> While we're here and we're designing this API to be called both before
> any network activity starts and after headers are available but no
> data has been consumed yet, can we have an intermediate step when the
> actual IP of the endpoint we're about to connect to is known but no
> data has been sent yet (i.e. DNS resolution already happened, or we're
> using the DNS cache or we're recycling a TCP connection)?
>
> This would be very helpful in making decision depending on the network
> topology, e.g. to implement defenses against cross-zone CSRF and DNS
> rebinding attacks, and I had to invent infamous hacks to accomplish
> this in NoScript within the current API limitations.

It was my hope that this would be significantly easier to get at this
information from necko since we now make the channel available?

/ Jonas

Giorgio Maone

unread,
Sep 17, 2011, 6:21:43 PM9/17/11
to
On Sat, Sep 17, 2011 at 10:36 PM, Jonas Sicking <jo...@sicking.cc>
wrote:

> On Sat, Sep 17, 2011 at 7:24 AM, Giorgio Maone <giorgi...@gmail.com>
> wrote:
>
> > aMimeTypeGuess is currently used by NoScript to tentatively honor
> > user's preferences about, for instance, allowing Silverlight but
> > forbidding Java and Flash before hitting the network.
>
> Can't you get that information by looking at the Node?

It's certainly possible (I guess is what the current API does behind
the
scenes), but not always trivial, including a mix of looking at the
element
name (<applet> vs <object> vs <embed> or even <iframe>/<frame>), at
the
"type" attribute (, at the src file name?) and even possibly at
<parameter>
children. I'd definitely prefer the browser to keep guessing as it did
before, if not else to keep compatibility with current userbase's
expectations.


>> an intermediate step when the
> > actual IP of the endpoint we're about to connect to is known but no
> > data has been sent yet (i.e. DNS resolution already happened, or we're
> > using the DNS cache or we're recycling a TCP connection)?
> >
> > This would be very helpful in making decision depending on the network
> > topology, e.g. to implement defenses against cross-zone CSRF and DNS
> > rebinding attacks, and I had to invent infamous hacks to accomplish
> > this in NoScript within the current API limitations.
>
> It was my hope that this would be significantly easier to get at this
> information from necko since we now make the channel available?

It's obviously easier as a matter of accessors, since as of Gecko 5
nsIHttpChannelInternal exposes a remoteAddress property, but it's
practically impossible as a matter of timing: beside current
implementation
bugs (e.g. https://bugzilla.mozilla.org/show_bug.cgi?id=526207#c44)
which
make even monitoring unreliable, effective vetoing would require this
information to be available before any data is sent out and allow a
cancel()
call to actually abort the request. There's currently no callback at
all
which can guarantee this (mainly because TCP activity happens in a
thread
different than the UI/JavaScript one). Hence my request for this API
to
include such a callback.

Giorgio Maone

unread,
Sep 17, 2011, 4:54:18 PM9/17/11
to Jonas Sicking, dev-pl...@lists.mozilla.org
On Sat, Sep 17, 2011 at 10:36 PM, Jonas Sicking <jo...@sicking.cc> wrote:

> On Sat, Sep 17, 2011 at 7:24 AM, Giorgio Maone <giorgi...@gmail.com>
> wrote:
>
> > aMimeTypeGuess is currently used by NoScript to tentatively honor
> > user's preferences about, for instance, allowing Silverlight but
> > forbidding Java and Flash before hitting the network.
>
> Can't you get that information by looking at the Node?
>
>
It's certainly possible (I guess is what the current API does behind the
scenes), but not always trivial, including a mix of looking at the element
name (<applet> vs <object> vs <embed> or even <iframe>/<frame>), at the
"type" attribute (, at the src file name?) and even possibly at <parameter>
children. I'd definitely prefer the browser to keep guessing as it did
before, if not else to keep compatibility with current userbase's
expectations.


> an intermediate step when the
> > actual IP of the endpoint we're about to connect to is known but no
> > data has been sent yet (i.e. DNS resolution already happened, or we're
> > using the DNS cache or we're recycling a TCP connection)?
> >
> > This would be very helpful in making decision depending on the network
> > topology, e.g. to implement defenses against cross-zone CSRF and DNS
> > rebinding attacks, and I had to invent infamous hacks to accomplish
> > this in NoScript within the current API limitations.
>

Boris Zbarsky

unread,
Sep 18, 2011, 9:20:39 PM9/18/11
to
On 9/17/11 10:24 AM, Giorgio Maone wrote:
> While we're here and we're designing this API to be called both before
> any network activity starts and after headers are available but no
> data has been consumed yet, can we have an intermediate step when the
> actual IP of the endpoint we're about to connect to is known but no
> data has been sent yet (i.e. DNS resolution already happened, or we're
> using the DNS cache or we're recycling a TCP connection)?

That would require some significant necko changes; it's almost certainly
out of the scope of the work we're taking on here.

It would be good to add such hooks to necko, of course, and once they
exist we can surface them to extensions, but that can be an additive
change later and I don't think it should block the initial API change
here....

-Boris

Patrick McManus

unread,
Sep 19, 2011, 9:33:13 AM9/19/11
to Boris Zbarsky, dev-pl...@lists.mozilla.org
Aye, but add a necko feature-bug (and cc: me) that describes just what
the useful points would be.. There is likely to be some churn in those
areas anyhow, so if the stars align we can make this easier.



Zack Weinberg

unread,
Sep 19, 2011, 12:58:56 PM9/19/11
to
Please cc: me on this bug too, it is highly relevant to stuff I plan to
be working on in the near future.

zw

ywla...@gmail.com

unread,
Feb 25, 2014, 8:14:45 PM2/25/14
to
Jonas Sicking於 2011年9月17日星期六UTC+8上午5時14分51秒寫道:

ywla...@gmail.com

unread,
Feb 25, 2014, 8:15:02 PM2/25/14
to
Jonas Sicking於 2011年9月17日星期六UTC+8上午5時14分51秒寫道:
0 new messages