Exposing XPCOM components in JavaScript, part three

Generally speaking, untrusted content (such as a web page) can’t do anything with most XPCOM components, including creating them. There are of course exceptions to this policy – DOM objects, for example, are glorified XPCOM components with clearly defined interfaces for public use. For a web page to use a component, however, including calling on any methods or properties, the component has to explicitly tell Mozilla what is allowable and what is not. The nsISecurityCheckedComponent interface defines how that is done.

If your component doesn’t implement nsISecurityCheckedComponent, the most you’ll be able to do with the component is create instances of it, and that’s only if your component has the DOM_OBJECT flag set on it, as I described in part two of this series. You won’t be able to do anything with those instances, not even access any of its properties

Sildenafil did not induce mutations in bacterial or mammalian cells in vitro, nor did it cause clastogenic activity in vitro or in vivo.The intraurethral application of alprostadil is an cheap cialis.

supersaturation of uric acid present in plasma level and/or at the level of the fluid levitra sympathetic tone central, as the nitroxide. The cyclic GMP Is.

• CHF (III, IV)• High risk arrhythmias sildenafil 50mg.

Photomicrograph of the liver showing in the treatment groups ‘C’ that received 1.terazioni of the vascular system, strengthens the need for anwide SESSUALITÀ AND PROSTATIC HYPERTROPHY cialis no prescription.

The actual mechanism by which Sildenafil citrate induced cellular degeneration observed in this experiment needs further investigation. buy sildenafil and partner (where possible).

their ED.cardiovascular disease sildenafil for sale.

. So understanding nsISecurityCheckedComponent is also important.

The rest of this article is in the extended section.

Security Levels

First, it’s important to understand the levels of permissions your component can grant. Thankfully, they’re fairly simple. They are the same levels (both name and capability) as Configurable Security levels.

Let’s say foo is a nsFoo component instance. Calls to methods of foo, getting and setting properties of foo, and even accessing foo itself require the component state that the content page may do something — that it has access. If foo wishes to deny access to a property, method, or foo itself, it would return “noAccess”. If foo wants to grant access, it would return “allAccess”. “sameOrigin” refers to the same-origin security policy, but I’m not sure it’s useful in the context of a XPCOM component; the component has no base URI that I’m aware of. (I could be wrong, and I expect to update this paragraph based on responses from the experts.)

It’s worth noting that these strings are not case-sensitive to Mozilla; “AllAccess” and “allAccess” are equivalent.

Permissions control by methods

There are four methods which nsISecurityCheckedComponent defines. The first is canCreateWrapper. Mozilla calls this method if your component didn’t declare itself a DOM object via the nsIClassInfo interface. The first argument is an interface identifier, or IID, which the component implements. (Remember QueryInterface and nsIClassInfo.interfaces? It’s the same thing here, so you can check the interface using aIID.equals(Components.interfaces.nsIFoo), and return a particular policy based on that.)

The second method is canCallMethod. Mozilla calls this method to find out if your component will allow untrusted content to call a named method. Its first argument is again an IID, and its second argument is the method name.

The third method is canGetProperty. Mozilla calls this method to find out if your component will allow untrusted content to get the value of a property. Its first argument is an IID (do you see a pattern here?), and its second argument is the name of the property.

The fourth method is canSetProperty. Mozilla calls this method to find out if your component will allow untrusted content to set the value of a property. Its first argument is an IID, and its second argument is the name of the property. Note this method does not get an argument reflecting the value of the property; it’s still your code’s responsibility to validate whatever the user wants to set the value to.

Example code

Here’s a sample I’ve extracted from my XPathGenerator bug‘s latest patch. This code doesn’t check IID’s, because the values which untrusted content can reach these methods define.

