4

I am looking to sandbox Java 8's Nashorn javascript engine. I've already discovered the --no-java flag, which helps, but I've also found the following link saying that one needs to be "running with SecurityManager enabled": http://mail.openjdk.java.net/pipermail/nashorn-dev/2013-September/002010.html

I haven't found documentation addressing how this is done with Nashorn, so how should this be done safely?

Scott B
  • 1,665
  • 1
  • 15
  • 14
  • Post about securing Nashorn already exists: http://stackoverflow.com/questions/20793089/secure-nashorn-js-execution – Marek Gregor Apr 29 '14 at 06:56
  • I'm fine merging as long as we include the extra context of wanting to run it under a Securitymanager – Scott B Apr 29 '14 at 06:58

3 Answers3

5

I know you probably don't need that anyway anymore, but for those who got here looking for an easy way to run nashorn in sandbox: if you just want to prevent scripts from using reflection, set up a ClassFilter. This way you can allow to use only SOME of the available classes... or none at all.

NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
ScriptEngine scriptEngine = factory.getScriptEngine(
    new String[] { "--no-java" }, //a quick way to disable direct access to java API
    null, //a ClassLoader, let's just ignore it
    new ClassFilter() { //this one simply forbids use of any java classes, including reflection
        @Override
        public boolean exposeToScripts(String string) {
            return false;
        }
    }
);
genobis
  • 1,081
  • 9
  • 13
4

It is possible to execute scripts using jjs with security manager enabled.

jjs -J-Djava.security.manager myscript.js

or

jjs -J-Djava.security.manager

for interactive mode. Note that if you just use -Djava.security.manager, than that option is processed by jjs tool. To pass option to VM, you've to use -J prefix. This is true of any other JDK bin tool other than the launcher tool "java".

tobias_k
  • 81,265
  • 12
  • 120
  • 179
Sundar
  • 41
  • 2
2

Unlike the java command, it doesn't seem possible to enable a security manager by setting the java.security.manager property on the jjs command line. (This might be a bug.) However, you can call the Java APIs from JavaScript to enable the security manager. In Java, this is

System.setSecurityManager(new SecurityManager());

and in JavaScript/Nashorn it's pretty much the same except you provide fully qualified class names:

java.lang.System.setSecurityManager(new java.lang.SecurityManager())

(Alternatively, you can import the names.) Either you can put this line into your application script, or you can put it into a script that you place on the jjs command line before your application script.

Example:

$ cat userhome.js
print(java.lang.System.getProperty("user.home"))
$ jjs userhome.js
/Users/xyzzy
$ cat secmgr.js
java.lang.System.setSecurityManager(new java.lang.SecurityManager())
$ jjs secmgr.js userhome.js
Exception in thread "main" java.security.AccessControlException: access denied ("java.util.PropertyPermission" "user.home" "read")
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:457)
    [...snip...]

It does work to set the policy file on the command line, though:

$ cat all.policy
grant {
    permission java.security.AllPermission;
};
$ jjs -Djava.security.policy=all.policy secmgr.js userhome.js
/Users/xyzzy

Or you can just add the equivalent setProperty call before enabling the security manager:

$ cat secmgr.js
java.lang.System.setProperty('java.security.policy', 'all.policy')
java.lang.System.setSecurityManager(new java.lang.SecurityManager())
Stuart Marks
  • 127,867
  • 37
  • 205
  • 259
  • You can enable the security manager in jjs command line "jjs -J-Djava.security.manager -J-Djava.security.policy=all.policy" , in addition, the debug log can also be enabled as well, "jjs -J-Djava.security.manager -J-Djava.security.policy=all.policy -J-Djava.security.debug=access,failure,policy" – Shing Lam Aug 11 '17 at 08:09