From 8b88b3b60a7932c9baa61e4d60cc18fbd82d7d76 Mon Sep 17 00:00:00 2001 From: OrcaWin Date: Sat, 5 Sep 2026 21:54:37 -0700 Subject: [PATCH] fix(windows): drop no-op -ExecutionPolicy Bypass from -Command spawns (#17873) * fix(windows): drop no-op -ExecutionPolicy Bypass from -Command spawns Execution policy gates script *files* only; it has no effect on -Command. Measured on Windows 11: powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Restricted \ -Command "Write-Output 'COMMAND-RAN'" -> COMMAND-RAN, exit 0 So the switch bought nothing on these two call sites while contributing the highest-weighted token on the command lines Defender for Endpoint flags. Font enumeration returns a byte-identical family list with and without the switch (182 families, matching SHA-256), and the ACL script's argv behaves identically either way. Tests now assert the argv carries no -ExecutionPolicy/Bypass, and the secure-file assertions derive the script position from -Command instead of a fixed index so they cannot rot the next time the switch list moves. * refactor(windows): tighten -Command argv assertions and comments Review follow-ups on the -ExecutionPolicy Bypass removal: - powershellScriptArgs asserts the -Command anchor before slicing, so a -Command -> -File swap names the switch shape that moved instead of surfacing as a path mismatch several asserts later. - Collapse both no-op rationale comments to one line per AGENTS.md. --------- Co-authored-by: Orca Worker --- src/main/system-fonts.test.ts | 16 ++++++++++++++++ src/main/system-fonts.ts | 3 ++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/system-fonts.test.ts b/src/main/system-fonts.test.ts index 106129feb8f..548fabf5a73 100644 --- a/src/main/system-fonts.test.ts +++ b/src/main/system-fonts.test.ts @@ -70,6 +70,22 @@ describe('listSystemFontFamilies', () => { }) }) + it('spawns the Windows font script without an -ExecutionPolicy switch', async () => { + // Why: execution policy gates script *files*, never -Command, so the switch + // was a no-op -- and it is the highest-weighted token on the command lines + // Defender flags (#17858). + await withPlatform('win32', async () => { + runProcessMock.mockResolvedValue(ok('Consolas\n')) + const { listSystemFontFamilies } = await import('./system-fonts') + await listSystemFontFamilies() + + const args = runProcessMock.mock.calls[0]?.[0].args ?? [] + expect(args).toContain('-Command') + expect(args).not.toContain('-ExecutionPolicy') + expect(args).not.toContain('Bypass') + }) + }) + it('runs PowerShell by absolute path on Windows', async () => { // Why: a bare `powershell.exe` resolves against the child's PATH, which is // not the user's under Electron. Where policy has pruned the System32 entry diff --git a/src/main/system-fonts.ts b/src/main/system-fonts.ts index f841e22a579..73d5ef9f993 100644 --- a/src/main/system-fonts.ts +++ b/src/main/system-fonts.ts @@ -89,7 +89,8 @@ $fonts.Families | ForEach-Object { $_.Name } return execFileText( windowsPowerShellPath(), - ['-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-Command', script], + // Why: policy gates script *files*, not -Command, so the switch was a Defender-weighted no-op. + ['-NoProfile', '-NonInteractive', '-Command', script], 8 * 1024 * 1024 ).then((output) => uniqueSorted(