oracle / graaljs

GraalJS – A high-performance, ECMAScript compliant, and embeddable JavaScript runtime for Java
https://www.graalvm.org/javascript/
Universal Permissive License v1.0
1.81k stars 190 forks source link

GraalJS breaks when a security manager is installed #318

Closed BillZaumen closed 4 years ago

BillZaumen commented 4 years ago

The enclosed Java program, used to run a script, fails when run using Graalvm but not when using Nashorn with the following stacktrace: graaldir/bin/java Test1 test1.js class com.oracle.truffle.js.scriptengine.GraalJSScriptEngine Exception in thread "main" java.security.AccessControlException: access denied ("java.util.PropertyPermission" "org.graalvm.nativeimage.imagecode" "read") at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:472) at java.base/java.security.AccessController.checkPermission(AccessController.java:897) at java.base/java.lang.SecurityManager.checkPermission(SecurityManager.java:322) at java.base/java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1066) at java.base/java.lang.System.getProperty(System.java:814) at org.graalvm.sdk/org.graalvm.nativeimage.ImageInfo.inImageRuntimeCode(ImageInfo.java:132) ... To run, remove the '.txt' suffixes in the file names and then

javac Test1.java

java Test1 test1.js

The program will run as expected using openjdk. For Graal, I used graalvm-ce-java11-20.1.0. I would surmise a custom security policy is needed given the stack trace, but I cannot find documentation indicating what to use. When the statement installing a security manager is removed, GraalJS and Nashorn behave identically. Given a script that does little more than write some text to stdout, however, one would expect this to be covered by a default security policy.

Test1.java.txt test1.js.txt

wirthi commented 4 years ago

Hi @BillZaumen

thanks for your question.

The Truffle Language Implementation Framework, which Graal.js is implemented upon, does currently not support the SecurityManager, at least not with a default security policy. It is possible to set up a fitting policy to make it work (tools like http://pro-grade.sourceforge.net/policy-file-generator.html might be able to help you). I don't think there is documentation from our side on that yet (right, @chumer ?) We strive to provide better security by default than Nashorn did, so that limits our options here (also, the current SecurityManager does not cover more recent security problems adequately https://mail.openjdk.java.net/pipermail/vuln-announce/2019-July/000002.html).

Another problem is that GraalVM's native-image tool does not support SecurityManager (see https://github.com/oracle/graal/blob/master/substratevm/LIMITATIONS.md#security-manager). This should not affect you in your setup, but I see org.graalvm.nativeimage.imagecode to be among the culprits - that's something we need to investigate.

Best, Christian

BillZaumen commented 4 years ago

Thanks for your reply.

Just to add more information, I have a program that loads various Java class libraries, sets up access to specific files or directories, installs a security manager, and then runs a script. The security manager's main function is to prevent inadvertent data loss due to programming errors when programmers collaborating with each other share scripts. The program makes use of a Java class I wrote named DirectoryAccessor. An instance can be created before the security manager is installed, but not afterwards unless a specific permission is granted. After the security manager is installed, the script can open or close the files in a specific directory and in its subdirectories, not in other directories.

Without a security manager, an error could easily occur if someone blindly copied a coding example such as the following (Java, in this case using a coding example for some animation software):

 animation.initFrames(25*secs, "tmp/img-", "png");
 animation.scheduleFrames(0, 25 * secs);
 File dir = new File("tmp");
 dir.mkdirs();
 for (File file:dir.listFiles()) {
      file.delete();
 }
 animation.run();

This will create a large number of files in the tmp directory with names such as img-0001.png, img-0002.png, etc. A test will work just fine but if someone gets two scripts based on this example, each using a directory named "tmp", files could be overwritten by accident. The use of a directory accessor prevents directory names such as "tmp" from being hard-wired into the script: if someone does, you just get a security exception so the person writing the script finds out immediately - before it is given to someone else.

Regards,

Bill
wirthi commented 4 years ago

Hi @BillZaumen

We have investigated SecurityManagers a bit more closely lately. The Truffle language implementation framework and the languages based on it like Graal.js typically need something close to "all permissions" to be executed.

Based on our findings, we have improved our Security Manager support. This did not make it to 20.2 though, it will be in 20.3 and already is in the nightly builds of GraalVM CE. With the latest changes we made sure that all the relevant permissions are given in our code. You still need to make sure that your user application has the relevant permissions - you can use the tool quote above for that; a default SecurityManager most certainly will not be good enough for that.

Best, Christian