-
Notifications
You must be signed in to change notification settings - Fork 34
feat(build): add actionlint and zizmor as required workflow security validation checks #352
Description
Summary
Add actionlint and zizmor as required workflow security validation checks on every PR that touches .github/workflows/**. This prevents recurrence of the script injection class of vulnerability (CWE-78) patched reactively in #350 / PR #351, and remediates the 8 remaining inputs.* interpolation instances across 3 workflow files.
Background
GitHub Actions evaluates ${{ expr }} template expressions server-side before the YAML is handed to the runner shell. When user-controlled values (branch names, PR titles, workflow inputs) are interpolated directly into run: blocks, an attacker can inject shell metacharacters to execute arbitrary commands in the runner context.
PR #351 (fixes #350) patched this in .github/workflows/create-release.yml by moving 4 expressions from inline run: text to step-level env: blocks. The same pattern (inputs.* directly in run:) remains in 3 other workflow files:
| File | Lines | Expression | Risk |
|---|---|---|---|
security-deployment.yml |
87, 88, 182, 183, 228 | inputs.max-age-days, inputs.break-build, inputs.iac-types |
Medium (write access required) |
application-matrix-builds.yml |
172, 178 | inputs.buildConfig, inputs.securityConfig (JSON blobs) |
High (JSON values embed shell metacharacters) |
resource-provider-pwsh-tests.yml |
78 | inputs.test-results-output |
Medium (write access required) |
Checkov (CKV_GHA_7) is configured in .checkov.yml with the github_actions framework active and no skips, but it does not produce line-level PR annotations and its CI invocation path is unconfirmed.
Acceptance Criteria
- A new reusable workflow
.github/workflows/workflow-lint.ymlis added that runsactionlint v1.7.12against all.github/workflows/*.ymlfiles - The workflow is triggered on
pull_requestandpushtomainwhen paths under.github/workflows/**change -
zizmor v1.23.1is added to the same workflow to upload SARIF findings to the GitHub Security tab viagithub/codeql-action/upload-sarif - The 8 remaining
inputs.*inrun:patterns are remediated (moved toenv:blocks) so the lint check passes without suppressions, OR each suppression is documented with justification - The workflow is called from
pr-validation.ymlas a required check
Implementation Notes
Recommended actionlint integration (binary install, no unverified third-party action):
- name: Install actionlint
shell: bash
run: |
ACTIONLINT_VERSION="1.7.12"
curl -sSfL \
"https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" \
-o /tmp/actionlint.tar.gz
tar -xzf /tmp/actionlint.tar.gz -C /tmp actionlint
sudo mv /tmp/actionlint /usr/local/bin/
rm /tmp/actionlint.tar.gz
- name: Run actionlint
shell: bash
run: actionlint -color .github/workflows/*.ymlzizmor SARIF integration:
- name: Run zizmor
shell: bash
run: zizmor --format sarif --output zizmor.sarif . || true
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@<pinned-sha>
with:
sarif_file: zizmor.sarif
category: zizmorRemediation pattern (same pattern as PR #351):
# Before (vulnerable)
run: |
VALUE="${{ inputs.some-input }}"
# After (safe)
env:
VALUE: ${{ inputs.some-input }}
run: |
echo "$VALUE"References
- Fixes remaining exposure after fix: script injection with untrusted input in create-release.yml #350 / PR fix(build): remediate script injection in create-release workflow #351 (create-release.yml remediation)
- GitHub Actions security hardening — Script injection
- actionlint — v1.7.12
- zizmor — v1.23.1
- CWE-78: Improper Neutralization of Special Elements used in an OS Command