window などは上書きできないのでローカルスコープに同名変数を作って そのスコープでコードを実行する
const exec = (source) => {
const window = {}
const location = null
const self = null
eval(source)
}
exec(`
console.log(location)
console.log(window.location)
`)
// null
// undefined
document などから辿れるのでそれらも同じように隠す
これだと this から window を参照できる
exec(`
console.log((function() { return this })().location)
`)
use strict をつけて this が window にならないようにする
const exec = (source) => {
"use strict"
const window = {}
const location = null
const self = null
eval(source)
}
これでも Function 関数を使えばグローバルスコープの関数を作れるので location などにアクセスできる
exec(`
Function("console.log(location)")()
`)
単純に Function を null にしても リテラルから関数を作れる
const exec = (source) => {
"use strict"
const window = {}
const location = null
const self = null
const Function = null
eval(source)
}
exec(`
(function() {}).constructor("console.log(location)")()
`)
Function.prototype.constructor も隠す
Function.prototype.constructor = null
const exec = (source) => {
"use strict"
const window = {}
const location = null
const self = null
const Function = null
eval(source)
}
ジェネレータや async 関数も同じようにする
Worker のスコープでの実行も避けるので Worker も隠す
思いつく方法は使えなくできたけど これで完全?