From 255a84f2b80ee9109cb71877775ba73cdf442920 Mon Sep 17 00:00:00 2001 From: Sykez <276981287+Sykezzz@users.noreply.github.com> Date: Thu, 13 Aug 2026 16:01:01 -0500 Subject: [PATCH 1/2] fix(setup): abort rejected silent preflight Run the bounded signer inspection during wizard initialization and use Inno's silent abort path on rejection. This prevents PrepareToInstall error UI from keeping a very-silent Setup process alive. --- scripts/windows_setup.iss | 41 ++++++++++++++++++------------------ tests/test_build_profiles.py | 6 +++++- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/scripts/windows_setup.iss b/scripts/windows_setup.iss index eb8c70b..a4c7120 100644 --- a/scripts/windows_setup.iss +++ b/scripts/windows_setup.iss @@ -341,7 +341,11 @@ begin TrustCheck.Checked := False; ProgressReceipt := AddBackslash(FixedData) + 'updates\setup-progress.json'; - + if WizardSilent and (not RunSilentSignerPreflight) then + begin + Log('Refusing silent setup because the pinned identity is missing, lacks its private key, is untrusted, or its provider did not answer safely.'); + Abort; + end; end; function InitializeUninstall: Boolean; @@ -398,28 +402,25 @@ begin end; function PrepareToInstall(var NeedsRestart: Boolean): String; +begin + Result := ''; + if ExistingInstall then + Result := 'GamGUI is already installed. Open it or uninstall it before running Setup again.'; +end; + +function RunSilentSignerPreflight: Boolean; var Arguments: String; ResultCode: Integer; begin - Result := ''; - if ExistingInstall then - Result := 'GamGUI is already installed. Open it or uninstall it before running Setup again.' - else if WizardSilent then - begin - { Run the same read-only signer inspection used by the transactional backend - before expanding the large embedded profile. The backend repeats the check - immediately before any application file is copied or signed. } - ExtractTemporaryFile('gamgui-signer-preflight.ps1'); - ExtractTemporaryFile('gamgui-signer-preflight-runner.ps1'); - Arguments := '-NoProfile -NonInteractive -ExecutionPolicy Bypass -File ' + - AddQuotes(ExpandConstant('{tmp}\gamgui-signer-preflight-runner.ps1')) + - ' -SigningScript ' + AddQuotes(ExpandConstant('{tmp}\gamgui-signer-preflight.ps1')) + - ' -CertificateSha256 ' + AddQuotes(SilentSigner) + ' -TimeoutSeconds 15'; - if (not Exec('powershell.exe', Arguments, '', SW_HIDE, ewWaitUntilTerminated, ResultCode)) or - (ResultCode <> 0) then - Result := 'The pinned GamGUI Local identity is missing, does not have its private key, or is not trusted for this Windows user.'; - end; + ExtractTemporaryFile('gamgui-signer-preflight.ps1'); + ExtractTemporaryFile('gamgui-signer-preflight-runner.ps1'); + Arguments := '-NoProfile -NonInteractive -ExecutionPolicy Bypass -File ' + + AddQuotes(ExpandConstant('{tmp}\gamgui-signer-preflight-runner.ps1')) + + ' -SigningScript ' + AddQuotes(ExpandConstant('{tmp}\gamgui-signer-preflight.ps1')) + + ' -CertificateSha256 ' + AddQuotes(SilentSigner) + ' -TimeoutSeconds 15'; + Result := Exec('powershell.exe', Arguments, '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and + (ResultCode = 0); end; function InitializeSetup: Boolean; @@ -450,7 +451,7 @@ begin Result := False; Exit; end; - { PrepareToInstall runs the shared read-only signer inspection before the + { InitializeWizard runs the shared read-only signer inspection before the large embedded profile is expanded. The transactional backend repeats the exact check before copying or signing the application. } end; diff --git a/tests/test_build_profiles.py b/tests/test_build_profiles.py index 57d9ace..1d67714 100644 --- a/tests/test_build_profiles.py +++ b/tests/test_build_profiles.py @@ -136,8 +136,12 @@ def test_windows_setup_wizard_is_native_offline_and_fail_closed(): assert "Flags: dontcopy solidbreak" not in wizard assert wizard.count("deleteafterinstall solidbreak") == 2 assert "-TimeoutSeconds 15" in wizard - assert "before expanding the large embedded profile" in wizard + assert "before Setup expands either profile" in wizard assert "The transactional backend repeats the" in wizard + assert "function RunSilentSignerPreflight: Boolean;" in wizard + assert "if WizardSilent and (not RunSilentSignerPreflight) then" in wizard + assert "Abort;" in wizard + assert "The pinned GamGUI Local identity is missing" not in wizard assert "-TrustMode Pretrusted -PretrustedSignerSha256" in wizard assert "GetEnv('CI')" not in wizard assert "Refusing a validation-only signer switch in public Setup" in wizard From 3efc946137eeb96c2034476a3c26844183bc3ede Mon Sep 17 00:00:00 2001 From: Sykez <276981287+Sykezzz@users.noreply.github.com> Date: Thu, 13 Aug 2026 16:04:01 -0500 Subject: [PATCH 2/2] fix(setup): declare silent preflight before wizard Expose the bounded preflight to InitializeWizard in Pascal declaration order. The pinned Inno Setup 7.0.2 compiler now validates the complete installer script. --- scripts/windows_setup.iss | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/scripts/windows_setup.iss b/scripts/windows_setup.iss index a4c7120..bb99369 100644 --- a/scripts/windows_setup.iss +++ b/scripts/windows_setup.iss @@ -179,6 +179,8 @@ begin end; end; +function RunSilentSignerPreflight: Boolean; forward; + procedure OpenInstalledClick(Sender: TObject); var ErrorCode: Integer; @@ -348,6 +350,21 @@ begin end; end; +function RunSilentSignerPreflight: Boolean; +var + Arguments: String; + ResultCode: Integer; +begin + ExtractTemporaryFile('gamgui-signer-preflight.ps1'); + ExtractTemporaryFile('gamgui-signer-preflight-runner.ps1'); + Arguments := '-NoProfile -NonInteractive -ExecutionPolicy Bypass -File ' + + AddQuotes(ExpandConstant('{tmp}\gamgui-signer-preflight-runner.ps1')) + + ' -SigningScript ' + AddQuotes(ExpandConstant('{tmp}\gamgui-signer-preflight.ps1')) + + ' -CertificateSha256 ' + AddQuotes(SilentSigner) + ' -TimeoutSeconds 15'; + Result := Exec('powershell.exe', Arguments, '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and + (ResultCode = 0); +end; + function InitializeUninstall: Boolean; begin Result := True; @@ -408,21 +425,6 @@ begin Result := 'GamGUI is already installed. Open it or uninstall it before running Setup again.'; end; -function RunSilentSignerPreflight: Boolean; -var - Arguments: String; - ResultCode: Integer; -begin - ExtractTemporaryFile('gamgui-signer-preflight.ps1'); - ExtractTemporaryFile('gamgui-signer-preflight-runner.ps1'); - Arguments := '-NoProfile -NonInteractive -ExecutionPolicy Bypass -File ' + - AddQuotes(ExpandConstant('{tmp}\gamgui-signer-preflight-runner.ps1')) + - ' -SigningScript ' + AddQuotes(ExpandConstant('{tmp}\gamgui-signer-preflight.ps1')) + - ' -CertificateSha256 ' + AddQuotes(SilentSigner) + ' -TimeoutSeconds 15'; - Result := Exec('powershell.exe', Arguments, '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and - (ResultCode = 0); -end; - function InitializeSetup: Boolean; begin Result := True;