From b9ce3ea8965a69ed01cdb5f07f734da0e1569283 Mon Sep 17 00:00:00 2001 From: sagic-orca <125193594+sagic-orca@users.noreply.github.com> Date: Thu, 9 Oct 2025 14:15:24 +0300 Subject: [PATCH 1/3] feat: sign windows binary --- .github/workflows/gating.yaml | 44 ++++++++ install.ps1 | 194 +++++++++++++++++++++++++++++----- 2 files changed, 211 insertions(+), 27 deletions(-) diff --git a/.github/workflows/gating.yaml b/.github/workflows/gating.yaml index 3e989fd..4b55394 100644 --- a/.github/workflows/gating.yaml +++ b/.github/workflows/gating.yaml @@ -30,3 +30,47 @@ jobs: cat ./install.sh | bash -s orca-cli -h rm -rf /usr/local/bin/orca-cli + run_windows_downloader_script: + name: Run Windows Downloader Script with Signature Check + runs-on: windows-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Install Orca CLI and Verify Signature + shell: powershell + run: | + # Define the target directory for the installation + $InstallDir = "$env:TEMP\orca_cli_test_bin" + New-Item -ItemType Directory -Path $InstallDir -ErrorAction Stop + + Write-Host "Executing install-orca-cli.ps1 with signature verification..." + + # Execute the PowerShell installer script (using a known-good tag for testing) + # This script will attempt the signed download and verification first, then fallback to checksum if needed. + .\install-orca-cli.ps1 -binDir $InstallDir -ErrorAction Stop + + # Verification step: Ensure the executable exists and runs + $ExePath = Join-Path -Path $InstallDir -ChildPath "orca-cli.exe" + + if (-not (Test-Path $ExePath)) { + Write-Error "Orca CLI executable was not found at $ExePath after installation." + exit 1 + } + + Write-Host "Verifying installed binary by running --help..." + + # Change directory to the installation path and execute the installed binary + cd $InstallDir + .\orca-cli.exe --help | Out-Host + + - name: Cleanup Temporary Directory + # Ensure cleanup runs even if previous steps fail + if: always() + shell: powershell + run: | + $InstallDir = "$env:TEMP\orca_cli_test_bin" + if (Test-Path $InstallDir) { + Write-Host "Cleaning up test directory $InstallDir" + Remove-Item -Path $InstallDir -Recurse -Force -ErrorAction SilentlyContinue + } diff --git a/install.ps1 b/install.ps1 index 6d547be..9c08e7a 100644 --- a/install.ps1 +++ b/install.ps1 @@ -106,50 +106,190 @@ function Get-Architecture { } } -function Download-InstallOrcaCLI { + +function Test-AuthenticodeSignature { + param( + [string]$Path + ) + Write-Output "Verifying Authenticode digital signature on file: '$Path'" + + if (-not (Test-Path $Path)) { + Write-Warning "File not found at '$Path' for signature check." + return $false + } + + + $ExpectedSignerCN = "CN=Orca Security Inc." + $ExpectedIssuerCN = "CN=Sectigo Public Code Signing CA" + + + try { + $signature = Get-AuthenticodeSignature -FilePath $Path -ErrorAction Stop + $signerSubject = $signature.SignerCertificate.Subject + $signerIssuer = $signature.SignerCertificate.Issuer + + + if ($signature.Status -eq "Valid") { + # Check 1: Signer Subject (Owner) + $isSubjectValid = $signerSubject -like "*$ExpectedSignerCN*" + + # Check 2: Signer Issuer (CA) + # Use -like for flexibility, ensuring the expected CN is part of the full Issuer string + $isIssuerValid = $signerIssuer -like "*$ExpectedIssuerCN*" + + if ($isSubjectValid -and $isIssuerValid) { + # Changed Write-Output to Write-Host for colored text + Write-Host "Authenticode Signature is VALID and verified to be signed by Orca Security Inc." -ForegroundColor Green + Write-Host "Subject: $($signerSubject)" -ForegroundColor DarkGreen + Write-Host "Issuer: $($signerIssuer)" -ForegroundColor DarkGreen + return $true + } else { + Write-Warning "Authenticode Signature is VALID but verification FAILED (Owner or Issuer mismatch)." + + if (-not $isSubjectValid) { + Write-Warning "Owner Check Failed: Expected subject to contain '$ExpectedSignerCN', but found: $($signerSubject)" + } + if (-not $isIssuerValid) { + Write-Warning "Issuer Check Failed: Expected issuer to contain '$ExpectedIssuerCN', but found: $($signerIssuer)" + } + return $false + } + } else { + Write-Warning "Authenticode Signature check FAILED: $($signature.Status). $($signature.StatusMessage)" + return $false + } + } catch { + Write-Error "An error occurred during signature check. Fallback to checksum is necessary. Error: $($_.Exception.Message)" + return $false + } +} + + + function Download-InstallOrcaCLI { param( [string]$tag, [string]$binDir ) $arch = Get-Architecture - $tarballUrl = "https://github.com/orcasecurity/orca-cli/releases/download/$tag/orca-cli_$($tag)_windows_$arch.zip" - $checksumUrl = "https://github.com/orcasecurity/orca-cli/releases/download/$tag/orca-cli_$($tag)_checksums.txt" - Write-Output "Downloading orca-cli.exe, version: $($tag)" - $tempDirName = "orca-cli_temp_" + (Get-Random) $tempDir = New-Item -ItemType Directory -Path $env:TEMP -Name $tempDirName | Select-Object -ExpandProperty FullName Write-Output "Downloading files into $($tempDir)" + $zipFileName = "orca-cli_windows.zip" + $tarballFile = "$($tempDir)\$zipFileName" + $binexe = "orca-cli.exe" + # Path to the extracted executable file + $extractedExePath = "$($tempDir)\$binexe" + + $success = $false + + # --- ATTEMPT 1: Signed Binary Download, Extraction, and Authenticode Verification --- + $tarballUrlSigned = "https://github.com/orcasecurity/orca-cli/releases/download/$tag/orca-cli_$($tag)_windows_$($arch)_signed.zip" + Write-Output "Attempt 1: Trying to download digitally signed binary from: $($tarballUrlSigned)" + try { - Invoke-WebRequestInsecure -Uri $tarballUrl -OutFile "$($tempDir)\orca-cli_windows.zip" + # 1. Download Signed File (ZIP) + Invoke-WebRequestInsecure -Uri $tarballUrlSigned -OutFile $tarballFile + Write-Output "Signed binary ZIP downloaded successfully." + + # 2. Extract the EXE + Expand-Archive -Path $tarballFile -DestinationPath $tempDir -Force + Write-Output "ZIP extracted successfully. Checking signature on the executable..." + + # 3. Verify Signature on the *extracted EXE* + $signatureValid = Test-AuthenticodeSignature -Path $extractedExePath + + if ($signatureValid) { + # Installation is only performed if the EXE signature is valid + Write-Host "Digital signature is valid. Installing Orca CLI..." -ForegroundColor Green + Copy-Item -Path $extractedExePath -Destination $binDir -Force + Write-Host "Orca CLI (Signed) installed successfully to: $($binDir)\$binexe" -ForegroundColor Green + $success = $true + } else { + Write-Warning "Signature verification failed for the extracted binary. Proceeding to fallback." + # Clean up temporary files, specifically the contents of $tempDir + } + } catch { - Write-Error "Failed to download the binary. Please check your internet connection and ensure that the version/tag is correct." - return + Write-Warning "Attempt 1 failed (Download or Extraction/Initial Signature Check). Error: $($_.Exception.Message). Proceeding to fallback." } - try { - Invoke-WebRequestInsecure -Uri $checksumUrl -OutFile "$($tempDir)\orca-cli_windows_checksums.txt" - } catch { - Write-Error "Failed to download the checksum file. Please check your internet connection and ensure that the version/tag is correct." - return + # Ensure temporary files are clean before falling back, in case of partial success/failure + if (-not $success) { + Remove-Item -Path $tarballFile -Force -ErrorAction SilentlyContinue + # This cleans up the extracted exe and any other files + if (Test-Path $tempDir) { + Get-ChildItem -Path $tempDir -Recurse | Remove-Item -Force -ErrorAction SilentlyContinue + } } - # Use compatible hash function - Write-Output "Verifying SHA256 checksum..." - $hash = Get-FileHashCompat -Path "$($tempDir)\orca-cli_windows.zip" -Algorithm SHA256 - Write-Output "File hash: $($hash.Hash)" + + # --- ATTEMPT 2: Fallback to Checksum Verification (Original Flow) --- + if (-not $success) { + $success = $true + Write-Output "Attempt 2: Initiating fallback to unsigned binary and SHA256 checksum verification." + + $tarballUrlUnsigned = "https://github.com/orcasecurity/orca-cli/releases/download/$tag/orca-cli_$($tag)_windows_$($arch).zip" + $checksumUrl = "https://github.com/orcasecurity/orca-cli/releases/download/$tag/orca-cli_$($tag)_checksums.txt" + $checksumFile = "$($tempDir)\orca-cli_windows_checksums.txt" + + Write-Output "Downloading binary from: $($tarballUrlUnsigned)" + + try { + Invoke-WebRequestInsecure -Uri $tarballUrlUnsigned -OutFile $tarballFile + + } catch { + Write-Error "Failed to download the binary. Please check your internet connection and ensure that the version/tag is correct." + $success = $false + # Use 'break' logic by falling through to final cleanup + } + + if ($success -ne $false) { # Only proceed if the download above was successful + try { + Invoke-WebRequestInsecure -Uri $checksumUrl -OutFile $checksumFile + } catch { + Write-Error "Failed to download the checksum file. Cannot verify integrity." + $success = $false + # Use 'break' logic by falling through to final cleanup + } + + if ($success -ne $false) { + # Use compatible hash function + Write-Output "Verifying SHA256 checksum..." + $hash = Get-FileHashCompat -Path $tarballFile -Algorithm SHA256 + Write-Output "File hash: $($hash.Hash)" + + # Check if the calculated hash exists in the checksum file + if ((Get-Content $checksumFile) -match $hash.Hash) { + # Changed Write-Output to Write-Host for correct console coloring + Write-Host "SHA256 verification successful" -ForegroundColor Green + + # Extract and copy for the checksum flow + Expand-Archive -Path $tarballFile -DestinationPath $tempDir -Force + Copy-Item -Path $extractedExePath -Destination $binDir -Force + + # Changed Write-Output to Write-Host for correct console coloring + Write-Host "Orca CLI (Checksum Verified) installed successfully to: $($binDir)\$binexe" -ForegroundColor Green + $success = $true + } else { + Write-Error "SHA256 verification FAILED for $($tarballFile). The downloaded file is corrupt or untrustworthy." + $success = $false + } + } + } + } - if ((Get-Content "$($tempDir)\orca-cli_windows_checksums.txt") -match $hash.Hash) { - Write-Output "SHA256 verification successful" - Expand-Archive -Path "$($tempDir)\orca-cli_windows.zip" -DestinationPath $tempDir - $binexe = "orca-cli.exe" - Copy-Item -Path "$($tempDir)\$binexe" -Destination $binDir -Force - Write-Output "Orca CLI installed successfully - $($binDir)\$binexe" - } else { - Write-Error "SHA256 verification failed for $($tempDir)\orca-cli_windows.zip" + # Final Cleanup + if (Test-Path $tempDir) { + Remove-Item -Path $tempDir -Force -Recurse -ErrorAction SilentlyContinue } - Remove-Item -Path $tempDir -Force -Recurse -} + + if (-not $success) { + Write-Error "Installation failed after both signed and checksum attempts." + exit 1 + } +} + # Check PowerShell version and warn if too old Write-Output "PowerShell Version: $($PSVersionTable.PSVersion)" From 870794ddaee4dfb88e67d6c586faf946e04aee1c Mon Sep 17 00:00:00 2001 From: sagic-orca <125193594+sagic-orca@users.noreply.github.com> Date: Thu, 9 Oct 2025 14:17:56 +0300 Subject: [PATCH 2/3] fix: gating windows installation --- .github/workflows/gating.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gating.yaml b/.github/workflows/gating.yaml index 4b55394..4c98709 100644 --- a/.github/workflows/gating.yaml +++ b/.github/workflows/gating.yaml @@ -44,11 +44,11 @@ jobs: $InstallDir = "$env:TEMP\orca_cli_test_bin" New-Item -ItemType Directory -Path $InstallDir -ErrorAction Stop - Write-Host "Executing install-orca-cli.ps1 with signature verification..." + Write-Host "Executing install.ps1 with signature verification..." # Execute the PowerShell installer script (using a known-good tag for testing) # This script will attempt the signed download and verification first, then fallback to checksum if needed. - .\install-orca-cli.ps1 -binDir $InstallDir -ErrorAction Stop + .\install.ps1 -binDir $InstallDir -ErrorAction Stop # Verification step: Ensure the executable exists and runs $ExePath = Join-Path -Path $InstallDir -ChildPath "orca-cli.exe" From ca7c62a4759d30b42c877c055d12f8e8c765ab43 Mon Sep 17 00:00:00 2001 From: sagic-orca <125193594+sagic-orca@users.noreply.github.com> Date: Sun, 12 Oct 2025 15:11:48 +0300 Subject: [PATCH 3/3] fixing CR comments --- install.ps1 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/install.ps1 b/install.ps1 index 9c08e7a..1e12dc6 100644 --- a/install.ps1 +++ b/install.ps1 @@ -226,7 +226,6 @@ function Test-AuthenticodeSignature { # --- ATTEMPT 2: Fallback to Checksum Verification (Original Flow) --- if (-not $success) { - $success = $true Write-Output "Attempt 2: Initiating fallback to unsigned binary and SHA256 checksum verification." $tarballUrlUnsigned = "https://github.com/orcasecurity/orca-cli/releases/download/$tag/orca-cli_$($tag)_windows_$($arch).zip" @@ -237,7 +236,7 @@ function Test-AuthenticodeSignature { try { Invoke-WebRequestInsecure -Uri $tarballUrlUnsigned -OutFile $tarballFile - + $success = $true } catch { Write-Error "Failed to download the binary. Please check your internet connection and ensure that the version/tag is correct." $success = $false