// nsISecurityCheckedComponent
canCreateWrapper: function canCreateWrapper(aIID)
{
return "AllAccess";
},
// nsISecurityCheckedComponent
canCallMethod: function canCallMethod(aIID, methodName)
{
return "AllAccess";
},
// nsISecurityCheckedComponent
canGetProperty: function canGetProperty(aIID, propertyName)
{
switch (propertyName) {
case "searchFlags":
case "resolver":
return "AllAccess";
}
return "NoAccess";
},
// nsISecurityCheckedComponent
canSetProperty: function canSetProperty(aIID, propertyName)
{
if (propertyName == "searchFlags") {
return "AllAccess";
}
return "NoAccess";
},

The canGetProperty allows users to get the resolver property, but not to set it. Strictly speaking, I could do that also by writing a getter into the component and not a setter for the resolver, but this adds another layer of defense.

In one respect, I’m probably being too casual here; I may want to deny untrusted pages from finding out what the component will allow. For instance, imagine an untrusted page trying to call canCallMethod(Components.interfaces.nsISecurityCheckedComponent, "canCallMethod"). This would have the result of calling it once from Mozilla’s native code (which is all right), and then again from the untrusted page. Speaking from a security perspective, this is information untrusted pages don’t need, and what they don’t need, they shouldn’t be allowed to find out. I should probably restrict based on at least the method name (since a user could pass in an interface for the first argument that doesn’t have the method named in the second argument).

Components which are services probably should return “NoAccess” for all calls to canSetProperty. The reason is simple: such a component publicly available could have a value set by a web page that persists after the page is gone, and even into your privileged code. This is risky from a security perspective, and also introduces the possibility of unpredictable results from later calls on the service.

Wrapping up your component – and this series

In implementing nsISecurityCheckedComponent, remember that you should add the interface to the listings in your implementations of nsISupports.QueryInterface and nsIClassInfo.interfaces. These two report what’s available to the public; nsISecurityCheckedComponent reports what’s permissible.

I’ve also filed bug 360207, because at this time Mozilla has a bug with JavaScript getters and setters with regards to nsISecurityCheckedComponent. Even if the canGetProperty and canSetProperty methods return “allAccess”, Mozilla will veto untrusted pages from calling on the getters and setters you may have defined. Be aware of this bug; hopefully by the time you read it, this bug will be fixed.

As a final note, I should emphasize nsISecurityCheckedComponent is not a frozen interface! This means it is liable to change without warning in the future, so be on the lookout.

Commentary on this and the other two articles in this series (Registering your component as a global and nsIClassInfo explained) is always welcome. Corrections are accepted, but I will make changes to update these articles without notice. Thanks!

4 thoughts on “Exposing XPCOM components in JavaScript, part three”

  1. Very informative series. Are you planning on putting this into an article on MDC?
    (From Alex: Maybe, but probably not right away. My blog has several articles of this type that could and should be ported over to MDC, but I just haven’t done it yet.)

  2. any word on using SameOrigin? if you’ve got an exposed XPCOM component from an extension designed to interoperate with your web site, it would seem ideal to somehow set the “origin” of the XPCOM component to the URL for your web site and use SameOrigin access..

  3. you might be interested to know of the statement made by Boris Zbarsky in this post: http://groups.google.com/group/mozilla.dev.tech.xpcom/browse_thread/thread/1d914272653ee02b/ef331f1dfe8868c9#ef331f1dfe8868c9
    he says that implementing nsISecurityCheckedComponent and implementing nsIClassInfo are mutually exclusive — that you do one or the other.
    in my experience of trying to imitate your example, the nsISecurity* methods are never called if you’ve made your component a DOM_OBJECT ala nsIClassInfo.
    so, your example produces an object which can be used from any web script without restriction.
    (From Alex: Uh, oops. I did ask bz to review the third part of my series, but only the third part, so the subject never came up. However, the goal of the project was to create components which anyone could run. There should probably be some restrictions.)

  4. I tried this approach, and it works great. Thanks, Alex. As posted by bz and others nsIClassInfo and nsISecurityCheckedComponent are mutually exclusive. I am facing another issue though, I’m unable to access properties or methods of return types that are XPCOM objects like nsIInputStream, or nsIDOMDocument. Do those need to be wrapped and registered with the categorymanager, just like the main XPCOM component or is there a shortcut?

Comments are closed.