Skip to content

Instantly share code, notes, and snippets.

@purplefox
Last active December 30, 2015 08:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save purplefox/7804105 to your computer and use it in GitHub Desktop.
Save purplefox/7804105 to your computer and use it in GitHub Desktop.
import javax.script.*;
/*
This example demonstrates possible leakage of Nashorn scopes and the incorrect scope being used when executing
a function defined in one scope, from another scope.
*/
public class LeakTest {
public static void main(String[] args) {
new LeakTest().run();
}
/*
script1 contains a function which simply sets a global, and then immediately logs out the type of the global
to system.out
I would expect it to log "typeof global is number"
Instead it logs "typeof global is undefined"
script1 runs inside its own scope - this is basically how commonJS modules would be run -they are allowed to set
globals but these won't be visible to other scopes that call it.
*/
private String script1 =
"function foo() { \n" +
" _someglobal = 123; \n" +
" java.lang.System.out.println('typeof global is ' + typeof _someglobal); \n" +
" // Now set another global \n" +
" _someotherglobal = 456; \n" +
"} \n" +
"_javaobject.setFunction(foo);";
/*
script2 simply calls the function foo() which we export by setting its value through a Java object
it then tries to display the value of _someotherglobal which was defined in another scope, and succeeds!
*/
private String script2 =
"foo(); \n" +
"java.lang.System.out.println('someotherglobal is ' + _someotherglobal)";
private void run() {
try {
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("nashorn");
// Run script1 in it's own scope
ScriptContext ctx = new SimpleScriptContext();
Bindings bindings = engine.createBindings();
bindings.put("_javaobject", this);
ctx.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
engine.eval(script1, ctx);
// Run script2 in it's own scope
bindings = engine.createBindings();
bindings.put("foo", function);
ctx = new SimpleScriptContext();
ctx.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
engine.eval(script2, ctx);
} catch (Exception e) {
e.printStackTrace();
}
}
private Object function;
// This allows us to pass an JavaScript object from one scope to another
public void setFunction(Object function) {
this.function = function;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment