From 011f80c9aa18551390aba88ffa3789fc6e9dad72 Mon Sep 17 00:00:00 2001 From: Matthew Watkins Date: Tue, 28 Jul 2026 15:54:05 +0100 Subject: [PATCH] Fix: Env-mediate expressions in run blocks zizmor's auditor persona reported 7 template-injection findings in testing.yaml: GitHub expressions expanded directly inside 'run:' blocks, where expansion happens before the shell sees the script and a crafted value could inject commands. Two steps were affected, both validating action outputs: the static fixture check and the dynamic-version check. Their outputs now travel through 'env:'. The dynamic step's variables are prefixed DYN_ so the version string and the dynamic_version flag stay distinguishable. The org-wide zizmor workflow now fails a run on any finding at any level, so these informational findings block every new pull request in this repository. zizmor offers an auto-fix for this audit, but it is marked unsafe and on inspection it is: it rewrites the expression in place, leaving it inside the original single quotes, where the shell will not expand it. The original was correct because GitHub expanded the template before the shell ever saw it. These edits were therefore written by hand, with double quotes, and follow the env-before-run shape already used elsewhere in this repository. No behavioural change: the same values reach the same commands. Zizmor now reports no findings for the repository. Co-authored-by: Claude Signed-off-by: Matthew Watkins --- .github/workflows/testing.yaml | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/.github/workflows/testing.yaml b/.github/workflows/testing.yaml index 2385bb2..42137ad 100644 --- a/.github/workflows/testing.yaml +++ b/.github/workflows/testing.yaml @@ -106,20 +106,23 @@ jobs: - name: "Validate action output: ${{ github.repository }}" shell: bash + env: + PROJECT_VERSION: ${{ steps.test.outputs.python_project_version }} + VERSION_SOURCE: ${{ steps.test.outputs.source }} + DYN_IS_DYNAMIC: ${{ steps.test.outputs.dynamic_version }} run: | # Validate Action Output - if [ "${{ steps.test.outputs.python_project_version }}" \ - = '0.0.1' ]; then + if [ "$PROJECT_VERSION" = '0.0.1' ]; then echo "Action returned the expected version ✅" else echo 'Unexpected return value for: python_project_version ❌' - echo "Returned: ${{ steps.test.outputs.python_project_version }}" + echo "Returned: $PROJECT_VERSION" echo 'Expected: 0.0.1' exit 1 fi # Source output must be the actual file path now, not the # version string (regression test for the previous copy-paste bug). - source='${{ steps.test.outputs.source }}' + source="$VERSION_SOURCE" case "$source" in *pyproject.toml) echo "Source output is correct ($source) ✅" @@ -131,7 +134,7 @@ jobs: ;; esac # Verify the new outputs are present and have expected values. - if [ "${{ steps.test.outputs.dynamic_version }}" != 'false' ]; then + if [ "$DYN_IS_DYNAMIC" != 'false' ]; then echo 'Expected dynamic_version=false for a static-version project ❌' exit 1 fi @@ -150,10 +153,14 @@ jobs: - name: "Validate dynamic version output" shell: bash + env: + DYN_VERSION: ${{ steps.test-dynamic.outputs.python_project_version }} + DYN_IS_DYNAMIC: ${{ steps.test-dynamic.outputs.dynamic_version }} + DYN_PROVIDER: ${{ steps.test-dynamic.outputs.dynamic_provider }} run: | - version='${{ steps.test-dynamic.outputs.python_project_version }}' - dynamic='${{ steps.test-dynamic.outputs.dynamic_version }}' - provider='${{ steps.test-dynamic.outputs.dynamic_provider }}' + version="$DYN_VERSION" + dynamic="$DYN_IS_DYNAMIC" + provider="$DYN_PROVIDER" if [ "$version" != 'dynamic' ] || [ "$dynamic" != 'true' ]; then echo 'Dynamic versioning not detected ❌' echo "version=$version dynamic_version=$dynamic"