Skip to content

Release 0.5.1: security fixes and the Lazarus launcher #18

Release 0.5.1: security fixes and the Lazarus launcher

Release 0.5.1: security fixes and the Lazarus launcher #18

Workflow file for this run

name: lazarus-launcher
# The Lazarus launcher (pe/lazarus) on a stand-in stick, with Windows PowerShell 5.1 as in
# Lazarus PE: checks how tools are found and sorted, and renders screenshots to look at.
on:
push:
paths: ["pe/lazarus/**", "pe/launcher/**", "tests/lazarus/**", ".github/workflows/launcher.yml"]
pull_request:
paths: ["pe/lazarus/**", "pe/launcher/**", "tests/lazarus/**", ".github/workflows/launcher.yml"]
workflow_dispatch:
permissions:
contents: read
jobs:
launcher:
runs-on: windows-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0
with:
persist-credentials: false
- name: Stick detection (a tag planted on the PC's own disks must not win)
shell: powershell
run: |
$base = "$env:RUNNER_TEMP\find"
# P: the tag is a folder; Q: a tag file, but on a drive holding Windows; R: a real stick
New-Item -ItemType Directory -Force "$base\p\helix-boot.tag", "$base\q\Windows\System32\config", "$base\r\Apps" | Out-Null
Set-Content "$base\q\helix-boot.tag" 'tag'
Set-Content "$base\q\Windows\System32\config\SYSTEM" 'hive'
Set-Content "$base\r\helix-boot.tag" 'tag'
Set-Content "$base\r\Apps\LazarusStartup.cmd" "@echo %~1> `"$base\started-from.txt`""
subst P: "$base\p"; subst Q: "$base\q"; subst R: "$base\r"
$find = (Resolve-Path pe\launcher\FindStick.ps1).Path
function Check($want, $got, $what) { if ("$got" -ne $want) { throw "${what}: wanted '$want', got '$got'" } }
Check 'R:' (& $find -Letters P, Q, R -BusOf @{ P = 'USB'; Q = 'USB'; R = 'USB' }) 'USB drives with decoys'
Check '' (& $find -Letters P, Q, R -BusOf @{ P = 'USB'; Q = 'USB'; R = 'NVMe' }) 'tagged internal disk'
Check 'R:' (& $find -Letters P, Q, R -BusOf @{}) 'no bus information'
Check '' (& $find -Letters P, Q, R) "the runner's own bus information (subst drives aren't USB)"
# The PE's startup helper, for real: with FindStick, a tagged drive that isn't USB is not run
$spa = Resolve-Path pe\launcher\StartPortableApps.cmd
cmd /c "$spa"
if (Test-Path "$base\started-from.txt") { throw "StartPortableApps.cmd ran a script from a non-USB drive" }
# ...and without PowerShell's help (no FindStick.ps1 beside it), the fallback skips both decoys
New-Item -ItemType Directory -Force "$base\bare" | Out-Null
Copy-Item $spa "$base\bare\"
cmd /c "$base\bare\StartPortableApps.cmd"
Check 'R:' ((Get-Content "$base\started-from.txt" -ErrorAction SilentlyContinue) -join '').Trim() 'fallback scan'
subst P: /d; subst Q: /d; subst R: /d
'stick detection ok'
- name: Stand-in stick
shell: powershell
run: |
$stick = "$env:RUNNER_TEMP\stick"; $menu = "$env:RUNNER_TEMP\menu"
& .\tests\lazarus\Make-FakeStick.ps1 -Stick $stick -Menu $menu
Copy-Item -Recurse pe\lazarus "$stick\Apps\Lazarus"
- name: Tools found and sorted
shell: powershell
run: |
$stick = "$env:RUNNER_TEMP\stick"; $menu = "$env:RUNNER_TEMP\menu"
$out = "$env:RUNNER_TEMP\tools.json"
powershell -NoProfile -STA -ExecutionPolicy Bypass -File "$stick\Apps\Lazarus\LazarusLauncher.ps1" -StartMenu $menu -ListTo $out
if ($LASTEXITCODE) { throw "the launcher failed to list tools ($LASTEXITCODE)" }
$tools = Get-Content -Raw -Encoding UTF8 $out | ConvertFrom-Json
$tools | Sort-Object Category, Title | Format-Table Category, Title, Where, Icon, IconType -AutoSize | Out-String -Width 220
$fail = @()
function Expect([string]$title, [string]$category) {
$hit = @($tools | Where-Object Title -eq $title)
if ($hit.Count -ne 1) { $script:fail += "$title listed $($hit.Count) times (want once)" }
elseif ($hit[0].Category -ne $category) { $script:fail += "$title is in $($hit[0].Category), want $category" }
}
Expect 'CrystalDiskInfo' 'diagnostics' # Helix App, also in PortableApps: once
Expect 'HWiNFO' 'diagnostics' # Helix App, PortableApps and the Start menu
Expect 'Wise Data Recovery' 'recovery'
Expect 'AOMEI Backupper' 'backup' # Start menu folder Backup & Imaging
Expect 'WizTree' 'disk'
Expect 'Smart Defrag' 'disk'
Expect 'KeePassXC' 'security'
Expect 'PuTTY' 'network'
Expect 'Everything' 'utilities'
Expect 'Autoruns' 'diagnostics' # appinfo.ini in UTF-16
Expect 'Brave' 'network' # no appinfo.ini: one program at the top
foreach ($gone in 'PortableApps.com Platform', 'Narrator', 'Helix Apps', 'CommonFiles') {
if ($tools | Where-Object Title -eq $gone) { $fail += "$gone should be hidden" }
}
$sys = $tools | Where-Object Title -eq 'Sysinternals Suite'
if (-not $sys -or -not $sys.Description) { $fail += 'Sysinternals Suite has no description from apps.txt' }
if (@($tools | Where-Object { -not $_.Icon }).Count -gt 2) { $fail += 'too many tools without an icon' }
$wiz = $tools | Where-Object Title -eq 'WizTree'
if (-not $wiz -or $wiz.Icon -lt 64) { $fail += "a PortableApps icon didn't load (WizTree: $($wiz.Icon) px)" }
Expect 'Recuva' 'recovery' # renamed from rcvPortable; appinfo.ini in ANSI
$rcv = $tools | Where-Object Title -eq 'Recuva'
if ($rcv -and $rcv.Description -ne "Recover files with Recuva$([char]0xAE) portably") { $fail += "ANSI text misread: $($rcv.Description)" }
if ($tools | Where-Object Title -match 'Portable$') { $fail += 'a name still ends in Portable' }
if ($fail) { $fail | ForEach-Object { Write-Host "::error::$_" }; exit 1 }
"$(@($tools).Count) tools, all where they belong"
- name: Screenshots
shell: powershell
run: |
$stick = "$env:RUNNER_TEMP\stick"; $menu = "$env:RUNNER_TEMP\menu"
$shots = New-Item -ItemType Directory -Force screens
function Shot([string]$name, [string[]]$more) {
$argv = @('-NoProfile', '-STA', '-ExecutionPolicy', 'Bypass', '-File', "$stick\Apps\Lazarus\LazarusLauncher.ps1",
'-StartMenu', $menu, '-Screenshot', "$shots\$name.png")
if ($more) { $argv += $more }
$p = Start-Process powershell -ArgumentList $argv -PassThru -NoNewWindow -RedirectStandardError "$shots\$name.err.txt"
if (-not $p.WaitForExit(120000)) { Stop-Process -Id $p.Id -Force; throw "$name hung" }
Get-Content "$shots\$name.err.txt" -ErrorAction SilentlyContinue
if ($p.ExitCode -or -not (Test-Path "$shots\$name.png")) { throw "$name failed ($($p.ExitCode))" }
Remove-Item "$shots\$name.err.txt"
"$name.png $((Get-Item "$shots\$name.png").Length) bytes"
}
Shot '1-recovery'
Shot '2-diagnostics' @('-Category', 'diagnostics')
Shot '3-search-disk' @('-SearchText', 'disk')
Shot '4-system-info' @('-ShowInfo')
Shot '5-1366x768' @('-Width', '1366', '-Height', '768', '-Category', 'security')
Shot '6-ultrawide' @('-Width', '2560', '-Height', '1080', '-Category', 'network')
Shot '7-16x10' @('-Width', '1920', '-Height', '1200', '-Category', 'backup')
Shot '8-4x3' @('-Width', '1024', '-Height', '768', '-Category', 'utilities')
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: always()
with:
name: lazarus-launcher-screens
path: screens/