Skip to content

Commit 5aa26ce

Browse files
reberhardt7claude
andauthored
fix: Harden GHA workflows (#58)
* fix: harden GitHub Actions workflows against injection and over-permissioning - Fix template injection vulnerabilities by moving ${{ }} expressions from run: blocks into env: variables (9 instances across _docker-pipeline.yml and publish-docker.yml) - Replace `secrets: inherit` with explicit secret passing in publish-docker.yml; remove unnecessary secret passing from smoke-test.yml (push: false) - Add zizmor suppression comments for false-positive template-injection findings on docker/build-push-action context: input - Add .github/zizmor.yml to disable secrets-outside-env rule Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: add dependabot cooldown configuration to resolve zizmor findings Add default-days: 7 cooldown to all three dependabot update entries (docker x2, github-actions x1) to satisfy the dependabot-cooldown audit. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b22cb31 commit 5aa26ce

5 files changed

Lines changed: 43 additions & 17 deletions

File tree

.github/dependabot.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ updates:
1515
commit-message:
1616
prefix: "chore"
1717
include: "scope" # → chore(deps): bump trivy from 0.69.2 to 0.69.3
18+
cooldown:
19+
default-days: 7
1820

1921
# app_tests Dockerfile — same as above, plus golang and securego/gosec.
2022
- package-ecosystem: "docker"
@@ -27,6 +29,8 @@ updates:
2729
commit-message:
2830
prefix: "chore"
2931
include: "scope"
32+
cooldown:
33+
default-days: 7
3034

3135
# GitHub Actions — tracks all uses: ... action versions.
3236
- package-ecosystem: "github-actions"
@@ -39,3 +43,5 @@ updates:
3943
commit-message:
4044
prefix: "ci"
4145
include: "scope" # → ci(deps): bump actions/checkout from v3 to v4
46+
cooldown:
47+
default-days: 7

.github/workflows/_docker-pipeline.yml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ jobs:
113113
- name: 🔨 Build (load for testing)
114114
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
115115
with:
116+
# zizmor: ignore[template-injection] — safe: always hardcoded "." from same-repo callers; passed as array element to exec, not shell-interpolated
116117
context: ${{ inputs.context }}
117118
file: ${{ inputs.dockerfile }}
118119
load: true
@@ -132,18 +133,23 @@ jobs:
132133

133134
# ── Step 2: Smoke test ─────────────────────────────────────────────────
134135
- name: 🧪 Smoke test
136+
env:
137+
IMAGE_NAME: ${{ inputs.name }}
138+
CHECK_SET: ${{ inputs.check_set }}
135139
run: |
136140
bash ./scripts/smoke-test-docker.sh \
137141
--skip-build \
138-
--image-tag ${{ inputs.name }}:pipeline-test \
139-
--check-set ${{ inputs.check_set }}
142+
--image-tag "$IMAGE_NAME:pipeline-test" \
143+
--check-set "$CHECK_SET"
140144
141145
# ── Step 3: Integration test (main image only) ─────────────────────────
142146
- name: 🔬 Integration test
143147
if: inputs.name == 'socket-basics'
148+
env:
149+
IMAGE_NAME: ${{ inputs.name }}
144150
run: |
145151
bash ./scripts/integration-test-docker.sh \
146-
--image-tag ${{ inputs.name }}:pipeline-test
152+
--image-tag "$IMAGE_NAME:pipeline-test"
147153
148154
# ── Step 4: Push to registries (publish mode only) ─────────────────────
149155
# Docker Hub login happens here — after build and tests, immediately before
@@ -161,6 +167,7 @@ jobs:
161167
if: inputs.push
162168
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
163169
with:
170+
# zizmor: ignore[template-injection] — safe: always hardcoded "." from same-repo callers; passed as array element to exec, not shell-interpolated
164171
context: ${{ inputs.context }}
165172
file: ${{ inputs.dockerfile }}
166173
load: false

.github/workflows/publish-docker.yml

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,15 @@ jobs:
4545

4646
- name: 🏷️ Resolve version
4747
id: version
48+
env:
49+
EVENT_NAME: ${{ github.event_name }}
50+
INPUT_TAG: ${{ inputs.tag }}
51+
REF_NAME: ${{ github.ref_name }}
4852
run: |
49-
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
50-
CLEAN="${{ inputs.tag }}" # full tag as provided (e.g. 1.1.3 or v2.0.0)
53+
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
54+
CLEAN="$INPUT_TAG" # full tag as provided (e.g. 1.1.3 or v2.0.0)
5155
else
52-
CLEAN="${{ github.ref_name }}" # e.g. v2.0.0
56+
CLEAN="$REF_NAME" # e.g. v2.0.0
5357
fi
5458
CLEAN="${CLEAN#v}" # strip leading v if present → 2.0.0 or 1.1.3
5559
echo "clean=$CLEAN" >> "$GITHUB_OUTPUT"
@@ -71,7 +75,9 @@ jobs:
7175
push: true
7276
tag_push: ${{ github.ref_type == 'tag' }}
7377
version: ${{ needs.resolve-version.outputs.version }}
74-
secrets: inherit
78+
secrets:
79+
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
80+
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
7581

7682
# ── Job 3: Create GitHub release + update CHANGELOG ────────────────────────
7783
# Runs once after the image is successfully pushed (not for workflow_dispatch
@@ -102,30 +108,35 @@ jobs:
102108
repositories: socket-basics
103109

104110
- name: 📝 Create GitHub release with auto-generated notes
111+
env:
112+
GH_TOKEN: ${{ steps.bot.outputs.token }}
113+
REF_NAME: ${{ github.ref_name }}
105114
run: |
106-
gh release create "${{ github.ref_name }}" \
107-
--title "${{ github.ref_name }}" \
115+
gh release create "$REF_NAME" \
116+
--title "$REF_NAME" \
108117
--generate-notes \
109118
--verify-tag \
110119
|| echo "Release already exists (re-run scenario) — skipping creation"
111-
env:
112-
GH_TOKEN: ${{ steps.bot.outputs.token }}
113120
114121
- name: 📋 Update CHANGELOG.md
122+
env:
123+
GH_TOKEN: ${{ steps.bot.outputs.token }}
124+
REF_NAME: ${{ github.ref_name }}
115125
run: |
116-
NOTES=$(gh release view "${{ github.ref_name }}" --json body --jq .body)
126+
NOTES=$(gh release view "$REF_NAME" --json body --jq .body)
117127
DATE=$(date +%Y-%m-%d)
118128
echo "$NOTES" | python scripts/update_changelog.py \
119129
--version "$VERSION" \
120130
--date "$DATE"
121-
env:
122-
GH_TOKEN: ${{ steps.bot.outputs.token }}
123131
124132
- name: 🔀 Commit CHANGELOG + action.yml back to main
133+
env:
134+
BOT_TOKEN: ${{ steps.bot.outputs.token }}
135+
REF_NAME: ${{ github.ref_name }}
125136
run: |
126137
git config user.name "socket-release-bot[bot]"
127138
git config user.email "socket-release-bot[bot]@users.noreply.github.com"
128-
git remote set-url origin "https://x-access-token:${{ steps.bot.outputs.token }}@github.com/SocketDev/socket-basics.git"
139+
git remote set-url origin "https://x-access-token:${BOT_TOKEN}@github.com/SocketDev/socket-basics.git"
129140
130141
# Auto-update action.yml image ref to the new version.
131142
# No-op if action.yml still uses `image: "Dockerfile"` (handles the
@@ -138,5 +149,5 @@ jobs:
138149
fi
139150
140151
git add CHANGELOG.md action.yml
141-
git diff --cached --quiet || git commit -m "chore: release ${{ github.ref_name }} — update CHANGELOG and action.yml [skip ci]"
152+
git diff --cached --quiet || git commit -m "chore: release ${REF_NAME} — update CHANGELOG and action.yml [skip ci]"
142153
git push origin HEAD:main

.github/workflows/smoke-test.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,3 @@ jobs:
3838
context: .
3939
check_set: main
4040
push: false
41-
secrets: inherit

.github/zizmor.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
rules:
2+
secrets-outside-env:
3+
disable: true

0 commit comments

Comments
 (0)