Java – Is it possible to sandbox Runnable

Is it possible to sandbox Runnable… here is a solution to the problem.

Is it possible to sandbox Runnable

Is it possible to sandbox my Runnable in Java? Given a Runnable, I want the code in it (along with any threads it spawns) to run in a sandbox that only allows code to access specific paths on the file system. Once the Runnable completes, the thread should return any normal permissions it has, while any remaining derivative threads will still have file system limits applied.

I want to do this at runtime. This means that I want to avoid creating a policy file and passing custom parameters to the JVM. So far I’ve been able to apply sandboxing to my entire application, but I haven’t found a way to scope it to Runnable…. only running in the current thread

if (System.getSecurityManager() == null) {
    System.setSecurityManager(new SecurityManager());
}

CodeSource nullSource = new CodeSource(null, (CodeSigner[]) null);

PermissionCollection perms = new Permissions();
perms.add(new FilePermission(path.toAbsolutePath().toString() + "/*", "read"));

ProtectionDomain domain = new ProtectionDomain(nullSource, perms);
AccessControlContext safeContext = new AccessControlContext(
        new ProtectionDomain[]{domain});

AccessController.doPrivileged((PrivilegedAction) () -> {
    try {
        r.run();
    } catch (Exception e) {
        throw new IllegalStateException(e);
    }
    return null;
}, safeContext);

Solution

The doPrivileged

technique of restricting permissions only applies to trusted code that does not abuse its location (for example, by calling doPrivileged itself). For example, it is useful as a layer to prevent XML inclusions, but is not an untrusted plug-in.

You can use a custom ClassLoader to load code with specific permissions at run time, but you must reload the code if you need permissions.

The Object Competency Model provides a “pure” dynamic solution. The container passes objects that can perform privileged operations to the plug-in. Internally, an object’s methods can simply be operations surrounded by doVist. Crucially, these operations are only available through instances and are not allowed to be instantiated by unprivileged code. If you ignore ServiceMangaer, this is similar to FileOpenService in JNLP/WebStart. Inside the JDK, you might see things like Unsafe and SharedSecrets, although they’re more about avoiding duplicate security checks.

Related Problems and Solutions