fix(ci): harden WorkflowTemplate against template injection

commit-sha (from the untrusted Gitea webhook body.after) was substituted
INLINE into shell scripts via {{workflow.parameters.commit-sha}} in all
three git-clone/decide-mode steps -> a malicious payload could inject shell
on a cluster-privileged pod. Now passed via ENV + hex-validated before use
(the build-image template's pattern), and mode is allowlist-checked. Closes
the background security review's Orchestrator Template Injection finding.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 10:20:26 +00:00
parent 603aaaabff
commit 0069b75d0e

View File

@@ -51,32 +51,38 @@ spec:
container:
image: alpine/git:latest
command: [/bin/sh, -c]
# SECURITY: commit-sha/mode arrive via ENV (not inline {{...}} substitution) so an untrusted webhook
# payload cannot inject shell. commit-sha is validated hex before use; mode is checked against an allowlist.
env:
- { name: COMMIT_SHA, value: "{{workflow.parameters.commit-sha}}" }
- { name: MODE, value: "{{workflow.parameters.mode}}" }
args:
- |
set -e
case "$COMMIT_SHA" in *[!0-9a-fA-F]*|"") echo "refusing non-hex commit-sha" >&2; exit 1 ;; esac
case "$MODE" in auto|build|deploy) : ;; *) echo "refusing unknown mode: $MODE" >&2; exit 1 ;; esac
mkdir -p /root/.ssh
cp /etc/git-ssh/ssh-privatekey /root/.ssh/id_ed25519
chmod 600 /root/.ssh/id_ed25519
printf 'Host *\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null\n' > /root/.ssh/config
git clone --filter=blob:none \
"ssh://git@gitea-sshd.foxhunt.svc.cluster.local:22/gitadmin/fxhnt.git" /workspace/src
cd /workspace/src && git checkout "{{workflow.parameters.commit-sha}}"
cd /workspace/src && git checkout "$COMMIT_SHA"
if [ "{{workflow.parameters.mode}}" != "auto" ]; then
echo -n "{{workflow.parameters.mode}}" > /tmp/mode
if [ "$MODE" != "auto" ]; then
printf '%s' "$MODE" > /tmp/mode
else
SHA="{{workflow.parameters.commit-sha}}"
RESOLVED="$(git rev-parse "$SHA")"
RESOLVED="$(git rev-parse "$COMMIT_SHA")"
if CHANGED=$(git diff --name-only "${RESOLVED}~1" "${RESOLVED}" 2>/dev/null); then
# diff succeeded (parent exists): build only if a dep/Dockerfile file changed, else deploy.
if echo "$CHANGED" | grep -qE '^pyproject\.toml$|^infra/docker/fxhnt\.Dockerfile$'; then
echo -n build > /tmp/mode
printf 'build' > /tmp/mode
else
echo -n deploy > /tmp/mode
printf 'deploy' > /tmp/mode
fi
else
# diff failed (no parent -- first commit / shallow history): default to build (safe, never wrong).
echo -n build > /tmp/mode
printf 'build' > /tmp/mode
fi
fi
cat /tmp/mode
@@ -97,16 +103,20 @@ spec:
- name: git-clone
image: alpine/git:latest
command: [/bin/sh, -c]
# SECURITY: commit-sha via ENV + hex-validated (see decide-mode note) — no inline shell substitution.
env:
- { name: COMMIT_SHA, value: "{{workflow.parameters.commit-sha}}" }
args:
- |
set -ex
case "$COMMIT_SHA" in *[!0-9a-fA-F]*|"") echo "refusing non-hex commit-sha" >&2; exit 1 ;; esac
mkdir -p /root/.ssh
cp /etc/git-ssh/ssh-privatekey /root/.ssh/id_ed25519
chmod 600 /root/.ssh/id_ed25519
printf 'Host *\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null\n' > /root/.ssh/config
git clone --no-checkout --filter=blob:none \
"ssh://git@gitea-sshd.foxhunt.svc.cluster.local:22/gitadmin/fxhnt.git" /workspace/src
cd /workspace/src && git checkout "{{workflow.parameters.commit-sha}}"
cd /workspace/src && git checkout "$COMMIT_SHA"
echo "checked out $(git rev-parse --short HEAD)"
volumeMounts:
- { name: git-ssh-key, mountPath: /etc/git-ssh, readOnly: true }
@@ -148,16 +158,20 @@ spec:
- name: git-clone
image: alpine/git:latest
command: [/bin/sh, -c]
# SECURITY: commit-sha via ENV + hex-validated — no inline shell substitution.
env:
- { name: COMMIT_SHA, value: "{{workflow.parameters.commit-sha}}" }
args:
- |
set -ex
case "$COMMIT_SHA" in *[!0-9a-fA-F]*|"") echo "refusing non-hex commit-sha" >&2; exit 1 ;; esac
mkdir -p /root/.ssh
cp /etc/git-ssh/ssh-privatekey /root/.ssh/id_ed25519
chmod 600 /root/.ssh/id_ed25519
printf 'Host *\n StrictHostKeyChecking no\n UserKnownHostsFile /dev/null\n' > /root/.ssh/config
git clone --no-checkout --filter=blob:none \
"ssh://git@gitea-sshd.foxhunt.svc.cluster.local:22/gitadmin/fxhnt.git" /workspace/src
cd /workspace/src && git checkout "{{workflow.parameters.commit-sha}}"
cd /workspace/src && git checkout "$COMMIT_SHA"
volumeMounts:
- { name: git-ssh-key, mountPath: /etc/git-ssh, readOnly: true }
- { name: workspace, mountPath: /workspace }