Files
orca/config/scripts/windows-bin-spawn-predicate.test.mjs
T
Jinwoo Hong c6548b98f4 test(scripts): widen the Windows shim ratchet to catch package bin spawns (#20285)
* Widen Windows shim ratchet to detect package bin spawns

Follow local program expressions into node_modules/.bin while preserving the existing literal check, roots, and allow-list. Document static-analysis limits and cover unsafe and resolver-based invocations.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb

* fix(scripts): fold dot segments before matching node_modules/.bin

The predicate joins call arguments textually, so a literal '..' segment hid a
path that resolves into node_modules/.bin at runtime. Folds '.' and '..' (and
Windows separators) first. A '..' that genuinely escapes .bin still does not
match.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb

* style(scripts): use .at(-1) in the dot-segment fold

oxlint's prefer-at rule; the repo-wide lint gate is an error, not a warning.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
2026-09-13 16:08:56 -04:00

71 lines
2.6 KiB
JavaScript

import { describe, expect, it } from 'vitest'
import { hasNodeModulesBinSpawn } from './windows-bin-spawn-predicate.mjs'
describe('node_modules bin spawn predicate', () => {
it.each(['spawn', 'spawnSync', 'execFile', 'execFileSync'])(
'catches %s through local aliases',
(method) => {
expect(
hasNodeModulesBinSpawn(`
const bin = path.join(root, 'node_modules', '.bin', 'oxfmt')
const program = bin
cp.${method}(program, ['--write', file])
`)
).toBe(true)
}
)
it.each([
"path.resolve(root, 'node_modules/.bin/oxfmt')",
'`' + '${root}/node_modules/.bin/oxfmt' + '`',
"root + '/node_modules/' + '.bin/oxfmt'",
"'C:\\\\repo\\\\node_modules\\\\.bin\\\\oxfmt'",
"enabled ? 'node_modules/.bin/oxfmt' : 'oxfmt'"
])('catches the path expression %s', (expression) => {
expect(hasNodeModulesBinSpawn(`execFileSync(${expression}, [])`)).toBe(true)
})
it.each([
"// spawnSync('node_modules/.bin/oxfmt', [])",
'const example = "spawnSync(\'node_modules/.bin/oxfmt\', [])"',
"const bin = path.join(root, 'node_modules', '.bin', 'oxfmt'); existsSync(bin)",
"spawnSync(process.execPath, ['node_modules/.bin/oxfmt'])",
"spawnSync('node_modules/.binary/oxfmt', [])",
"spawnSync('other_node_modules/.bin/oxfmt', [])",
`const invocation = resolveOxcCliInvocation('oxfmt', 'oxfmt', root)
execFileSync(invocation.command, [...invocation.prefixArgs, '--write', file])`,
'const a = b; const b = a; spawnSync(a, [])'
])('does not flag non-program paths or safe invocations: %s', (contents) => {
expect(hasNodeModulesBinSpawn(contents)).toBe(false)
})
it('folds dot segments, so a .. detour into node_modules/.bin is still caught', () => {
expect(
hasNodeModulesBinSpawn(
"import { execFileSync } from 'node:child_process'\n" +
"import path from 'node:path'\n" +
"execFileSync(path.join(root, 'node_modules', 'tools', '..', '.bin', 'oxfmt'), [])\n"
)
).toBe(true)
})
it('folds Windows-separator dot segments too', () => {
expect(
hasNodeModulesBinSpawn(
"import { execFileSync } from 'node:child_process'\n" +
"execFileSync('root\\\\node_modules\\\\tools\\\\..\\\\.bin\\\\oxfmt', [])\n"
)
).toBe(true)
})
it('does not fold a .. back into .bin when it escapes the directory', () => {
expect(
hasNodeModulesBinSpawn(
"import { execFileSync } from 'node:child_process'\n" +
"import path from 'node:path'\n" +
"execFileSync(path.join(root, 'node_modules', '.bin', '..', 'oxfmt', 'cli.js'), [])\n"
)
).toBe(false)
})
})