Question

Part of our java application needs to run javascript that is written by non-developers. These non-developers are using javascript for data formatting. (Simple logic and string concatenation mostly).

My question is how can I setup the execution of these scripts to make sure scripting errors don't have a major negative impact on the rest of the application.

  • Need to guard against infinite loops
  • Guard against spawning new threads.
  • Limit access to services and environment
    • File system (Example: If a disgruntled script writer decided to delete files)
    • Database (Same thing delete database records)

Basically I need to setup the javascript scope to only include exactly what they need and no more.

Was it helpful?

Solution

To guard against infinite loops, you'd need to put it in a separate process so that it could be killed.

To guard against creating threads, you'd need to extend SecurityManager (the default implementation allows untrusted code to access non-root thread groups).

Java security does allow you to prevent access to the file system.

For database restrictions, you might be able to use the standard SQL user security, but that is quite weak. Otherwise, you need to provide an API that enforces your restrictions.

Edit: I should point out that the version of Rhino provided with JDK6 has had security work done on it, but doesn't include the compiler.

OTHER TIPS

To guard against infinite loops, you can observe the instruction count as the script runs (this works only with interpreted scripts, not with compiled ones).

There is this example in the Rhino JavaDocs to prevent a script from running for more than ten seconds:

 protected void observeInstructionCount(Context cx, int instructionCount)
 {
     MyContext mcx = (MyContext)cx;
     long currentTime = System.currentTimeMillis();
     if (currentTime - mcx.startTime > 10*1000) {
         // More then 10 seconds from Context creation time:
         // it is time to stop the script.
         // Throw Error instance to ensure that script will never
         // get control back through catch or finally.
         throw new Error();
     }
 }

To block Java class and method access have a look at...

http://codeutopia.net/blog/2009/01/02/sandboxing-rhino-in-java/

I just ran across this blog post that seems to be useful for sandboxing more or less anything (not just Rhino):

http://calumleslie.blogspot.com/2008/06/simple-jvm-sandboxing.html

If you are looking for pure JavaScript functions only, here is a solution basing on JDK embedded Rhino library without importing any 3rd-parties libraries:

  1. Find out JavaScript script engine factory class name by ScriptEngineManager#getEngineFactories
  2. Load script engine factory class in a new class loader, in which JavaMembers or other related classes will be ignored.
  3. Call #getScriptEngine on loaded script engine factory and eval scripts on returned script engine.

If given script contains Java script, class loader will try to load JavaMembers or other classes and trigger class not found exceptions. In this way, malicious scripts will be ignored without execution.

Please read ConfigJSParser.java and ConfigJSClassLoader.java files for more details:

https://github.com/webuzz/simpleconfig/tree/master/src/im/webuzz/config

Javascript is single-threaded and can't access the filesystem, so I don't think you have to worry about those. I'm not sure if there's a way to set a timeout to guard against infinite loops, but you could always spawn a (Java) thread that executes the script, and then kill the thread after so much time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top