Sandboxing JSR-223
Asked Answered
A

3

14

I'm trying to sandbox JSR-223. Specifically, I don't want any script to have access to any of my classes. (I hear Rhino can do that with ClassShutter, but I want to do it generally. ie. for all script engines of JSR-223).

I first tried to use the AccessController.doPrivileged solution, by passing no permissions at all. It works for most permissions, but the scripts can still access all my public classes (it seems to ignore "package access" permission ...?).

I found this. My question is : how do I install a custom ClassLoader on the script engine ? (Or How do I replace the ClassLoader globally if I have to ?)

Almatadema answered 9/9, 2009 at 12:52 Comment(0)
C
8

There is a constructor for ScriptEngineManager that takes a classloader. The classloader is used to load the scripting engine implementation. As classes inherit their classloaders, the scripting engine and any objects it creates should also use that classloader.

That classloader needs to deny the existence of any classes that are not white-listed.

Top it off with a custom SecurityManager so you can base access checks on which classloader in use.

Edit: Here's an article I found on Sandboxing Rhino in Java. Most of it should also apply to JSR-223. Sun's implementation is Rhino with modifications, so there may be some differences.

Caul answered 10/9, 2009 at 22:28 Comment(4)
Thanks. I tried that. But for some reason, the only classes that my ClassLoader is asked for are com.sun.script.javascript.RhinoScriptEngineFactory and other engines factories.Almatadema
When I played with a custom ClassLoader last I had trouble getting it to use my ClassLoader all the time as well. I believe I had to use Thread.currentThread().setContextClassLoader(cl) in addition to passing the ClassLoader in Class.forName().Mccrary
How can you deny access to classes loaded via the bootstrap classloader with a custom classloader? Aren't parent classloaders always checked first, and isn't getParent() final? If you can't orphan a custom classloader from the bootstrap classloader then you can't deny access to sources of authority like System.exit(int) for example.Astute
When creating a new ClassLoader, you can use super(null) to construct one without a parent. Your implementation can then explicitly delegate to the system ClassLoaders for white listed types. Note: sandboxing cannot be done with ClassLoaders alone. You need to use a SecurityManager as well.Caul
M
0

Is it possible to run the part of your application that requires the scripting engine in a separate JVM? You could start the scripting engine JVM with a different classpath (and security manager) and then use some form of lightweight message passing between the 2 JVMs.

Melano answered 9/9, 2009 at 13:45 Comment(2)
Thank you for this idea. Well, yes I could do it. But in my case, it's not an option. I actually pass a huge DOM document to the script (the only objects I allow access to). And I don't want to double that in memory.Almatadema
With the PassThroughProxyHandler it's not very difficult to implement communication between ClassLoaders and you don't have to copy the entire DOM over either. surguy.net/articles/communication-across-classloaders.xmlMccrary
A
0

See http://code.google.com/p/prebake/source/browse/trunk/code/src/org/prebake/js/RhinoExecutor.java and related classes in the same package, especially the SANDBOXING_FACTORY there.

That's some code that sandboxes a rhino interpreter to allow it access to the filesystem mediated by a loader.

Astute answered 2/4, 2011 at 0:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.