Skip to content

Commit a3d805c

Browse files
hbrodinclaude
andauthored
ci: shell-quote env values in system-integration workflow (#536)
* ci: shell-quote env values for system integration tests Two bugs in the env file step prevented the weekly System Integration Tests from ever passing since #427 (2026-01-26): 1. The deletion regex `/^KEY=/` did not match the template's `export KEY=replace-me` lines, leaving stale `replace-me` placeholders in the file alongside the appended real values. 2. Appended values were not shell-quoted, so `source ./env` in deployment/crs-architecture.sh treated whitespace and metacharacters as shell syntax. The `OTEL_TOKEN` secret (a `Bearer <token>` header) tripped this with `command not found` on the token component. The same gap was a code-execution sink: a secret containing `$(...)` or backticks would execute on the runner at source time. Fix: strip with `(export[[:space:]]+)?` so template lines are actually removed, and write with `printf 'export %s=%q\n'` so every value is shell-escaped — defending against both whitespace and injection. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * ci: drop placeholder block from ci-env.template The placeholder lines (`export KEY=replace-me`) only existed because the pre-rewrite step substituted into them with `sed -i "s|KEY=.*|...|"`. The new `printf %q` write path doesn't need them, so removing them at the source eliminates the entire delete-then-rewrite dance. Drops `strip_var` and the for-loop. The workflow step is now: copy the static template, then append shell-quoted assignments for every secret the env: block injects. GHCR_AUTH is no longer defined at all, so the `[ -n "$GHCR_AUTH" ]` warning branch in crs-architecture.sh:63 fires as intended. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b3e5851 commit a3d805c

2 files changed

Lines changed: 18 additions & 36 deletions

File tree

.github/ci-env.template

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,3 @@ export OTEL_PROTOCOL="http"
1414
export LANGFUSE_ENABLED=true
1515
export DOCKER_USERNAME=""
1616
export DOCKER_PAT=""
17-
18-
# Secrets/Env replaced
19-
export OTEL_ENDPOINT=replace-me
20-
export OTEL_TOKEN=replace-me
21-
export BUTTERCUP_NAMESPACE=replace-me
22-
export GHCR_AUTH=replace-me
23-
export OPENAI_API_KEY=replace-me
24-
export ANTHROPIC_API_KEY=replace-me
25-
export GEMINI_API_KEY=replace-me
26-
export LANGFUSE_HOST=replace-me
27-
export LANGFUSE_PUBLIC_KEY=replace-me
28-
export LANGFUSE_SECRET_KEY=replace-me

.github/workflows/system-integration.yml

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -98,30 +98,24 @@ jobs:
9898
OTEL_EP: ${{ secrets.OTEL_ENDPOINT }}
9999
OTEL_TK: ${{ secrets.OTEL_TOKEN }}
100100
run: |
101-
cp ../.github/ci-env.template env
102-
# Remove GHCR_AUTH line and lines for values we'll append
103-
sed -i "/^GHCR_AUTH=/d" env
104-
sed -i "/^BUTTERCUP_NAMESPACE=/d" env
105-
sed -i "/^OPENAI_API_KEY=/d" env
106-
sed -i "/^ANTHROPIC_API_KEY=/d" env
107-
sed -i "/^GEMINI_API_KEY=/d" env
108-
sed -i "/^LANGFUSE_HOST=/d" env
109-
sed -i "/^LANGFUSE_PUBLIC_KEY=/d" env
110-
sed -i "/^LANGFUSE_SECRET_KEY=/d" env
111-
sed -i "/^OTEL_ENDPOINT=/d" env
112-
sed -i "/^OTEL_TOKEN=/d" env
113-
# Append values safely using echo (avoids sed injection with special chars)
114-
{
115-
echo "BUTTERCUP_NAMESPACE=${BUTTERCUP_NS}"
116-
echo "OPENAI_API_KEY=${OPENAI_KEY}"
117-
echo "ANTHROPIC_API_KEY=${ANTHROPIC_KEY}"
118-
echo "GEMINI_API_KEY=${GEMINI_KEY}"
119-
echo "LANGFUSE_HOST=${LF_HOST}"
120-
echo "LANGFUSE_PUBLIC_KEY=${LF_PUBLIC_KEY}"
121-
echo "LANGFUSE_SECRET_KEY=${LF_SECRET_KEY}"
122-
echo "OTEL_ENDPOINT=${OTEL_EP}"
123-
echo "OTEL_TOKEN=${OTEL_TK}"
124-
} >> "env"
101+
# The env file is sourced by deployment/crs-architecture.sh, so every
102+
# value must be shell-quoted. printf %q produces a form bash can
103+
# re-parse as the literal string, defending against shell injection
104+
# from secret contents (whitespace, $(), backticks, quotes, etc.).
105+
write_var() {
106+
printf 'export %s=%q\n' "$1" "$2" >> ./env
107+
}
108+
109+
cp ../.github/ci-env.template ./env
110+
write_var BUTTERCUP_NAMESPACE "$BUTTERCUP_NS"
111+
write_var OPENAI_API_KEY "$OPENAI_KEY"
112+
write_var ANTHROPIC_API_KEY "$ANTHROPIC_KEY"
113+
write_var GEMINI_API_KEY "$GEMINI_KEY"
114+
write_var LANGFUSE_HOST "$LF_HOST"
115+
write_var LANGFUSE_PUBLIC_KEY "$LF_PUBLIC_KEY"
116+
write_var LANGFUSE_SECRET_KEY "$LF_SECRET_KEY"
117+
write_var OTEL_ENDPOINT "$OTEL_EP"
118+
write_var OTEL_TOKEN "$OTEL_TK"
125119
working-directory: deployment
126120

127121
- name: Run CRS

0 commit comments

Comments
 (0)