Reject Actions run steps that inline a program body #990

Merged
coilysiren merged 1 commit from aos/claude/ck67 into main 2026-08-10 03:05:56 +00:00
Owner

Closes #989.

The gap

actions-run-one-line's description says to move script bodies into tracked
language-native files. The checker enforced only the one-line half, so a step
could inline an arbitrarily large program as long as it was one physical line.

What now fails

A run: fails when it:

  • passes an inline source string to python, node, ruby, perl, or a shell through -c, -e, -E, -p, --eval, --exec, or --print, and that string carries an escaped newline or exceeds MAX_INLINE_BODY_CHARS (100)
  • opens a heredoc

Short direct one-liners still pass (python3 -c 'import sys; print(sys.version_info[0])', node -e 'console.log(process.version)'), as do printf 'a\nb\n', herestrings, and $(( 1 << 3 )). Detection splits with shlex so the body is measured exactly, and falls back to a tail regex when the command quoting is unbalanced. Both paths are covered by tests.

This repo's own instances

12 steps across 6 workflows carried the same ~50-line inlined Telegram alert, all byte-identical, including one on aos-cli-release labelled "release failure" that still said "CI failed on main". They now call ./actions/telegram-alert, the composite action this repo already ships and tests, so the alert is one program rather than 13.

I diffed the parsed workflow semantics before and after: triggers, runs-on, uses, if, env, and continue-on-error are identical across all 8 workflows apart from those step bodies. Every affected job already ran actions/checkout, which the local action needs.

ward exec pre-commit-all and uv run pytest (522 tests) pass.

Not covered here

coilyco-bridge/deploy is swept by its own PR #338. Four other checkouts still carry the same inlined body and are filed separately: infrastructure (5), agentic-os-kai (4), agentic-os-hardware (1), agentic-os-xxx (1). The tightening only bites them when each bumps its aos-precommit ref.

Not merging. .ward/ward.yaml declares workflow: pull-request-and-merge.

Closes #989. ## The gap `actions-run-one-line`'s description says to move script bodies into tracked language-native files. The checker enforced only the one-line half, so a step could inline an arbitrarily large program as long as it was one physical line. ## What now fails A `run:` fails when it: * passes an inline source string to `python`, `node`, `ruby`, `perl`, or a shell through `-c`, `-e`, `-E`, `-p`, `--eval`, `--exec`, or `--print`, and that string carries an escaped newline or exceeds `MAX_INLINE_BODY_CHARS` (100) * opens a heredoc Short direct one-liners still pass (`python3 -c 'import sys; print(sys.version_info[0])'`, `node -e 'console.log(process.version)'`), as do `printf 'a\nb\n'`, herestrings, and `$(( 1 << 3 ))`. Detection splits with `shlex` so the body is measured exactly, and falls back to a tail regex when the command quoting is unbalanced. Both paths are covered by tests. ## This repo's own instances 12 steps across 6 workflows carried the same ~50-line inlined Telegram alert, all byte-identical, including one on `aos-cli-release` labelled "release failure" that still said "CI failed on main". They now call `./actions/telegram-alert`, the composite action this repo already ships and tests, so the alert is one program rather than 13. I diffed the parsed workflow semantics before and after: triggers, `runs-on`, `uses`, `if`, `env`, and `continue-on-error` are identical across all 8 workflows apart from those step bodies. Every affected job already ran `actions/checkout`, which the local action needs. `ward exec pre-commit-all` and `uv run pytest` (522 tests) pass. ## Not covered here `coilyco-bridge/deploy` is swept by its own PR #338. Four other checkouts still carry the same inlined body and are filed separately: infrastructure (5), agentic-os-kai (4), agentic-os-hardware (1), agentic-os-xxx (1). The tightening only bites them when each bumps its `aos-precommit` ref. Not merging. `.ward/ward.yaml` declares `workflow: pull-request-and-merge`.
feat(pre-commit): reject Actions run steps that inline a program body
All checks were successful
ci / aos-cli-tests (pull_request) Successful in 41s
ci / gate (pull_request) Successful in 1m11s
ci / ward-doctor (pull_request) Successful in 2m42s
9465a2b278
actions-run-one-line enforced only the first half of its own description.
A step could carry an arbitrarily large program as long as it was one
physical line, so `python3 -c 'exec("...")'` passed while being unreadable
by ruff, shellcheck, review, and git diff.

The hook now also fails a run that passes a long or escaped-newline source
string to python/node/ruby/perl/a shell through -c, -e, -E, -p, --eval,
--exec, or --print, or that opens a heredoc. Short direct one-liners and
file-invoking commands still pass.

Sweeps this repo's own 12 inlined copies of the Telegram alert onto the
composite action it already ships at ./actions/telegram-alert. Parsed
workflow semantics are identical apart from those step bodies.

Closes #989

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
coilysiren deleted branch aos/claude/ck67 2026-08-10 03:05:56 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/agentic-os!990
No description provided.