140 lines
No EOL
4 KiB
JavaScript
Executable file
140 lines
No EOL
4 KiB
JavaScript
Executable file
'use strict';
|
|
|
|
var clones = require('clones');
|
|
|
|
var hasWindow = typeof window !== 'undefined';
|
|
exports.hasWindow = hasWindow;
|
|
var hasGlobal = typeof global !== 'undefined';
|
|
exports.hasGlobal = hasGlobal;
|
|
var FN_NOOP = 'function () {}';
|
|
var NON_IDENTIFIER = /^\d|-|^(break|case|catch|continue|debugger|default|delete|do|else|finally|for|function|if|in|instanceof|new|return|switch|this|throw|try|typeof|var|void|while|with|class|const|enum|export|extends|import|super|implements|interface|let|package|private|protected|public|static|yield|null|true|false)$/;
|
|
|
|
var isIdentifier = function isIdentifier(key) {
|
|
return !NON_IDENTIFIER.test(key);
|
|
};
|
|
|
|
exports.isIdentifier = isIdentifier;
|
|
/**
|
|
* create a fresh context where nearly nothing is allowed
|
|
* @private
|
|
*/
|
|
|
|
exports.createContext = function () {
|
|
// protection might not be complete!
|
|
var context = {
|
|
// disallowed
|
|
global: undefined,
|
|
process: undefined,
|
|
module: undefined,
|
|
require: undefined,
|
|
document: undefined,
|
|
window: undefined,
|
|
Window: undefined,
|
|
// no evil...
|
|
eval: undefined,
|
|
Function: undefined
|
|
};
|
|
|
|
var fillContext = function fillContext(root) {
|
|
Object.keys(root).forEach(function (key) {
|
|
if (isIdentifier(key)) {
|
|
context[key] = undefined;
|
|
}
|
|
});
|
|
}; // locally define all potential global vars
|
|
|
|
|
|
if (hasGlobal) {
|
|
fillContext(global);
|
|
cloneFunctions(context);
|
|
context.Buffer = _protect('Buffer');
|
|
context.console = clones(console, console); // console needs special treatment
|
|
|
|
context.console.constructor.constructor = FN_NOOP;
|
|
}
|
|
|
|
if (hasWindow) {
|
|
fillContext(window, true);
|
|
cloneFunctions(context);
|
|
protectBuiltInObjects(context);
|
|
context.console = clones(console, console); // console needs special treatment
|
|
|
|
try {
|
|
context.Object.constructor.constructor = FN_NOOP;
|
|
} catch (e) {}
|
|
}
|
|
|
|
return context;
|
|
};
|
|
/**
|
|
* Apply allowed context properties
|
|
* @private
|
|
*/
|
|
|
|
|
|
exports.allow = function (context, newContext) {
|
|
Object.keys(context || {}).forEach(function (key) {
|
|
if (isIdentifier(key)) {
|
|
newContext[key] = context[key]; // this is harmful - objects can be overwritten
|
|
}
|
|
});
|
|
};
|
|
/**
|
|
* clone global functions
|
|
* @private
|
|
*/
|
|
|
|
|
|
function cloneFunctions(context) {
|
|
;
|
|
['clearImmediate', 'clearInterval', 'clearTimeout'].forEach(function (str) {
|
|
try {
|
|
var fn = new Function("return ".concat(str))(); // eslint-disable-line no-new-func
|
|
|
|
context[str] = fn ? function () {
|
|
return fn.apply(null, [].slice.call(arguments));
|
|
} : undefined;
|
|
} catch (e) {}
|
|
});
|
|
['setImmediate', 'setInterval', 'setTimeout'].forEach(function (str) {
|
|
try {
|
|
var fn = new Function("return ".concat(str))(); // eslint-disable-line no-new-func
|
|
|
|
context[str] = fn ? function (f) {
|
|
if (typeof f === 'function') {
|
|
return fn.apply(null, [].slice.call(arguments));
|
|
} else {
|
|
throw new Error(str + ' requires function as argument');
|
|
}
|
|
} : undefined;
|
|
} catch (e) {}
|
|
});
|
|
}
|
|
/**
|
|
* wraps up build-in objects using a cloned copy
|
|
* protect object against overwriting
|
|
* @private
|
|
*/
|
|
|
|
|
|
function protectBuiltInObjects(context) {
|
|
;
|
|
['Object', 'Boolean', 'Symbol', 'Error', 'EvalError', 'InternalError', 'RangeError', 'ReferenceError', 'SyntaxError', 'TypeError', 'URIError', 'Number', 'Math', 'Date', 'String', 'RegExp', 'Array', 'Int8Array', 'Uint8Array', 'Uint8ClampedArray', 'Int16Array', 'Uint16Array', 'Int32Array', 'Uint32Array', 'Float32Array', 'Float64Array', 'Map', 'Set', 'WeakMap', 'WeakSet', 'ArrayBuffer', 'SharedArrayBuffer', 'Atomics', 'DataView', 'JSON', 'Promise', 'Generator', 'GeneratorFunction', 'Reflect', 'Proxy', 'Intl', 'Buffer'].forEach(function (str) {
|
|
try {
|
|
context[str] = _protect(str);
|
|
new context[str](); // eslint-disable-line no-new
|
|
} catch (e) {}
|
|
});
|
|
}
|
|
/**
|
|
* @private
|
|
*/
|
|
|
|
|
|
function _protect(str) {
|
|
try {
|
|
var type = new Function("return ".concat(str))(); // eslint-disable-line no-new-func
|
|
|
|
return type ? clones.classes(type) : undefined;
|
|
} catch (e) {}
|
|
} |