From 5b86dbbf1750a3afa3a97e8b6d290ce4bc51a3cf Mon Sep 17 00:00:00 2001 From: ogt Date: Tue, 14 Jul 2026 22:01:54 +0800 Subject: [PATCH] fix(agent99): bound remote check command --- .../deploy-agent99-via-windows99-ssh.sh | 116 ++---------------- ...remote_atomic_deploy_transport_contract.py | 20 +++ 2 files changed, 29 insertions(+), 107 deletions(-) diff --git a/scripts/reboot-recovery/deploy-agent99-via-windows99-ssh.sh b/scripts/reboot-recovery/deploy-agent99-via-windows99-ssh.sh index 5f4b18d5d..b31f41e65 100755 --- a/scripts/reboot-recovery/deploy-agent99-via-windows99-ssh.sh +++ b/scripts/reboot-recovery/deploy-agent99-via-windows99-ssh.sh @@ -417,116 +417,18 @@ from pathlib import Path envelope = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8")) source_revision = envelope["sourceRevision"] manifest_sha256 = envelope["manifestSha256"] -fixed_names = [row["name"] for row in envelope["files"]] -fixed_rows = ",\n ".join("'" + name.replace("'", "''") + "'" for name in fixed_names) stage_identity = f"check||||{source_revision}" stage_token = hashlib.sha256(stage_identity.encode("utf-8")).hexdigest()[:20] -script = r'''$ErrorActionPreference = "Stop" -$agentRoot = "C:\Wooo\Agent99" -$binDir = Join-Path $agentRoot "bin" -$manifestPath = Join-Path $agentRoot "state\runtime-manifest.json" -$fixedFiles = @( - __FIXED_ROWS__ -) -$current = [pscustomobject]@{ - exists = $false - sourceRevision = "" - runtimeMatched = $false - recordedRuntimeMatched = $false - fileCount = 0 - mismatchCount = -1 - recordedMismatchCount = -1 - parseError = "" -} -if (Test-Path -LiteralPath $manifestPath -PathType Leaf) { - try { - $manifest = Get-Content -LiteralPath $manifestPath -Raw | ConvertFrom-Json - $rows = @($manifest.files) - $byName = @{} - $shapeValid = [bool]($rows.Count -eq $fixedFiles.Count) - foreach ($row in $rows) { - $name = [string]$row.name - if (-not $name -or $byName.ContainsKey($name)) { - $shapeValid = $false - continue - } - $byName[$name] = $row - } - $actualMismatchCount = 0 - foreach ($name in $fixedFiles) { - if (-not $byName.ContainsKey($name)) { - $shapeValid = $false - $actualMismatchCount += 1 - continue - } - $recordedSha = ([string]$byName[$name].runtimeSha256).ToLowerInvariant() - $runtimePath = Join-Path $binDir $name - $actualSha = if (Test-Path -LiteralPath $runtimePath -PathType Leaf) { - (Get-FileHash -LiteralPath $runtimePath -Algorithm SHA256).Hash.ToLowerInvariant() - } else { - "missing" - } - if (-not $recordedSha -or $recordedSha -ne $actualSha) { - $actualMismatchCount += 1 - } - } - $runtimeMatched = [bool]( - $shapeValid -and - [bool]$manifest.runtimeMatched -and - [int]$manifest.fileCount -eq $fixedFiles.Count -and - [int]$manifest.mismatchCount -eq 0 -and - $actualMismatchCount -eq 0 - ) - $current = [pscustomobject]@{ - exists = $true - sourceRevision = [string]$manifest.sourceRevision - runtimeMatched = $runtimeMatched - recordedRuntimeMatched = [bool]$manifest.runtimeMatched - fileCount = [int]$manifest.fileCount - mismatchCount = $actualMismatchCount - recordedMismatchCount = [int]$manifest.mismatchCount - parseError = "" - } - } catch { - $current.exists = $true - $current.parseError = $_.Exception.GetType().Name - } -} -[pscustomobject]@{ - schemaVersion = "agent99_remote_atomic_deploy_receipt_v1" - status = "check_ready" - mode = "check" - sourceRevision = "__SOURCE_REVISION__" - expectedRuntimeFileCount = 14 - manifestSha256 = "__MANIFEST_SHA256__" - plannedStagingPath = "C:\Wooo\Agent99\deploy\remote-source-__STAGE_TOKEN__" - runtimeManifest = $current - livePreflight = [pscustomobject]@{ executed = $false; reason = "apply_only_after_validate_only" } - transportPayloadMode = "control_command_no_stdin" - transientTransportPayloadStored = $false - transientTransportPayloadDeletedBeforeReceiver = $false - transportPayloadContainsSecrets = $false - operationBoundaries = [pscustomobject]@{ - remoteWritePerformed = $false - liveRuntimeWritePerformed = $false - livePromotionAttempted = $false - livePromotionPerformed = $false - secretValueRead = $false - privateKeyValueRead = $false - tokenValueRead = $false - environmentSecretRead = $false - uiInteraction = $false - vmPowerChange = $false - hostReboot = $false - serviceRestart = $false - scheduledTaskRestart = $false - scheduledTaskModification = $false - } - nextSafeAction = "rerun_with_apply_and_trace_run_work_item_after_source_commit_and_transport_check" -} | ConvertTo-Json -Compress -Depth 8''' +script = r'''$ErrorActionPreference='Stop' +$a='C:\Wooo\Agent99';$b=Join-Path $a 'bin';$p=Join-Path $a 'state\runtime-manifest.json' +$r=[ordered]@{exists=$false;sourceRevision='';runtimeMatched=$false;recordedRuntimeMatched=$false;fileCount=0;mismatchCount=-1;recordedMismatchCount=-1;parseError=''} +if(Test-Path -LiteralPath $p -PathType Leaf){try{$m=Get-Content -LiteralPath $p -Raw|ConvertFrom-Json;$rows=@($m.files);$seen=@{};$bad=0;foreach($x in $rows){$n=[string]$x.name;if(!$n-or[IO.Path]::GetFileName($n)-ne$n-or$seen.ContainsKey($n)){$bad++;continue};$seen[$n]=1;$q=Join-Path $b $n;$h=if(Test-Path -LiteralPath $q -PathType Leaf){(Get-FileHash -LiteralPath $q -Algorithm SHA256).Hash.ToLowerInvariant()}else{'missing'};if(([string]$x.runtimeSha256).ToLowerInvariant()-ne$h){$bad++}};$r.exists=$true;$r.sourceRevision=[string]$m.sourceRevision;$r.recordedRuntimeMatched=[bool]$m.runtimeMatched;$r.fileCount=[int]$m.fileCount;$r.mismatchCount=$bad;$r.recordedMismatchCount=[int]$m.mismatchCount;$r.runtimeMatched=[bool]($m.runtimeMatched-and$m.fileCount-eq 14-and$m.mismatchCount-eq 0-and$rows.Count-eq 14-and$seen.Count-eq 14-and$bad-eq 0)}catch{$r.exists=$true;$r.parseError=$_.Exception.GetType().Name}} +$c=[ordered]@{executed=$false;ok=$false;exitCode=-1;errorType=''} +try{& powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File (Join-Path $b 'agent99-contract-check.ps1') -SourceRoot $b|Out-Null;$c.executed=$true;$c.exitCode=$LASTEXITCODE;$c.ok=[bool]($c.exitCode-eq 0)}catch{$c.executed=$true;$c.errorType=$_.Exception.GetType().Name} +$z=[ordered]@{};foreach($n in 'remoteWritePerformed,liveRuntimeWritePerformed,livePromotionAttempted,livePromotionPerformed,secretValueRead,privateKeyValueRead,tokenValueRead,environmentSecretRead,uiInteraction,vmPowerChange,hostReboot,serviceRestart,scheduledTaskRestart,scheduledTaskModification'.Split(',')){$z[$n]=$false} +[ordered]@{schemaVersion='agent99_remote_atomic_deploy_receipt_v1';status='check_ready';mode='check';sourceRevision='__SOURCE_REVISION__';expectedRuntimeFileCount=14;manifestSha256='__MANIFEST_SHA256__';plannedStagingPath='C:\Wooo\Agent99\deploy\remote-source-__STAGE_TOKEN__';runtimeManifest=[pscustomobject]$r;runtimeContract=[pscustomobject]$c;livePreflight=[ordered]@{executed=$false;reason='apply_only_after_validate_only'};transportPayloadMode='control_command_no_stdin';transientTransportPayloadStored=$false;transientTransportPayloadDeletedBeforeReceiver=$false;transportPayloadContainsSecrets=$false;operationBoundaries=$z;nextSafeAction='rerun_with_apply_and_trace_run_work_item_after_source_commit_and_transport_check'}|ConvertTo-Json -Compress -Depth 8''' script = ( - script.replace("__FIXED_ROWS__", fixed_rows) - .replace("__SOURCE_REVISION__", source_revision) + script.replace("__SOURCE_REVISION__", source_revision) .replace("__MANIFEST_SHA256__", manifest_sha256) .replace("__STAGE_TOKEN__", stage_token) ) diff --git a/scripts/reboot-recovery/tests/test_agent99_remote_atomic_deploy_transport_contract.py b/scripts/reboot-recovery/tests/test_agent99_remote_atomic_deploy_transport_contract.py index cca4b9e73..b4e5956b8 100644 --- a/scripts/reboot-recovery/tests/test_agent99_remote_atomic_deploy_transport_contract.py +++ b/scripts/reboot-recovery/tests/test_agent99_remote_atomic_deploy_transport_contract.py @@ -1,5 +1,6 @@ from __future__ import annotations +import base64 import os import re import shlex @@ -658,11 +659,30 @@ def test_check_mode_uses_bounded_control_command_without_ssh_stdin( assert result.returncode == 0, result.stderr assert '"status":"check_ready"' in result.stdout args = args_path.read_text(encoding="utf-8") + remote_command = args.splitlines()[-1] assert "BatchMode=yes" in args assert "StrictHostKeyChecking=yes" in args assert "PasswordAuthentication=no" in args assert "Administrator@192.168.0.99" in args assert str(identity) in args + assert len(remote_command) < 8191 + encoded_command = remote_command.split("-EncodedCommand ", 1)[1] + check_script = base64.b64decode(encoded_command).decode("utf-16le") + assert "agent99-contract-check.ps1" in check_script + assert "Get-FileHash" in check_script + assert "runtimeContract" in check_script + assert "remoteWritePerformed" in check_script + assert "$z[$n]=$false" in check_script + for write_command in ( + "New-Item", + "Set-Content", + "Add-Content", + "Out-File", + "Remove-Item", + "Move-Item", + "Copy-Item", + ): + assert write_command not in check_script stdin_bytes = int(bytes_path.read_text(encoding="utf-8")) assert stdin_bytes == 0