🐛 fix(ci): replace head_commit.message expression with git log (shell injection) #38

Merged
arcodange merged 1 commits from fix/ci-commit-msg-shell-injection into main 2026-05-05 07:29:41 +02:00
Owner

Symptom

Every CI run since PR #31 has failed at the same step:

/var/run/act/workflow/12.sh: line 34: syntax error: unexpected newline
❌  Failure - Main Update badges and version (multiple commits, single push)

Affected post-merge runs: #621 (PR #32), #622 (PR #33), #623 (PR #34), #624 (PR #35).

Root cause

The "Update badges and version" step did:

COMMIT_MSG="${{ github.event.head_commit.message }}"

${{ ... }} is interpolated literally into the rendered shell script before bash parses it. Any of the following in a commit body breaks the next line:

  • A backtick (treated as command substitution)
  • An unbalanced quote
  • A line that, after substitution, ends mid-token

Test/coverage/badge work itself is fine — the failure is purely cosmetic at the post-test step. But it pollutes CI history and triggers cancellations on chained workflows.

Fix

Read the same information from git log instead — no shell-injection surface:

COMMIT_MSG=$(git log -1 --pretty=%B)

This was already the fallback (added in PR #31 for workflow_dispatch). Promoting it to be the only path eliminates the bug class entirely.

Verification

  • paths-ignore for the workflow includes documentation/** and *.md — does NOT include .gitea/** ; this PR will trigger CI on its own merge → first signal of the fix working.
  • No other ${{ ... }} expansions feed shell variables in the workflow (the other 3 uses are inside contains() job-level conditions which are evaluated server-side as booleans).
  • The git log -1 --pretty=%B path was already exercised on every merge since PR #31 (the fallback hit on workflow_dispatch but the syntax error fired before reaching it on regular pushes).

Why it was missed

PR #31 fixed the empty-message case but kept the original expression as the primary path. The fall-through was for the harmless case (empty); the dangerous path (special-char body) was untouched. Verifier-skill style review (Dim C — test reliability) would flag this: "fix removes one branch of failure but leaves the other branch + adds no regression test for the failing case."

Follow-up worth tracking: add a CI smoke that asserts the workflow renders without act --validate errors on PRs touching .gitea/workflows/.

## Symptom Every CI run since PR #31 has failed at the same step: ``` /var/run/act/workflow/12.sh: line 34: syntax error: unexpected newline ❌ Failure - Main Update badges and version (multiple commits, single push) ``` Affected post-merge runs: #621 (PR #32), #622 (PR #33), #623 (PR #34), #624 (PR #35). ## Root cause The "Update badges and version" step did: ```bash COMMIT_MSG="${{ github.event.head_commit.message }}" ``` `${{ ... }}` is interpolated **literally** into the rendered shell script before bash parses it. Any of the following in a commit body breaks the next line: - A backtick (treated as command substitution) - An unbalanced quote - A line that, after substitution, ends mid-token Test/coverage/badge work itself is fine — the failure is purely cosmetic at the post-test step. But it pollutes CI history and triggers cancellations on chained workflows. ## Fix Read the same information from `git log` instead — no shell-injection surface: ```bash COMMIT_MSG=$(git log -1 --pretty=%B) ``` This was already the fallback (added in PR #31 for `workflow_dispatch`). Promoting it to be the only path eliminates the bug class entirely. ## Verification - [x] `paths-ignore` for the workflow includes `documentation/**` and `*.md` — does NOT include `.gitea/**` ; this PR will trigger CI on its own merge → first signal of the fix working. - [x] No other `${{ ... }}` expansions feed shell variables in the workflow (the other 3 uses are inside `contains()` job-level conditions which are evaluated server-side as booleans). - [x] The `git log -1 --pretty=%B` path was already exercised on every merge since PR #31 (the fallback hit on workflow_dispatch but the syntax error fired before reaching it on regular pushes). ## Why it was missed PR #31 fixed the empty-message case but kept the original expression as the primary path. The fall-through was for the harmless case (empty); the dangerous path (special-char body) was untouched. Verifier-skill style review (Dim C — test reliability) would flag this: "fix removes one branch of failure but leaves the other branch + adds no regression test for the failing case." Follow-up worth tracking: add a CI smoke that asserts the workflow renders without `act --validate` errors on PRs touching `.gitea/workflows/`.
arcodange added 1 commit 2026-05-05 07:29:32 +02:00
PR #31 added a fallback to git log -1 --pretty=%B for the workflow_dispatch
case (where head_commit.message is empty), but kept ${{ ... }} as the primary
source. That expression is interpolated literally into the rendered shell
script — so a commit body containing a backtick, an unbalanced quote, or even
just a newline at an unfortunate position breaks the line that follows.

Symptom: every PR since #31 has shown:
  /var/run/act/workflow/12.sh: line 34: syntax error: unexpected newline
    Failure - Main Update badges and version (multiple commits, single push)

Fix: skip the expression entirely. git log -1 --pretty=%B reads the same
information from the actual commit and has no shell-injection surface.
arcodange merged commit 7c5f11779e into main 2026-05-05 07:29:41 +02:00
arcodange deleted branch fix/ci-commit-msg-shell-injection 2026-05-05 07:29:42 +02:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: arcodange/dance-lessons-coach#38