Add sanitize functions
ADD
shim/src/evaluate/verifyStrictFunctionBody.js
+
+//TODO this is a stub
+
+export default function verifyStrictFunctionBody() { return arguments[0]; }
\ No newline at end of file

MODIFY
shim/src/evaluators.js
shim/src/evaluators.js
@@ -9,27 +9,12 @@ function getEvalEvaluator(sandbox) {
return evaluate(sourceText, sandbox);
}
};
- setPrototypeOf(o.eval, sandbox.Function);
+ // TODO
+ // setPrototypeOf(o.eval, sandbox.Function);
o.eval.toString = () => 'function eval() { [shim code] }';
return o.eval;
}
-function getFunctionEvaluator(sandbox) {
- const { confinedWindow } = sandbox;
- const f = function Function(...args) {
- // console.log(`Shim-Evaluation: Function("${args.join('", "')}")`);
- const sourceText = args.pop();
- const fnArgs = args.join(', ');
- return evaluate(`(function anonymous(${fnArgs}){\n${sourceText}\n}).bind(this)`, sandbox);
- }
- f.prototype = confinedWindow.Function.prototype;
- setPrototypeOf(f, f.prototype);
- f.prototype.constructor = f;
- f.toString = () => 'function Function() { [shim code] }';
- return f;
-}
-
export function getEvaluators(sandbox) {
- sandbox.Function = getFunctionEvaluator(sandbox);
sandbox.eval = getEvalEvaluator(sandbox);
}
\ No newline at end of file

ADD
shim/src/repair/functionConstructors.js
+// Adapted from SES/Caja - Copyright (C) 2011 Google Inc.
+// https://github.com/google/caja/blob/master/src/com/google/caja/ses/startSES.js
+// https://github.com/google/caja/blob/master/src/com/google/caja/ses/repairES5.js
+
+import verifyStrictFunctionBody from '../evaluate/verifyStrictFunctionBody';
+import { getPrototypeOf, setPrototypeOf, defineProperty } from '../commons';
+
+// This block replaces the original Function, %GeneratorFunction% and
+// %AsycnGeneratorFunction%, with safe implementations that preserve SES
+// confinement. After this block is done, the originals should no longer be
+// reachable.
+
+export default function repairFunctionConstructors(confinedWindow) {
+
+ const { eval: secureEval } = confinedWindow;
+
+ /**
+ * A safe form of the {@code Function} constructor, which
+ * constructs strict functions that can only refer freely to the
+ * {@code sharedImports}.
+ *
+ * The returned function is strict whether or not it declares
+ * itself to be.
+ */
+ function secureFunctionFactory(funcDeclaration) {
+ return (function SecureFunction(...params) {
+ var body = verifyStrictFunctionBody(params.pop() || '');
+
+ var exprSrc = `
+(${funcDeclaration}(${params.join(',')} {
+ ${body}
+})`;
+ return secureEval(exprSrc);
+ });
+ }
+
+ // Our process to secure constructors:
+ // 1. Obtain the original prototype of an instance from the sandbox
+ // 2. Create a secure constructor
+ // 3. Replace its prototype property with the original prototype
+ // 4*. Replace its internal [[Prototype]] property with a secure function (except for Function)
+ // 5. Replace the original prototype's constructor with the secure constructor
+ // 6*. Export the secure function to the sandbox (only for Function)
+
+ const FuncProto = getPrototypeOf(secureEval('(function () {})'));
+ const secureFunction = secureFunctionFactory('function');
+ defineProperty(secureFunction, 'prototype', { value: FuncProto });
+ defineProperty(secureFunction, 'toString', { value: () => 'function Function() { [shim code] }' });
+ // Function already has [[Prototype]] defined as itself
+ defineProperty(FuncProto, 'constructor', { value: secureFunction });
+ confinedWindow.Function = secureFunction;
+
+ const GenFuncProto = getPrototypeOf(secureEval('(function* () {})'));
+ const secureGenerator = secureFunctionFactory('function*');
+ defineProperty(secureGenerator, 'prototype', { value: GenFuncProto });
+ defineProperty(secureGenerator, 'toString', { value: () => 'function GeneratorFunction() { [shim code] }' });
+ setPrototypeOf(secureGenerator, secureFunction);
+ defineProperty(GenFuncProto, 'constructor', { value: secureGenerator });
+ // Generator isn't exported on global
+
+ const AsyncFuncProto = getPrototypeOf(secureEval('(async function () {})'));
+ const secureAsyncFunction = secureFunctionFactory('async function');
+ defineProperty(secureAsyncFunction, 'prototype', { value: AsyncFuncProto });
+ defineProperty(secureAsyncFunction, 'toString', { value: () => 'function AsyncFunction() { [shim code] }' });
+ setPrototypeOf(secureAsyncFunction, secureFunction);
+ defineProperty(AsyncFuncProto, 'constructor', { value: secureAsyncFunction });
+ // AsyncFunction isn't exported on global
+}

RENAME
shim/src/repair/accessors.js
shim/src/repair/objectAccessors.js
@@ -8,7 +8,9 @@ import { getPrototypeOf, defineProperty, getOwnPropertyDescriptor } from '../com
// we need to redefine them while in strict mode.
// https://tc39.github.io/ecma262/#sec-object.prototype.__defineGetter__
-export default function repairAccessors(objProto) {
+export default function repairObjectAccessors(confinedWindow) {
+
+ const { Object: { prototype: objProto } } = confinedWindow;
try {

MODIFY
shim/src/sanitize.js
shim/src/sanitize.js
-import repairAccessors from "./repair/accessors";
+import repairObjectAccessors from "./repair/objectAccessors";
+import repairFunctionConstructors from "./repair/functionConstructors";
// locking down the environment
export function sanitize(sandbox) {
- const { confinedWindow: { Object: { prototype: objProto } } } = sandbox;
+ const { confinedWindow } = sandbox;
- repairAccessors(objProto);
- // TODO: other steps
+ repairObjectAccessors(confinedWindow);
+ repairFunctionConstructors(confinedWindow);
}
\ No newline at end of file

Add sanitize functions