Subj : Workaround was: Rhino security cookbook for untrusted javascript? To : netscape.public.mozilla.jseng From : Jan Grant Date : Fri May 06 2005 06:47 pm Ok, I think I have a workaround for my Rhino security problems; I'd appreciate it if anyone might give feedback or opinions. Hopefully this might help anyone else who's in the same boat and is prepared to accept the same restrictions on Rhino. The problem is/was that I'm trying to use javascript as a "little language" to permit relatively untrusted third parties to upload and execute javascripts within a web application: their entire purpose is to coordinate a few calls on the objects exposed by the web app. I want to expose some of the web application's operations to the javascript by embedding objects. Unfortunately, the object graph reachable from one of the embedded objects covers members of quite a few classes; and I wanted to avoid having to wrap all of those classes in Scriptable wrappers by hand. Now, those web application objects require certain levels of security privilege (reading files, writing files, etc) for particular operations. Unfortuantely, making large and invasive changes to the web app (someone else wrote it) isn't feasible; for instance, sprinkling doPrivileged() calls throughout it would be problematic. Additionally, because the webapp runs under a traditional security manager (tomcat's), I'm limited in what I can do without doPrivileged(), since if I slap a restrictive policy on rhino then the embedded application objects are also crippled when called from javascript. The last part of the problem is this: even without a restrictive security policy in place, the embedded objects colaborate to enforce the programmatic security model of the web application. This enforcement, however, effectively uses objects as capabilities (if you can reach the object you can perform the operation); thus, unscrupulous code could create new capability objects (by calling "new"), effectively circumventing the cooperative security model in the webapp's API. Unfortunately, rhino exposes the getClass() method on those objects when it wraps them, and from there it's a relatively small step to being able to access all the java reflection APIs via javascript. A security policy that turns off the runtime permission "getClassLoader", "accessDeclaredMembers" and accessClassInPackage.* unfortunately crippled Rhino. Anyway: getClass() seemed to be the major stumbling block. So I made a couple of small changes: firstly, removing getClass and the other NativeJavaTopPackage objects installed by initStandardObjects; secondly, by a gross hack in JavaMembers#reflect that simply adds: if ("getClass".equals(name)) continue; at the appropriate spot. The resulting (rather neutered) Rhino appears to still permit me to expose to untrusted scripts the functionality I'm after; and I _think_ it's relatively safe. Any opinions gladly received: cheers, jan -- jan grant, ILRT, University of Bristol. http://www.ilrt.bris.ac.uk/ Tel +44 (0)117 9287088 (with luck) http://ioctl.org/jan/ Hang on, wasn't he holding a wooden parrot? No! It was a porcelain owl. .