From 492b88fdb0877b6f436cbd58481df5e1dc0b843c Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sun, 6 Sep 2026 09:34:45 +0000 Subject: [PATCH 1/2] ci(windows): turn off Smart App Control on the Windows 11 test runners Smart App Control ships in evaluation mode on Windows 11. It hashes every unsigned executable on its first launch and asks the cloud for its reputation. That costs 2 to 3.5 seconds per bun build --compile output. bundler_compile.test.ts launches about 85 of those, so the file takes 220 to 290 seconds against the runner's 300 second per-file cap, and goes over it in the slower Azure regions. The runner turns the policy off at job start (it takes effect at once, no reboot). bootstrap.ps1 does the same for future image bakes. --- scripts/bootstrap.ps1 | 19 +++++++++++++++++++ scripts/runner.node.mjs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/scripts/bootstrap.ps1 b/scripts/bootstrap.ps1 index 42776496a344..85ef3d4ef671 100755 --- a/scripts/bootstrap.ps1 +++ b/scripts/bootstrap.ps1 @@ -665,6 +665,7 @@ function Install-Buildkite { function Optimize-System { Disable-Windows-Defender + Disable-Smart-App-Control Disable-Windows-Threat-Protection Disable-Windows-Services Disable-Power-Management @@ -680,6 +681,24 @@ function Disable-Windows-Defender { Add-MpPreference -ExclusionPath "C:\", "D:\" } +# Windows 11 ships Smart App Control in evaluation mode (Server has no such +# policy). It hashes every unsigned executable on its first launch and asks the +# cloud for its reputation: 2 to 3.5 seconds per `bun build --compile` output, +# which the compile test suites launch by the dozen. Defender exclusions do not +# cover it, and tamper protection does not guard this key. The change takes +# effect after `CiTool --refresh` or a reboot, and cannot be undone without a +# reinstall, which is fine for a CI image. +function Disable-Smart-App-Control { + $itemPath = "HKLM:\SYSTEM\CurrentControlSet\Control\CI\Policy" + if (Test-Path $itemPath) { + Write-Output "Disabling Smart App Control..." + Set-ItemProperty -Path $itemPath -Name "VerifiedAndReputablePolicyState" -Value 0 -Type DWORD + if (Get-Command CiTool -ErrorAction SilentlyContinue) { + CiTool --refresh -json | Out-Null + } + } +} + function Disable-Windows-Threat-Protection { $itemPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows Advanced Threat Protection" if (Test-Path $itemPath) { diff --git a/scripts/runner.node.mjs b/scripts/runner.node.mjs index 1ef7223d7010..d6d97e8d575a 100755 --- a/scripts/runner.node.mjs +++ b/scripts/runner.node.mjs @@ -3494,6 +3494,35 @@ function escapeXml(str) { .replace(/'/g, "'"); } +/** + * Windows 11 ships Smart App Control in evaluation mode. In that mode the kernel + * hashes every unsigned executable on its first launch and asks the cloud for + * its reputation, which costs 2 to 3.5 seconds for a 77 MB `bun build --compile` + * output. bundler_compile.test.ts launches about 85 of those, which puts the file + * at 220 to 290 seconds against the 300 second per-file cap. Turning the policy + * off takes effect at once and needs no reboot. scripts/bootstrap.ps1 does the + * same at image bake time; this covers images baked before that change. + */ +async function disableSmartAppControl() { + const script = [ + "$p = 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\CI\\Policy'", + "if (-not (Test-Path $p)) { exit 0 }", + "$state = (Get-ItemProperty $p).VerifiedAndReputablePolicyState", + "if ($null -eq $state -or $state -eq 0) { exit 0 }", + "Set-ItemProperty $p -Name VerifiedAndReputablePolicyState -Value 0 -Type DWord", + "if (Get-Command CiTool -ErrorAction SilentlyContinue) { CiTool --refresh -json | Out-Null }", + 'Write-Output "Smart App Control: state $state -> 0"', + ].join("; "); + const { ok, error } = await spawnSafe({ + command: "pwsh", + args: ["-NoProfile", "-Command", script], + timeout: 60_000, + }); + if (!ok) { + console.warn(`Failed to disable Smart App Control: ${error}`); + } +} + export async function main() { for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) { process.on(signal, () => onExit(signal)); @@ -3511,6 +3540,7 @@ export async function main() { "-Command", "Set-DnsClientServerAddress -InterfaceAlias 'Ethernet 4' -ServerAddresses ('8.8.8.8','8.8.4.4')", ]); + await disableSmartAppControl(); } let doRunTests = true; From 651369f7b17dad0249e5235f9bbd1a43427abd25 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sun, 6 Sep 2026 09:55:34 +0000 Subject: [PATCH 2/2] runner: only turn off Smart App Control on Buildkite agents CI=true alone also satisfies isCI, and the policy cannot be turned on again without a reinstall. --- scripts/runner.node.mjs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/runner.node.mjs b/scripts/runner.node.mjs index d6d97e8d575a..5bc184cc45cd 100755 --- a/scripts/runner.node.mjs +++ b/scripts/runner.node.mjs @@ -3502,8 +3502,12 @@ function escapeXml(str) { * at 220 to 290 seconds against the 300 second per-file cap. Turning the policy * off takes effect at once and needs no reboot. scripts/bootstrap.ps1 does the * same at image bake time; this covers images baked before that change. + * + * Only on Buildkite: the policy cannot be turned on again without a reinstall, + * so a developer's machine running with CI=true must not get this. */ async function disableSmartAppControl() { + if (!isBuildkite) return; const script = [ "$p = 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\CI\\Policy'", "if (-not (Test-Path $p)) { exit 0 }",