views:

304

answers:

2

We have an admin debug console in our app that lets you enter a script and submit it to get the result back. We're not worried about malicious users, but would like to prevent basic stuff like someone entering System.exit(1) just to see what it does. Unfortunately, adding a security policy file isn't an option. Is there any other way to sandbox a script?

+1  A: 

Groovy comes with special Security Manager for this. Just set it before you run the script,

        System.setSecurityManager(new NoExitSecurityManager());
ZZ Coder
That's cool, but I can't make global changes to the JVM, and I only need to limit security for the script.
noah
+1  A: 

I looked at Groovy's "NoExitSecurityManager" and found it is doing exactly that: disallowing System.exit() ... which is not enough.

My solution was creating my own class "DisallowAllSecurityManager" which extends SecurityManager and disallows everything a script should not need, like write access to the file system or connecting to other hosts, by throwing an SecurityException in each check.. method.

But: You cannot throw an exception in all check.. methods. Here is a list of check.. methods you need to allow:

  • checkCreateClassLoader()
  • checkMemberAccess()
  • checkPackageAccess()
  • checkPermission()
  • checkPropertyAccess()
  • checkRead()

When you want to evaluate your Groovy script you can do it the following way, limiting only the groovy script:

SecurityManager securityManager = System.getSecurityManager();
try {
 System.setSecurityManager(new DisallowAllSecurityManager());
 Object result = groovyShell.evaluate(expression);
        ...
} catch (...) {
        ...
} finally {
        System.setSecurityManager(securityManager);
}
arturh
The only problem with this answer is that other threads than the current one are also affected (i.e., their security manager is replaced) which could cause really hard to track down problems. None the less, it seems to be the best possible answer so I'm accepting it.
noah