Skip to content

Commit 750202a

Browse files
committed
fix(checkver)!: Harden checkver script evaluation
Signed-off-by: Chawye Hsu <su+git@chawyehsu.com>
1 parent a7a7d34 commit 750202a

2 files changed

Lines changed: 37 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
- **core:** Give `dark` higher priority when use `Extract-DarkArchive` ([#6637](https://github.com/ScoopInstaller/Scoop/issues/6637))
3737
- **checkver:** Harden github checkver ([#6641](https://github.com/ScoopInstaller/Scoop/issues/6641))
3838
- **scoop-search:** Select latest search result semantically ([#6643](https://github.com/ScoopInstaller/Scoop/issues/6643))
39+
- **checkver:** Harden checkver script evaluation ([#6652](https://github.com/ScoopInstaller/Scoop/issues/6652))
3940

4041
### Code Refactoring
4142

bin/checkver.ps1

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,23 @@ function next($er) {
266266
Write-Host $er -ForegroundColor DarkRed
267267
}
268268

269+
function Get-CheckverScriptPrelude() {
270+
return @(
271+
'$ErrorActionPreference = "Stop"',
272+
'$ProgressPreference = "SilentlyContinue"',
273+
# Set allowed env vars, `SystemRoot` is required for irm/iwr
274+
'$allowedEnvs = @("SystemRoot","TEMP","TMP")',
275+
'Get-ChildItem Env: | Where-Object { $allowedEnvs -notcontains $_.Name } | Remove-Item',
276+
# Use `UseBasicParsing` for Invoke-WebRequest by default (WindowsPowerShell)
277+
'$PSDefaultParameterValues["Invoke-WebRequest:UseBasicParsing"] = $true',
278+
# Use ConstrainedLanguage language mode to restrict checkver.script capabilities
279+
'$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"',
280+
# Available variables/functions for checkver.script
281+
# - `$page`: the retrieved webpage content
282+
'$page = $using:page'
283+
)
284+
}
285+
269286
# wait for all to complete
270287
while ($in_progress -gt 0) {
271288
$ev = Wait-Event
@@ -318,12 +335,28 @@ while ($in_progress -gt 0) {
318335
$page = (New-Object System.IO.StreamReader($ms, (Get-Encoding $wc))).ReadToEnd()
319336
}
320337

338+
# checkver.script evaluation
321339
if ($script) {
322-
$page = Invoke-Command ([scriptblock]::Create($script -join "`r`n"))
323-
$source = 'the output of script'
340+
# Restrict the capability of accessing outer variables via `$using:`
341+
$tokens = $null
342+
$errors = $null
343+
$ast = [System.Management.Automation.Language.Parser]::ParseInput($script, [ref]$tokens, [ref]$errors)
344+
if ($ast.Find({ param($node) $node -is [System.Management.Automation.Language.UsingExpressionAst] }, $true)) {
345+
next 'checkver.script may not use $using:'
346+
continue
347+
}
348+
349+
$prelude = Get-CheckverScriptPrelude
350+
351+
$script = $prelude + @($script)
352+
$scriptBlock = [scriptblock]::Create($script -join "`n")
353+
354+
$page = (Start-Job -ScriptBlock $scriptBlock | Receive-Job -Wait -AutoRemoveJob | Out-String).Trim()
355+
Write-Verbose "Output from evaluating checkver.script:`r`n$page"
356+
$source = 'the output of checkver.script'
324357
}
325358

326-
if ($null -eq $page) {
359+
if (!$page) {
327360
next "couldn't retrieve content from $source"
328361
continue
329362
}

0 commit comments

Comments
 (0)