How do I create a Java sandbox?

Viewed 34913

I want to make my application to run other people's code, aka plugins. However, what options do I have to make this secure so they don't write malicious code. How do I control what they can or can not do?

I have stumbled around that JVM has a "built in sandbox" feature - what is it and is this the only way? Are there third-party Java libraries for making a sandbox?

What options do I have? Links to guides and examples is appreciated!

7 Answers

After spending a day in the depths of the Java security APIs, I found an amazingly simple solution for executing untrusted code within a sandbox confined by Permissions:

https://github.com/janino-compiler/janino/blob/master/commons-compiler/src/main/java/org/codehaus/commons/compiler/Sandbox.java

Here's the (simplified) source code:

package org.codehaus.commons.compiler;

import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Policy;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;

public final
class Sandbox {

    static {

        if (System.getSecurityManager() == null) {

            // Before installing the security manager, configure a decent ("positive") policy.
           Policy.setPolicy(new Policy() {

                @Override public boolean
                implies(ProtectionDomain domain, Permission permission) { return true; }
            });

            System.setSecurityManager(new SecurityManager());
        }
    }

    private final AccessControlContext accessControlContext;

    /**
     * @param permissions Will be applied on later calls to {@link #confine(PrivilegedAction)} and {@link
     *                    #confine(PrivilegedExceptionAction)}
     */
    public
    Sandbox(PermissionCollection permissions) {
        this.accessControlContext = new AccessControlContext(new ProtectionDomain[] {
            new ProtectionDomain(null, permissions)
        });
    }

    /**
     * Runs the given <var>action</var>, confined by the permissions configured through the {@link
     * #Sandbox(PermissionCollection) constructor}.
     *
     * @return The value returned by the <var>action</var>
     */
    public <R> R
    confine(PrivilegedAction<R> action) {
        return AccessController.doPrivileged(action, this.accessControlContext);
    }

    public <R> R
    confine(PrivilegedExceptionAction<R> action) throws Exception {
        try {
            return AccessController.doPrivileged(action, this.accessControlContext);
        } catch (PrivilegedActionException pae) {
            throw pae.getException();
        }
    }
}
Related