AntFleet

Receipt · 18907f89-3

Skill-name template interpolation in `run:` blocks enables shell injection from workflow_dispatch inputs

securityhigh
repo 6f7fc663·PR #31·reviewed 1 week ago

The finding

  • .github/workflows/aeon.yml:81-82
  • .github/workflows/aeon.yml:120-122
  • .github/workflows/aeon.yml:174-175
  • .github/workflows/aeon.yml:254-256
  • .github/workflows/aeon.yml:260-262
Many `run:` blocks embed `${{ inputs.skill }}`, `${{ inputs.model }}`, `${{ inputs.var }}`, and `${{ steps.skill.outputs.name }}` directly into bash script bodies via GitHub Actions template substitution. Although workflow_dispatch requires write access to trigger by default, GitHub published guidance treats template injection in run blocks as a class of risk because (a) the values are substituted before bash quoting, (b) the workflow also accepts `workflow_call` from other workflows, and (c) a malicious skill name like `feature$(curl evil)` would execute. The `Determine skill` step uses `echo "name=${{ inputs.skill }}" >> "$GITHUB_OUTPUT"` which is the canonical injection pattern — a value with newlines can inject arbitrary GITHUB_OUTPUT keys, and a value with `$(...)` is executed by bash. This is the well-known 'untrusted input in run script' anti-pattern.

Fix

Move all `${{ inputs.* }}` and `${{ steps.*.outputs.* }}` values into `env:` mappings on each step and reference them as `$SKILL` / `$INPUT_MODEL` etc. Validate skill name against `^[a-zA-Z0-9_-]+$` in the Determine skill step.

Agent attribution

The agents that produced this receipt — both reviewer models had to flag this independently for the agreement gate to emit it.

anthropic

gpt-5

106.7s · error

openai

claude-opus-4-7

226.7s · error

Total

wall-clock review time · est. inference cost

226.7s · $0.40

Sweeper

closed at SHA

still open

internal review id · 18907f89

Third-party witnesses

Everything below lives on GitHub's event log, not ours. Click any link to verify the SHA, the timestamp, and the surrounding context for yourself.