mirror of
https://github.com/stablyai/orca.git
synced 2026-10-07 16:02:29 +00:00
Resolve Microsoft Store PowerShell App Execution Aliases to their real package executable before ConPTY spawn, while preserving explicit PowerShell choices and the existing fail-safe fallback chain.
199 lines
6.9 KiB
TypeScript
199 lines
6.9 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import {
|
|
getWindowsCmdPath,
|
|
resolveWindowsPowerShellExecutablePath,
|
|
resolveWindowsPowerShellSpawnChain
|
|
} from './windows-powershell-executable'
|
|
|
|
const WIN_ENV: NodeJS.ProcessEnv = {
|
|
ProgramW6432: 'C:\\Program Files',
|
|
'ProgramFiles(x86)': 'C:\\Program Files (x86)',
|
|
LOCALAPPDATA: 'C:\\Users\\dev\\AppData\\Local',
|
|
SystemRoot: 'C:\\Windows',
|
|
ComSpec: 'C:\\Windows\\System32\\cmd.exe'
|
|
}
|
|
|
|
const PWSH7 = 'C:\\Program Files\\PowerShell\\7\\pwsh.exe'
|
|
const PATH_PWSH7 = 'D:\\Tools\\PowerShell\\7\\pwsh.exe'
|
|
const WINDOWS_POWERSHELL = 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'
|
|
// The Microsoft Store App Execution Alias stub for pwsh — a zero-byte reparse
|
|
// point under WindowsApps that ConPTY's CreateProcessW rejects with error 5.
|
|
const PWSH_STORE_ALIAS = 'C:\\Users\\dev\\AppData\\Local\\Microsoft\\WindowsApps\\pwsh.exe'
|
|
const PWSH_STORE_EXE =
|
|
'C:\\Program Files\\WindowsApps\\Microsoft.PowerShell_7.6.3.0_x64__8wekyb3d8bbwe\\pwsh.exe'
|
|
|
|
describe('resolveWindowsPowerShellExecutablePath', () => {
|
|
it('returns null on non-Windows platforms', () => {
|
|
expect(
|
|
resolveWindowsPowerShellExecutablePath('pwsh.exe', {
|
|
platform: 'linux',
|
|
env: WIN_ENV,
|
|
isRealExecutable: () => true
|
|
})
|
|
).toBeNull()
|
|
})
|
|
|
|
it('resolves pwsh.exe to a real absolute path under Program Files', () => {
|
|
expect(
|
|
resolveWindowsPowerShellExecutablePath('pwsh.exe', {
|
|
platform: 'win32',
|
|
env: WIN_ENV,
|
|
isRealExecutable: (p) => p === PWSH7
|
|
})
|
|
).toBe(PWSH7)
|
|
})
|
|
|
|
it('repro: resolves pwsh.exe from a real PATH entry when standard roots miss', () => {
|
|
expect(
|
|
resolveWindowsPowerShellExecutablePath('pwsh.exe', {
|
|
platform: 'win32',
|
|
env: {
|
|
...WIN_ENV,
|
|
Path: [
|
|
'relative-tools',
|
|
'C:\\Users\\dev\\AppData\\Local\\Microsoft\\WindowsApps',
|
|
'D:\\Tools\\PowerShell\\7'
|
|
].join(';')
|
|
},
|
|
isRealExecutable: (p) => p === PATH_PWSH7
|
|
})
|
|
).toBe(PATH_PWSH7)
|
|
})
|
|
|
|
it('resolves powershell.exe to inbox System32 WindowsPowerShell', () => {
|
|
expect(
|
|
resolveWindowsPowerShellExecutablePath('powershell.exe', {
|
|
platform: 'win32',
|
|
env: WIN_ENV,
|
|
isRealExecutable: (p) => p === WINDOWS_POWERSHELL
|
|
})
|
|
).toBe(WINDOWS_POWERSHELL)
|
|
})
|
|
|
|
it('repro: never resolves pwsh.exe to the Store App Execution Alias stub', () => {
|
|
// Only the WindowsApps alias "exists"; a naive resolver would return it and
|
|
// ConPTY would fail with error code 5. The resolver must reject it.
|
|
const resolved = resolveWindowsPowerShellExecutablePath('pwsh.exe', {
|
|
platform: 'win32',
|
|
env: WIN_ENV,
|
|
isRealExecutable: (p) => p === PWSH_STORE_ALIAS
|
|
})
|
|
expect(resolved).toBeNull()
|
|
expect(resolved).not.toBe(PWSH_STORE_ALIAS)
|
|
})
|
|
|
|
it('repro: resolves a Store App Execution Alias to its real package executable', () => {
|
|
const resolved = resolveWindowsPowerShellExecutablePath('pwsh.exe', {
|
|
platform: 'win32',
|
|
env: {
|
|
...WIN_ENV,
|
|
Path: 'C:\\Users\\dev\\AppData\\Local\\Microsoft\\WindowsApps'
|
|
},
|
|
isRealExecutable: (p) => p === PWSH_STORE_EXE,
|
|
resolveAppExecutionAlias: (p) => (p === PWSH_STORE_ALIAS ? PWSH_STORE_EXE : null)
|
|
})
|
|
expect(resolved).toBe(PWSH_STORE_EXE)
|
|
})
|
|
|
|
it.each(['pwsh.exe', PWSH_STORE_ALIAS, 'C:\\Tools\\powershell.exe'])(
|
|
'rejects unsafe Store alias target %s',
|
|
(target) => {
|
|
const resolved = resolveWindowsPowerShellExecutablePath('pwsh.exe', {
|
|
platform: 'win32',
|
|
env: {
|
|
...WIN_ENV,
|
|
Path: 'C:\\Users\\dev\\AppData\\Local\\Microsoft\\WindowsApps'
|
|
},
|
|
isRealExecutable: (p) => p === target,
|
|
resolveAppExecutionAlias: (p) => (p === PWSH_STORE_ALIAS ? target : null)
|
|
})
|
|
expect(resolved).toBeNull()
|
|
}
|
|
)
|
|
|
|
it('returns null for pwsh when no real executable is found', () => {
|
|
expect(
|
|
resolveWindowsPowerShellExecutablePath('pwsh.exe', {
|
|
platform: 'win32',
|
|
env: WIN_ENV,
|
|
isRealExecutable: () => false
|
|
})
|
|
).toBeNull()
|
|
})
|
|
})
|
|
|
|
describe('resolveWindowsPowerShellSpawnChain', () => {
|
|
it('orders pwsh -> Windows PowerShell -> cmd.exe when all resolve', () => {
|
|
const chain = resolveWindowsPowerShellSpawnChain('pwsh.exe', {
|
|
platform: 'win32',
|
|
env: WIN_ENV,
|
|
isRealExecutable: (p) => p === PWSH7 || p === WINDOWS_POWERSHELL
|
|
})
|
|
expect(chain).toEqual([PWSH7, WINDOWS_POWERSHELL, WIN_ENV.ComSpec])
|
|
})
|
|
|
|
it('falls back to Windows PowerShell + cmd.exe when pwsh is only a Store alias', () => {
|
|
const chain = resolveWindowsPowerShellSpawnChain('pwsh.exe', {
|
|
platform: 'win32',
|
|
env: WIN_ENV,
|
|
// pwsh exists only as the alias stub (rejected); Windows PowerShell is real.
|
|
isRealExecutable: (p) => p === PWSH_STORE_ALIAS || p === WINDOWS_POWERSHELL
|
|
})
|
|
expect(chain).toEqual([WINDOWS_POWERSHELL, WIN_ENV.ComSpec])
|
|
expect(chain).not.toContain(PWSH_STORE_ALIAS)
|
|
})
|
|
|
|
it('uses the real Store package executable ahead of Windows PowerShell', () => {
|
|
const chain = resolveWindowsPowerShellSpawnChain('pwsh.exe', {
|
|
platform: 'win32',
|
|
env: {
|
|
...WIN_ENV,
|
|
Path: 'C:\\Users\\dev\\AppData\\Local\\Microsoft\\WindowsApps'
|
|
},
|
|
isRealExecutable: (p) => p === PWSH_STORE_EXE || p === WINDOWS_POWERSHELL,
|
|
resolveAppExecutionAlias: (p) => (p === PWSH_STORE_ALIAS ? PWSH_STORE_EXE : null)
|
|
})
|
|
expect(chain).toEqual([PWSH_STORE_EXE, WINDOWS_POWERSHELL, WIN_ENV.ComSpec])
|
|
})
|
|
|
|
it('orders PATH-resolved pwsh before Windows PowerShell when standard roots miss', () => {
|
|
const chain = resolveWindowsPowerShellSpawnChain('pwsh.exe', {
|
|
platform: 'win32',
|
|
env: {
|
|
...WIN_ENV,
|
|
Path: 'D:\\Tools\\PowerShell\\7'
|
|
},
|
|
isRealExecutable: (p) => p === PATH_PWSH7 || p === WINDOWS_POWERSHELL
|
|
})
|
|
expect(chain).toEqual([PATH_PWSH7, WINDOWS_POWERSHELL, WIN_ENV.ComSpec])
|
|
})
|
|
|
|
it('always ends with cmd.exe even when no PowerShell resolves', () => {
|
|
const chain = resolveWindowsPowerShellSpawnChain('powershell.exe', {
|
|
platform: 'win32',
|
|
env: WIN_ENV,
|
|
isRealExecutable: () => false
|
|
})
|
|
expect(chain).toEqual([WIN_ENV.ComSpec])
|
|
})
|
|
|
|
it('does not duplicate cmd.exe when ComSpec is missing', () => {
|
|
const chain = resolveWindowsPowerShellSpawnChain('powershell.exe', {
|
|
platform: 'win32',
|
|
env: { SystemRoot: 'C:\\Windows' },
|
|
isRealExecutable: () => false
|
|
})
|
|
expect(chain).toEqual(['C:\\Windows\\System32\\cmd.exe'])
|
|
})
|
|
})
|
|
|
|
describe('getWindowsCmdPath', () => {
|
|
it('prefers ComSpec when set', () => {
|
|
expect(getWindowsCmdPath(WIN_ENV)).toBe('C:\\Windows\\System32\\cmd.exe')
|
|
})
|
|
|
|
it('derives cmd.exe from SystemRoot when ComSpec is absent', () => {
|
|
expect(getWindowsCmdPath({ SystemRoot: 'D:\\Win' })).toBe('D:\\Win\\System32\\cmd.exe')
|
|
})
|
|
})
|