I use the following approach while running some Groovy script within an application. I obviously want to prevent the script from running (intentionally or unintentionally) a System.exit
I install a java SecurityManager in the usual way:
-Djava.security.manager -Djava.security.policy=<policy file>
In the <policy file>
I give my application all permissions (I do fully trust my application), i.e.:
grant {
permission java.security.AllPermission;
};
I limit the capabilities in the part where the Groovy script is run:
list = AccessController.doPrivileged(new PrivilegedExceptionAction<List<Stuff>> () {
public List<Stuff> run() throws Exception {
return groovyToExecute.someFunction();
}
}, allowedPermissionsAcc);
The allowedPermissionsAcc
doesn't change and therefore I create them in a static block
private static final AccessControlContext allowedPermissionsAcc;
static { // initialization of the allowed permissions
PermissionCollection allowedPermissions = new Permissions();
allowedPermissions.add(new RuntimePermission("accessDeclaredMembers"));
// ... <many more permissions here> ...
allowedPermissionsAcc = new AccessControlContext(new ProtectionDomain[] {
new ProtectionDomain(null, allowedPermissions)});
}
Now the tricky part is to find the right permissions.
If you want to allow access to certain libraries, you will quickly realize that they have not been written with a Security Manager in mind and don't handle one very gracefully, and finding out which permissions they need can be quite tricky. You will run into additional problems if you want to run UnitTests through the Maven Surefire plugin, or run on different platforms, like Linux/Windows, since the behavior can vary :-(. But those issues are another topic
Implementing a SecurityManager
is probably the best way to go. You would have to override checkPermission
. That method would look at the Permission
object passed to it, and determine if a certain action is dangerous. This way you can allow some permissions and disallow other permissions.
Can you describe the custom SecurityManager
you used?
From the docs:
The AccessControlContext of the thread that created the instance of URLClassLoader will be used when subsequently loading classes and resources.
The classes that are loaded are by default granted permission only to access the URLs specified when the URLClassLoader was created.
The URLClassLoader is doing exactly as its says, the AccessControlContext is what you need to be looking at. Basically the thread that is being referenced in AccessControlContext does not have permissions to do what you think it does.