Skip to content

Instantly share code, notes, and snippets.

@hmmhmmhm
Last active April 7, 2022 18:21
Show Gist options
  • Select an option

  • Save hmmhmmhm/6613b4b844a46a54f6291d87f8d19151 to your computer and use it in GitHub Desktop.

Select an option

Save hmmhmmhm/6613b4b844a46a54f6291d87f8d19151 to your computer and use it in GitHub Desktop.
Lexical Free Smallest Sandbox
const outerLexicalEnvironment = {
window: {},
global: {},
Object: {},
Function: {},
self: {},
globalThis: {},
Error: {},
TypeError: {},
JSON: {},
Number: {},
String: {},
Array: {},
Date: {},
Boolean: {},
RegExp: {},
Proxy: {},
};
for (const key of Object.keys(self)) outerLexicalEnvironment[key] = {};
const outerLexicalEnvironmentList = Object.keys(outerLexicalEnvironment);
Object.freeze(outerLexicalEnvironment);
Object.freeze(outerLexicalEnvironmentList);
const sandbox = (code) => {
try {
let result;
with (outerLexicalEnvironment) {
function isObject(obj) {
return obj !== null && typeof obj === "object";
}
function setValue(obj, key, value) {
const keylist = key.split(".");
const e = keylist.shift();
if (keylist.length > 0) {
if (!isObject(obj[e])) obj[e] = {};
setValue(obj[e], keylist.join("."), value);
} else {
obj[key] = value;
return obj;
}
}
const obj1 = {};
setValue(obj1, "prototype.constructor", null);
setValue(obj1, "__proto__.constructor", null);
for (const item of outerLexicalEnvironmentList) {
try {
eval(
`${item}.constructor = null;${item}.prototype.constructor = null;${item}.__proto__.constructor = null;`
);
} catch (e) {}
}
const evalEnvironment = {
eval: function (code) {
return eval(
`function lock (code) { "use strict"; return eval(\`${code}\`) }; lock()`
);
},
};
result = evalEnvironment.eval(code);
}
return result;
} catch (e) {}
};
console.log(`window:`, sandbox("window"));
console.log(`"normal":`, sandbox('"normal"'));
console.log(`eval:`, sandbox("eval"));
console.log(`Object:`, sandbox("Object"));
console.log(`Function:`, sandbox("Function"));
console.log(
`const a = function () { return this }; a():`,
sandbox(`const a = function () { return this }; a()`)
);
console.log(
`const a = function () { return window }; a():`,
sandbox(`const a = function () { return window }; a()`)
);
console.log(`self: `, sandbox("self"));
console.log(
`const a = function () { return self }; a():`,
sandbox(`const a = function () { return self }; a()`)
);
console.log(`globalThis: `, sandbox("globalThis"));
console.log(
`sandbox(\`const fn = Error.__proto__.constructor; (new fn('return window'))()\`)`,
sandbox(`const fn = Error.__proto__.constructor; (new fn('return window'))()`)
);
console.log(
`sandbox(\`try { throw new Error() } catch (e) { console.log(e.__proto__.valueOf) }\`)`,
sandbox(
`try { throw new Error() } catch (e) { console.log(e.__proto__.valueOf) }`
)
);
sandbox(`(123).constructor.constructor`)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment