From 09dbbd3de3f0f374f3548d5fe6145720094d2f86 Mon Sep 17 00:00:00 2001 From: Gregory Brail Date: Mon, 13 Apr 2015 16:34:17 -0700 Subject: [PATCH] Add "initSafeStandardObjects" to create standard objects with no Java class access whatsoever. --- src/org/mozilla/javascript/Context.java | 99 +++++++++++++++++++ src/org/mozilla/javascript/ScriptRuntime.java | 42 +++++--- 2 files changed, 125 insertions(+), 16 deletions(-) diff --git a/src/org/mozilla/javascript/Context.java b/src/org/mozilla/javascript/Context.java index 16003b628a..6f1d1a5e71 100644 --- a/src/org/mozilla/javascript/Context.java +++ b/src/org/mozilla/javascript/Context.java @@ -1001,6 +1001,33 @@ public final ScriptableObject initStandardObjects() return initStandardObjects(null, false); } + /** + * Initialize the standard objects, leaving out those that offer access directly + * to Java classes. This sets up "scope" to have access to all the standard + * JavaScript classes, but does not create global objects for any top-level + * Java packages. In addition, the "Packages," "JavaAdapter," and + * "JavaImporter" classes, and the "getClass" function, are not + * initialized. + * + * The result of this function is a scope that may be safely used in a "sandbox" + * environment where it is not desirable to give access to Java code from JavaScript. + * + * Creates instances of the standard objects and their constructors + * (Object, String, Number, Date, etc.), setting up 'scope' to act + * as a global object as in ECMA 15.1.

+ * + * This method must be called to initialize a scope before scripts + * can be evaluated in that scope.

+ * + * This method does not affect the Context it is called upon. + * + * @return the initialized scope + */ + public final ScriptableObject initSafeStandardObjects() + { + return initSafeStandardObjects(null, false); + } + /** * Initialize the standard objects. * @@ -1024,6 +1051,37 @@ public final Scriptable initStandardObjects(ScriptableObject scope) return initStandardObjects(scope, false); } + /** + * Initialize the standard objects, leaving out those that offer access directly + * to Java classes. This sets up "scope" to have access to all the standard + * JavaScript classes, but does not create global objects for any top-level + * Java packages. In addition, the "Packages," "JavaAdapter," and + * "JavaImporter" classes, and the "getClass" function, are not + * initialized. + * + * The result of this function is a scope that may be safely used in a "sandbox" + * environment where it is not desirable to give access to Java code from JavaScript. + * + * Creates instances of the standard objects and their constructors + * (Object, String, Number, Date, etc.), setting up 'scope' to act + * as a global object as in ECMA 15.1.

+ * + * This method must be called to initialize a scope before scripts + * can be evaluated in that scope.

+ * + * This method does not affect the Context it is called upon. + * + * @param scope the scope to initialize, or null, in which case a new + * object will be created to serve as the scope + * @return the initialized scope. The method returns the value of the scope + * argument if it is not null or newly allocated scope object which + * is an instance {@link ScriptableObject}. + */ + public final Scriptable initSafeStandardObjects(ScriptableObject scope) + { + return initSafeStandardObjects(scope, false); + } + /** * Initialize the standard objects. * @@ -1057,6 +1115,47 @@ public ScriptableObject initStandardObjects(ScriptableObject scope, return ScriptRuntime.initStandardObjects(this, scope, sealed); } + /** + * Initialize the standard objects, leaving out those that offer access directly + * to Java classes. This sets up "scope" to have access to all the standard + * JavaScript classes, but does not create global objects for any top-level + * Java packages. In addition, the "Packages," "JavaAdapter," and + * "JavaImporter" classes, and the "getClass" function, are not + * initialized. + * + * The result of this function is a scope that may be safely used in a "sandbox" + * environment where it is not desirable to give access to Java code from JavaScript. + * + * Creates instances of the standard objects and their constructors + * (Object, String, Number, Date, etc.), setting up 'scope' to act + * as a global object as in ECMA 15.1.

+ * + * This method must be called to initialize a scope before scripts + * can be evaluated in that scope.

+ * + * This method does not affect the Context it is called upon.

+ * + * This form of the method also allows for creating "sealed" standard + * objects. An object that is sealed cannot have properties added, changed, + * or removed. This is useful to create a "superglobal" that can be shared + * among several top-level objects. Note that sealing is not allowed in + * the current ECMA/ISO language specification, but is likely for + * the next version. + * + * @param scope the scope to initialize, or null, in which case a new + * object will be created to serve as the scope + * @param sealed whether or not to create sealed standard objects that + * cannot be modified. + * @return the initialized scope. The method returns the value of the scope + * argument if it is not null or newly allocated scope object. + * @since 1.7.6 + */ + public ScriptableObject initSafeStandardObjects(ScriptableObject scope, + boolean sealed) + { + return ScriptRuntime.initSafeStandardObjects(this, scope, sealed); + } + /** * Get the singleton object that represents the JavaScript Undefined value. */ diff --git a/src/org/mozilla/javascript/ScriptRuntime.java b/src/org/mozilla/javascript/ScriptRuntime.java index f2d45c4d9d..6d16835991 100644 --- a/src/org/mozilla/javascript/ScriptRuntime.java +++ b/src/org/mozilla/javascript/ScriptRuntime.java @@ -151,9 +151,9 @@ public static boolean isRhinoRuntimeType(Class cl) } } - public static ScriptableObject initStandardObjects(Context cx, - ScriptableObject scope, - boolean sealed) + public static ScriptableObject initSafeStandardObjects(Context cx, + ScriptableObject scope, + boolean sealed) { if (scope == null) { scope = new NativeObject(); @@ -204,22 +204,9 @@ public static ScriptableObject initStandardObjects(Context cx, // define lazy-loaded properties using their class name new LazilyLoadedCtor(scope, "RegExp", "org.mozilla.javascript.regexp.NativeRegExp", sealed, true); - new LazilyLoadedCtor(scope, "Packages", - "org.mozilla.javascript.NativeJavaTopPackage", sealed, true); - new LazilyLoadedCtor(scope, "getClass", - "org.mozilla.javascript.NativeJavaTopPackage", sealed, true); - new LazilyLoadedCtor(scope, "JavaAdapter", - "org.mozilla.javascript.JavaAdapter", sealed, true); - new LazilyLoadedCtor(scope, "JavaImporter", - "org.mozilla.javascript.ImporterTopLevel", sealed, true); new LazilyLoadedCtor(scope, "Continuation", "org.mozilla.javascript.NativeContinuation", sealed, true); - for (String packageName : getTopPackageNames()) { - new LazilyLoadedCtor(scope, packageName, - "org.mozilla.javascript.NativeJavaTopPackage", sealed, true); - } - if (withXml) { String xmlImpl = cx.getE4xImplementationFactory().getImplementationClassName(); new LazilyLoadedCtor(scope, "XML", xmlImpl, sealed, true); @@ -271,6 +258,29 @@ public static ScriptableObject initStandardObjects(Context cx, return scope; } + + public static ScriptableObject initStandardObjects(Context cx, + ScriptableObject scope, + boolean sealed) + { + ScriptableObject s = initSafeStandardObjects(cx, scope, sealed); + + new LazilyLoadedCtor(s, "Packages", + "org.mozilla.javascript.NativeJavaTopPackage", sealed, true); + new LazilyLoadedCtor(s, "getClass", + "org.mozilla.javascript.NativeJavaTopPackage", sealed, true); + new LazilyLoadedCtor(s, "JavaAdapter", + "org.mozilla.javascript.JavaAdapter", sealed, true); + new LazilyLoadedCtor(s, "JavaImporter", + "org.mozilla.javascript.ImporterTopLevel", sealed, true); + + for (String packageName : getTopPackageNames()) { + new LazilyLoadedCtor(s, packageName, + "org.mozilla.javascript.NativeJavaTopPackage", sealed, true); + } + + return s; + } static String[] getTopPackageNames() { // Include "android" top package if running on Android