Skip to content

Commit 25fbbe5

Browse files
committed
fix: sandbox breakout with console.constructor...
1 parent 1ff9411 commit 25fbbe5

File tree

3 files changed

+38
-9
lines changed

3 files changed

+38
-9
lines changed

src/common.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,17 @@ exports.createContext = function () {
4747
cloneFunctions(context)
4848
context.Buffer = _protect('Buffer')
4949
context.console = clones(console, console) // console needs special treatment
50+
context.console.constructor.constructor = 'function () {}'
5051
}
5152
if (hasWindow) {
5253
fillContext(window, true)
5354
cloneFunctions(context)
5455
protectBuiltInObjects(context)
5556
context.console = clones(console, console) // console needs special treatment
56-
context.Object.constructor.constructor = 'function () {}'
57+
try {
58+
context.Object.constructor.constructor = 'function () {}'
59+
} catch (e) {
60+
}
5761
}
5862

5963
return context
@@ -82,7 +86,7 @@ function cloneFunctions (context) {
8286
'clearTimeout'
8387
].forEach((str) => {
8488
try {
85-
let fn = new Function(`return ${str}`)() // eslint-disable-line no-new-func
89+
const fn = new Function(`return ${str}`)() // eslint-disable-line no-new-func
8690
context[str] = fn
8791
? function () {
8892
return fn.apply(null, [].slice.call(arguments))
@@ -97,7 +101,7 @@ function cloneFunctions (context) {
97101
'setTimeout'
98102
].forEach((str) => {
99103
try {
100-
let fn = new Function(`return ${str}`)() // eslint-disable-line no-new-func
104+
const fn = new Function(`return ${str}`)() // eslint-disable-line no-new-func
101105
context[str] = fn
102106
? function (f) {
103107
if (typeof f === 'function') {
@@ -175,7 +179,7 @@ function protectBuiltInObjects (context) {
175179
*/
176180
function _protect (str) {
177181
try {
178-
let type = new Function(`return ${str}`)() // eslint-disable-line no-new-func
182+
const type = new Function(`return ${str}`)() // eslint-disable-line no-new-func
179183
return type
180184
? clones.classes(type)
181185
: undefined

test/saferEval.spec.js

+28-3
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,9 @@ describe('#saferEval', function () {
8383
})
8484

8585
it('setInterval passing a function', function (done) {
86-
var res = saferEval('(function (){var id = setInterval(function () {Array._test = 111; console.log("intervall"); clearInterval(id)}, 5)}())')
87-
assert.strictEqual(res)
86+
var res = saferEval('(function (){var id = setInterval(function () {Array._test = 111; console.log("interval"); clearInterval(id)}, 5)})')
87+
assert.strictEqual(typeof res, 'function')
88+
res()
8889
setTimeout(function () {
8990
assert.strictEqual(Array._test, undefined)
9091
done()
@@ -270,6 +271,22 @@ describe('#saferEval', function () {
270271
}
271272
assert.strictEqual(res, undefined)
272273
})
274+
it('should not allow using console.constructor.constructor', function () {
275+
let res
276+
try {
277+
res = saferEval("console.constructor.constructor('return process')().env")
278+
} catch (e) {
279+
}
280+
assert.strictEqual(res, undefined)
281+
})
282+
it('should not allow using JSON.constructor.constructor', function () {
283+
let res
284+
try {
285+
res = saferEval("JSON.constructor.constructor('return process')().env")
286+
} catch (e) {
287+
}
288+
assert.strictEqual(res, undefined)
289+
})
273290
it('should prevent a breakout using Object.constructor', function () {
274291
let res
275292
try {
@@ -301,7 +318,15 @@ describe('#saferEval', function () {
301318
it('should not allow using Object.constructor.constructor', function () {
302319
let res
303320
try {
304-
res = saferEval("Object.constructor.constructor('return localStorage')()")
321+
res = saferEval("Object.constructor.constructor('return window')()")
322+
} catch (e) {
323+
}
324+
assert.strictEqual(res, undefined)
325+
})
326+
it('should not allow using console.constructor.constructor', function () {
327+
let res
328+
try {
329+
res = saferEval("console.constructor.constructor('return window')()")
305330
} catch (e) {
306331
}
307332
assert.strictEqual(res, undefined)

webpack.config.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ module.exports = {
66
devtool: 'source-map',
77
resolve: {
88
alias: {
9-
'src': path.resolve(__dirname, 'src'),
10-
'lib': path.resolve(__dirname, 'lib')
9+
src: path.resolve(__dirname, 'src'),
10+
lib: path.resolve(__dirname, 'lib')
1111
}
1212
},
1313
module: {

0 commit comments

Comments
 (0)