Harden Windows release mode harness
CI / tests-and-images (pull_request) Successful in 2m11s
Runner smoke test / runner-smoke (pull_request) Successful in 2s

This commit is contained in:
codex committed 2026-11-03 10:19:45 +03:00
1 parent 8748760594
commit 81ab7aac39
2 files changed
+65 -11

No files matched your search

@@ -4,15 +4,28 @@ param(
)
$ErrorActionPreference = 'Stop'
$repository = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path
$installerPath = Join-Path $PSScriptRoot 'install_windows_release_client.ps1'
$fixtureScript = Join-Path $PSScriptRoot 'test_windows_release_launcher.py'
$temporaryRoot = Join-Path ([IO.Path]::GetTempPath()) ('akyldash-bundle-mode-' + [guid]::NewGuid().ToString('N'))
$temporaryBase = [IO.Path]::GetFullPath([IO.Path]::GetTempPath())
$temporaryBase = [IO.Path]::GetFullPath((Resolve-Path -LiteralPath $temporaryBase).Path).TrimEnd('\')
$temporaryName = 'akyldash-bundle-mode-' + [guid]::NewGuid().ToString('N')
$temporaryRoot = [IO.Path]::Combine($temporaryBase, $temporaryName)
if (Test-Path -LiteralPath $temporaryRoot) { throw 'Temporary fixture directory already exists.' }
[void][IO.Directory]::CreateDirectory($temporaryRoot)
$temporaryRootItem = Get-Item -LiteralPath $temporaryRoot -Force
if (($temporaryRootItem.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0) {
throw 'Temporary fixture root must not be a reparse point.'
}
$temporaryRootCreated = $temporaryRootItem.CreationTimeUtc
$temporaryAclOwner = (Get-Acl -LiteralPath $temporaryRoot).Owner
$temporaryOwnerSid = ([Security.Principal.NTAccount]$temporaryAclOwner).Translate(
[Security.Principal.SecurityIdentifier]).Value
$currentSid = [Security.Principal.WindowsIdentity]::GetCurrent().User.Value
if ($temporaryOwnerSid -cne $currentSid) { throw 'Temporary fixture root is not owned by the current user.' }
$bundlePath = Join-Path $temporaryRoot 'fixture.zip'
try {
$fixtureOutput = & $PythonPath -E -s -S $fixtureScript --write-bundle-fixture $bundlePath
$fixtureOutput = & $PythonPath -B -E -s -S $fixtureScript --write-bundle-fixture $bundlePath
if ($LASTEXITCODE -ne 0) { throw 'The temporary packager fixture failed.' }
$fixture = ($fixtureOutput -join "`n") | ConvertFrom-Json
@@ -55,13 +68,14 @@ try {
$copy = $targetArchive.CreateEntry($entry.FullName, [System.IO.Compression.CompressionLevel]::NoCompression)
$copy.ExternalAttributes = $entry.ExternalAttributes
if (-not $changed) {
$copy.ExternalAttributes = [int]([long]0x81A0 -shl 16)
$copy.ExternalAttributes = [BitConverter]::ToInt32(
[BitConverter]::GetBytes([uint32]0x81A00000), 0)
$changed = $true
}
$input = $entry.Open()
$output = $copy.Open()
try { $input.CopyTo($output) }
finally { $output.Dispose(); $input.Dispose() }
$entryInput = $entry.Open()
$entryOutput = $copy.Open()
try { $entryInput.CopyTo($entryOutput) }
finally { $entryOutput.Dispose(); $entryInput.Dispose() }
}
if (-not $changed) { throw 'Packager fixture had no entries to mutate.' }
} finally { $targetArchive.Dispose(); $sourceArchive.Dispose() }
@@ -72,14 +86,45 @@ try {
$alteredArchive = [System.IO.Compression.ZipArchive]::new(
$alteredStream, [System.IO.Compression.ZipArchiveMode]::Read, $true)
try {
$alteredEntry = $alteredArchive.Entries[0]
$alteredMode = (([long]$alteredEntry.ExternalAttributes -shr 16) -band 0xFFFF)
if ($alteredMode -ne 0x81A0) { throw 'Altered ZIP fixture does not contain the intended unsafe mode.' }
$rejected = $false
try { Assert-ReceiverBundleEntryMode -Entry $alteredArchive.Entries[0] }
catch { $rejected = $true }
try { Assert-ReceiverBundleEntryMode -Entry $alteredEntry }
catch {
if ($_.Exception.Message -notmatch 'unsafe file mode') { throw }
$rejected = $true
}
if (-not $rejected) { throw 'Installer validator accepted an altered ZIP entry mode.' }
} finally { $alteredArchive.Dispose() }
} finally { $alteredStream.Dispose() }
Write-Output ("PASS: installer validator accepted the actual packager bundle for commit {0} (SHA-256 {1}) and rejected altered mode." -f $fixture.commit, $fixture.sha256)
} finally {
Remove-Item -LiteralPath $temporaryRoot -Recurse -Force
$expectedRoot = [IO.Path]::Combine($temporaryBase, $temporaryName)
$rootItem = Get-Item -LiteralPath $expectedRoot -Force
$resolvedRoot = [IO.Path]::GetFullPath((Resolve-Path -LiteralPath $expectedRoot).Path).TrimEnd('\')
if ([string]::Compare($resolvedRoot, $expectedRoot, [StringComparison]::OrdinalIgnoreCase) -ne 0 -or
[string]::Compare([IO.Path]::GetDirectoryName($resolvedRoot), $temporaryBase,
[StringComparison]::OrdinalIgnoreCase) -ne 0 -or
[string]::Compare([IO.Path]::GetFileName($resolvedRoot), $temporaryName,
[StringComparison]::OrdinalIgnoreCase) -ne 0 -or
($rootItem.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0 -or
$rootItem.CreationTimeUtc -ne $temporaryRootCreated) {
throw 'Refusing to remove a replaced, moved, or reparse temporary fixture directory.'
}
$aclOwner = (Get-Acl -LiteralPath $expectedRoot).Owner
$ownerSid = ([Security.Principal.NTAccount]$aclOwner).Translate(
[Security.Principal.SecurityIdentifier]).Value
if ($ownerSid -cne $temporaryOwnerSid -or $ownerSid -cne $currentSid) {
throw 'Refusing to remove a temporary fixture directory with a changed owner.'
}
foreach ($item in Get-ChildItem -LiteralPath $expectedRoot -Force -Recurse) {
$itemPath = [IO.Path]::GetFullPath($item.FullName)
if (($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0 -or
-not $itemPath.StartsWith($resolvedRoot + '\', [StringComparison]::OrdinalIgnoreCase)) {
throw 'Refusing to recursively remove a reparse or out-of-root fixture entry.'
}
}
[IO.Directory]::Delete($resolvedRoot, $true)
}
@@ -255,6 +255,15 @@ class WindowsReleaseBootstrapTests(unittest.TestCase):
self.assertIn("$current = $current.Parent", script)
self.assertIn("$ownerSid -notin @('S-1-5-18', 'S-1-5-32-544', $trustedInstaller)", script)
def test_windows_bundle_mode_harness_uses_safe_python_and_validates_cleanup_target(self):
harness = (ROOT / "infra/deploy/test_windows_release_bundle_mode.ps1").read_text(encoding="utf-8")
self.assertIn("-B -E -s -S", harness)
self.assertIn("$rootItem.CreationTimeUtc -ne $temporaryRootCreated", harness)
self.assertIn("$ownerSid -cne $temporaryOwnerSid", harness)
self.assertIn("[IO.FileAttributes]::ReparsePoint", harness)
self.assertIn("[IO.Directory]::Delete($resolvedRoot, $true)", harness)
self.assertIn("-not $itemPath.StartsWith($resolvedRoot + '\\'", harness)
def test_windows_tool_environment_discards_path_and_git_overrides(self):
environment = {
"PATH": r"C:\Users\attacker\bin",