Files
2026-07-13 12:46:20 +08:00

90 lines
2.6 KiB
JavaScript

const test = require('node:test')
const assert = require('node:assert/strict')
const childProcess = require('child_process')
const os = require('os')
const originalSpawn = childProcess.spawn
const originalPlatform = os.platform
const originalArch = os.arch
const originalNodeEnv = process.env.NODE_ENV
function loadFsForPlatform (platform) {
os.platform = () => platform
os.arch = () => 'x64'
process.env.NODE_ENV = 'development'
delete require.cache[require.resolve('../../src/app/lib/fs')]
delete require.cache[require.resolve('../../src/app/common/runtime-constants')]
return require('../../src/app/lib/fs').fsExport
}
test.afterEach(() => {
childProcess.spawn = originalSpawn
os.platform = originalPlatform
os.arch = originalArch
process.env.NODE_ENV = originalNodeEnv
delete require.cache[require.resolve('../../src/app/lib/fs')]
delete require.cache[require.resolve('../../src/app/common/runtime-constants')]
})
test('openFile passes malicious Windows filenames as a literal PowerShell argument', async () => {
let spawnCall
childProcess.spawn = (command, args, options) => {
spawnCall = { command, args, options }
return {
stderr: {
on: () => {}
},
on: (event, handler) => {
if (event === 'close') {
process.nextTick(() => handler(0))
}
},
unref: () => {}
}
}
const fsExport = loadFsForPlatform('win32')
await fsExport.openFile("C:\\Temp\\poc';Start-Process calc;#.txt")
assert.equal(spawnCall.command, 'powershell.exe')
assert.deepEqual(spawnCall.args.slice(0, 3), [
'-NoLogo',
'-NonInteractive',
'-Command'
])
assert.match(spawnCall.args[3], /Invoke-Item -LiteralPath \$path/)
assert.equal(
Buffer.from(spawnCall.options.env.ELECTERM_OPEN_FILE_PATH_B64, 'base64').toString('utf8'),
"C:\\Temp\\poc';Start-Process calc;#.txt"
)
assert.equal(spawnCall.options.windowsHide, true)
})
test('openFile passes malicious Unix filenames directly to open command', async () => {
let spawnCall
childProcess.spawn = (command, args, options) => {
spawnCall = { command, args, options }
return {
stderr: {
on: () => {}
},
on: (event, handler) => {
if (event === 'close') {
process.nextTick(() => handler(0))
}
},
unref: () => {}
}
}
const fsExport = loadFsForPlatform('darwin')
await fsExport.openFile('/tmp/poc";touch /tmp/pwn;#.txt')
assert.equal(spawnCall.command, 'open')
assert.deepEqual(spawnCall.args, ['/tmp/poc";touch /tmp/pwn;#.txt'])
assert.equal(spawnCall.options.detached, false)
})