mirror of
https://github.com/nesquena/hermes-webui.git
synced 2026-05-26 03:30:36 +00:00
fix(start.ps1): TryParse HERMES_WEBUI_PORT + exit AFTER try/finally cleanup
Two hardening fixes for start.ps1 — both flagged by Copilot's review on PR #2806, both touching lines that exist in #2783's scope rather than #2806's docs change, so split into this focused follow-up PR per the "keep diffs focused" guidance. ## Fix 1: TryParse on HERMES_WEBUI_PORT Before: $PortFinal = if ($Port) { $Port } elseif ($env:HERMES_WEBUI_PORT) { [int]$env:HERMES_WEBUI_PORT } else { 8787 } `[int]$env:HERMES_WEBUI_PORT` throws InvalidCastException with no actionable context when the env var contains a non-integer value (typo, accidental shell expansion, etc.). The cast also doesn't range-check — HERMES_WEBUI_PORT=999999 would pass the cast and then fail at the network layer with a confusing port-out-of-range error from Python's socket.bind(). After: explicit TryParse + range guard (1-65535), each failure mode gets a targeted Write-Error naming the offending value and the remedy: HERMES_WEBUI_PORT='abc' is not a valid integer port. Unset the variable to use the default (8787), or set it to a number 1-65535. HERMES_WEBUI_PORT=99999 is out of TCP-port range. Must be 1-65535. ## Fix 2: exit AFTER try/finally cleanup Before: Push-Location $RepoRoot try { & $Python $serverPath @args exit $LASTEXITCODE } finally { Pop-Location } `exit` inside the `try` block can prevent the `finally` from running in some termination paths (notably when the script is dot-sourced or invoked from an interactive PowerShell session). The result is a caller stuck at $RepoRoot instead of their original working directory. After: capture the exit code into a scoped variable, let the finally run cleanup, exit after the try/finally completes: $script:serverExitCode = 0 Push-Location $RepoRoot try { & $Python $serverPath @args $script:serverExitCode = $LASTEXITCODE } finally { Pop-Location } exit $script:serverExitCode ## Smoke test Verified all three port-error paths against the modified script on a Windows 11 Pro foundry-side workstation (PowerShell 7.5.4): Test A: HERMES_WEBUI_PORT='abc' -> exit 1 + 'not a valid integer port' PASS Test B: HERMES_WEBUI_PORT='99999' -> exit 1 + 'out of TCP-port range' PASS Test C: HERMES_WEBUI_PORT='0' -> exit 1 + 'out of TCP-port range' PASS Test environment used HERMES_WEBUI_AGENT_DIR override to bypass agent- discovery (this branch is based on #2783's 2-path candidate list which doesn't include the LOCALAPPDATA install path that #2805 adds; the hardening fix itself is orthogonal to discovery). Stacks on top of #2783. Once #2783 lands, rebases cleanly onto master. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -119,7 +119,26 @@ if (Test-Path $agentVenvPython) {
|
||||
|
||||
# === Resolve bind + state defaults =====================================
|
||||
$BindHostFinal = if ($BindHost) { $BindHost } elseif ($env:HERMES_WEBUI_HOST) { $env:HERMES_WEBUI_HOST } else { '127.0.0.1' }
|
||||
$PortFinal = if ($Port) { $Port } elseif ($env:HERMES_WEBUI_PORT) { [int]$env:HERMES_WEBUI_PORT } else { 8787 }
|
||||
$PortFinal = if ($Port) {
|
||||
$Port
|
||||
} elseif ($env:HERMES_WEBUI_PORT) {
|
||||
# TryParse + range guard on the env var. A plain [int] cast on the
|
||||
# env var throws InvalidCastException with no actionable context when
|
||||
# the env var is set to a non-integer (typo, accidental shell
|
||||
# expansion, etc.) — surface a targeted error message instead.
|
||||
$parsedPort = 0
|
||||
if (-not [int]::TryParse($env:HERMES_WEBUI_PORT, [ref]$parsedPort)) {
|
||||
Write-Error "HERMES_WEBUI_PORT='$($env:HERMES_WEBUI_PORT)' is not a valid integer port. Unset the variable to use the default (8787), or set it to a number 1-65535."
|
||||
exit 1
|
||||
}
|
||||
if ($parsedPort -lt 1 -or $parsedPort -gt 65535) {
|
||||
Write-Error "HERMES_WEBUI_PORT=$parsedPort is out of TCP-port range. Must be 1-65535."
|
||||
exit 1
|
||||
}
|
||||
$parsedPort
|
||||
} else {
|
||||
8787
|
||||
}
|
||||
$env:HERMES_WEBUI_HOST = $BindHostFinal
|
||||
$env:HERMES_WEBUI_PORT = "$PortFinal"
|
||||
if (-not $env:HERMES_WEBUI_STATE_DIR) {
|
||||
@@ -147,10 +166,17 @@ if (-not (Test-Path $serverPath)) {
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Capture exit code, let finally{} run Pop-Location, exit AFTER the try.
|
||||
# Plain `exit $LASTEXITCODE` inside the try block can prevent the finally
|
||||
# from running in some termination paths (especially when dot-sourced or
|
||||
# in interactive sessions), leaving the caller's working directory stuck
|
||||
# at $RepoRoot.
|
||||
$script:serverExitCode = 0
|
||||
Push-Location $RepoRoot
|
||||
try {
|
||||
& $Python $serverPath @args
|
||||
exit $LASTEXITCODE
|
||||
$script:serverExitCode = $LASTEXITCODE
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
exit $script:serverExitCode
|
||||
|
||||
Reference in New Issue
Block a user