Skip to content

Commit a08428b

Browse files
fix(ci): avoid template injection in org TruffleHog workflow (zizmor)
Pass workflow_dispatch inputs via step env only; validate org slug and single_repo URL before invoking trufflehog. Made-with: Cursor
1 parent aac4d10 commit a08428b

2 files changed

Lines changed: 42 additions & 3 deletions

File tree

.github/workflows/org-trufflehog-fullscan.yml

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
#
44
# Test now: Actions → this workflow → Run workflow.
55
# Smoke test: set `single_repo` to one HTTPS URL and leave org as default.
6+
#
7+
# Inputs are passed only via step `env` (not ${{ }} inside `run:`) to satisfy
8+
# zizmor template-injection rules; values are validated before use.
69

710
name: TruffleHog org scan (GitHub)
811

@@ -54,17 +57,46 @@ jobs:
5457
- name: Run scan (advisory — never blocks merges)
5558
env:
5659
TOKEN: ${{ secrets.ORG_TRUFFLEHOG_PAT }}
60+
# Do not interpolate workflow inputs inside `run:` (zizmor: template-injection).
61+
ORG_INPUT: ${{ github.event.inputs.org || '' }}
62+
SINGLE_REPO_INPUT: ${{ github.event.inputs.single_repo || '' }}
63+
EVENT_NAME: ${{ github.event_name }}
5764
run: |
5865
if [[ -z "${TOKEN}" ]]; then
5966
echo "::error::Create repository secret ORG_TRUFFLEHOG_PAT (PAT with read access to the org repos you scan)."
6067
exit 1
6168
fi
6269
70+
# GitHub org slug: alphanumeric + hyphen, reasonable length (GitHub max 39).
71+
validate_org() {
72+
local o="$1"
73+
[[ "${o}" =~ ^[a-zA-Z0-9][a-zA-Z0-9-]{0,38}$ ]]
74+
}
75+
76+
# Single-repo smoke test: strict https://github.com/org/repo only.
77+
validate_repo_url() {
78+
local u="$1"
79+
[[ -z "${u}" ]] && return 0
80+
[[ "${u}" =~ ^https://github\.com/[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+/?$ ]]
81+
}
82+
6383
ORG="${DEFAULT_ORG}"
6484
SINGLE_REPO=""
65-
if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
66-
ORG="${{ github.event.inputs.org }}"
67-
SINGLE_REPO="${{ github.event.inputs.single_repo }}"
85+
if [[ "${EVENT_NAME}" == "workflow_dispatch" ]]; then
86+
if [[ -n "${ORG_INPUT}" ]]; then
87+
if ! validate_org "${ORG_INPUT}"; then
88+
echo "::error::Invalid org slug (allowed: letters, digits, hyphen; 1–39 chars)."
89+
exit 1
90+
fi
91+
ORG="${ORG_INPUT}"
92+
fi
93+
if [[ -n "${SINGLE_REPO_INPUT}" ]]; then
94+
if ! validate_repo_url "${SINGLE_REPO_INPUT}"; then
95+
echo "::error::Invalid single_repo URL (use https://github.com/ORG/REPO with no query or fragment)."
96+
exit 1
97+
fi
98+
SINGLE_REPO="${SINGLE_REPO_INPUT}"
99+
fi
68100
fi
69101
70102
set +e

docs/trufflehog-org-fullscan.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,10 @@ With token: add `--token="$GITHUB_TOKEN"`.
2323

2424
- Workflow is advisory (no `--fail`); do not add as a required ruleset check if you want it off the merge path.
2525
- Weekly schedule is optional; remove `schedule:` in the YAML for manual-only.
26+
27+
## Input validation (workflow_dispatch)
28+
29+
To avoid unsafe values being interpreted by the shell, inputs are restricted:
30+
31+
- **org:** GitHub org slug only — letters, digits, hyphen; 1–39 characters (first character must be alphanumeric).
32+
- **single_repo:** Must look like `https://github.com/ORG/REPO` (no query string, fragment, or `.git` suffix in the URL you pass).

0 commit comments

Comments
 (0)