Skip to content

Commit fc09dcf

Browse files
security: fix code injection and untrusted checkout vulnerabilities
- bot-ai-review.yml: Add fork check to prevent untrusted code execution - gen-create-spec.yml: Remove eval, use direct command execution - bot-auto-tag.yml: Replace sed with Python for safe string handling - gen-preview.yml: Use unquoted heredoc instead of sed for variable expansion Fixes CodeQL alerts for code injection and untrusted checkout patterns.
1 parent 3381c8d commit fc09dcf

File tree

4 files changed

+50
-35
lines changed

4 files changed

+50
-35
lines changed

.github/workflows/bot-ai-review.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,17 @@ jobs:
1919
steps:
2020
- name: Check conditions
2121
id: check
22+
env:
23+
HEAD_REPO: ${{ github.event.workflow_run.head_repository.full_name }}
24+
BASE_REPO: ${{ github.repository }}
2225
run: |
26+
# Security: Skip if workflow run is from a fork (untrusted code)
27+
if [[ "$HEAD_REPO" != "$BASE_REPO" ]]; then
28+
echo "::notice::Skipping: Workflow run is from fork '$HEAD_REPO', not '$BASE_REPO'"
29+
echo "should_run=false" >> $GITHUB_OUTPUT
30+
exit 0
31+
fi
32+
2333
CONCLUSION="${{ github.event.workflow_run.conclusion }}"
2434
2535
if [[ "$CONCLUSION" != "success" ]]; then

.github/workflows/bot-auto-tag.yml

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -131,26 +131,31 @@ jobs:
131131
PLOT_CONTENT=""
132132
fi
133133
134-
# Create prompt for Claude
135-
cat > /tmp/tag_prompt.txt << 'PROMPTEOF'
136-
Analyze this plot specification and implementation to generate a hierarchical tag structure.
134+
# Create prompt for Claude (Security: avoid sed with user content)
135+
# Export variables so Python can access them, then use Python for safe string handling
136+
export SPEC_CONTENT PLOT_CONTENT
137+
python3 << 'PYEOF'
138+
import os
139+
spec = os.environ.get('SPEC_CONTENT', '')
140+
plot = os.environ.get('PLOT_CONTENT', '')
141+
prompt = f"""Analyze this plot specification and implementation to generate a hierarchical tag structure.
137142
138143
## Specification:
139-
${SPEC_CONTENT}
144+
{spec}
140145
141146
## Implementation (example):
142-
${PLOT_CONTENT}
147+
{plot}
143148
144149
## Task:
145150
Generate a 5-level tag hierarchy for this plot. Format as JSON:
146-
{
151+
{{
147152
"level1_category": "visualization_type",
148153
"level2_type": "specific_chart_type",
149154
"level3_style": "style_variant",
150155
"level4_features": ["feature1", "feature2"],
151156
"level5_use_cases": ["use_case1", "use_case2"],
152157
"search_tags": ["tag1", "tag2", "tag3"]
153-
}
158+
}}
154159
155160
Categories:
156161
- Level 1: Main category (scatter, bar, line, heatmap, distribution, comparison, etc.)
@@ -159,12 +164,10 @@ jobs:
159164
- Level 4: Features used (gridlines, annotations, legends, colors, etc.)
160165
- Level 5: Use cases (exploratory, presentation, publication, dashboard, etc.)
161166
162-
Return ONLY valid JSON, no markdown formatting.
163-
PROMPTEOF
164-
165-
# Replace placeholders
166-
sed -i "s|\${SPEC_CONTENT}|${SPEC_CONTENT}|g" /tmp/tag_prompt.txt
167-
sed -i "s|\${PLOT_CONTENT}|${PLOT_CONTENT}|g" /tmp/tag_prompt.txt
167+
Return ONLY valid JSON, no markdown formatting."""
168+
with open('/tmp/tag_prompt.txt', 'w') as f:
169+
f.write(prompt)
170+
PYEOF
168171
169172
# Call Claude API (with timeout)
170173
RESPONSE=$(curl -s --max-time 60 --connect-timeout 10 https://api.anthropic.com/v1/messages \

.github/workflows/gen-create-spec.yml

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -341,17 +341,20 @@ jobs:
341341
ISSUE_NUMBER: ${{ github.event.issue.number }}
342342
TARGET_LIBRARY: ${{ needs.create-spec.outputs.target_library }}
343343
run: |
344-
# Build command with optional target_library
345-
CMD="gh workflow run gen-new-plot.yml --repo ${{ github.repository }}"
346-
CMD="$CMD -f spec_id=\"$SPEC_ID\""
347-
CMD="$CMD -f feature_branch=\"$FEATURE_BRANCH\""
348-
CMD="$CMD -f issue_number=\"$ISSUE_NUMBER\""
349-
344+
# Security: Direct execution instead of eval to prevent command injection
350345
if [[ -n "$TARGET_LIBRARY" ]]; then
351-
CMD="$CMD -f target_library=\"$TARGET_LIBRARY\""
352346
echo "::notice::Triggering gen-new-plot.yml for $SPEC_ID (library: $TARGET_LIBRARY)"
347+
gh workflow run gen-new-plot.yml \
348+
--repo "${{ github.repository }}" \
349+
-f spec_id="$SPEC_ID" \
350+
-f feature_branch="$FEATURE_BRANCH" \
351+
-f issue_number="$ISSUE_NUMBER" \
352+
-f target_library="$TARGET_LIBRARY"
353353
else
354354
echo "::notice::Triggering gen-new-plot.yml for $SPEC_ID (all libraries)"
355+
gh workflow run gen-new-plot.yml \
356+
--repo "${{ github.repository }}" \
357+
-f spec_id="$SPEC_ID" \
358+
-f feature_branch="$FEATURE_BRANCH" \
359+
-f issue_number="$ISSUE_NUMBER"
355360
fi
356-
357-
eval $CMD

.github/workflows/gen-preview.yml

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -312,25 +312,24 @@ jobs:
312312
PREV_URL=$(echo "$PREV_VERSIONS" | jq -r --arg key "$KEY" '.[$key].url // empty')
313313
PREV_COUNT=$(echo "$PREV_VERSIONS" | jq -r --arg key "$KEY" '.[$key].count // 0')
314314
315+
# Security: Use unquoted heredoc for direct variable expansion (safer than sed)
315316
if [ -n "$PREV_URL" ] && [ "$PREV_URL" != "null" ]; then
316317
NEW_COUNT=$((PREV_COUNT + 1))
317-
cat >> plot_markdown.txt << 'PLOTEOF'
318-
### ${LIBRARY} (${VARIANT}) - UPDATE
318+
cat >> plot_markdown.txt << PLOTEOF
319+
### ${LIBRARY} (${VARIANT}) - UPDATE
319320

320-
| Before | After |
321-
|--------|-------|
322-
| ![Before](${PREV_URL}) | ![After](${NEW_URL}) |
321+
| Before | After |
322+
|--------|-------|
323+
| ![Before](${PREV_URL}) | ![After](${NEW_URL}) |
323324

324-
[View version history (${NEW_COUNT} versions)](${HISTORY_URL})
325-
PLOTEOF
326-
sed -i "s|\${LIBRARY}|${LIBRARY}|g; s|\${VARIANT}|${VARIANT}|g; s|\${PREV_URL}|${PREV_URL}|g; s|\${NEW_URL}|${NEW_URL}|g; s|\${NEW_COUNT}|${NEW_COUNT}|g; s|\${HISTORY_URL}|${HISTORY_URL}|g" plot_markdown.txt
325+
[View version history (${NEW_COUNT} versions)](${HISTORY_URL})
326+
PLOTEOF
327327
else
328-
cat >> plot_markdown.txt << 'PLOTEOF'
329-
### ${LIBRARY} (${VARIANT}) - NEW
328+
cat >> plot_markdown.txt << PLOTEOF
329+
### ${LIBRARY} (${VARIANT}) - NEW
330330

331-
![${LIBRARY} ${VARIANT}](${NEW_URL})
332-
PLOTEOF
333-
sed -i "s|\${LIBRARY}|${LIBRARY}|g; s|\${VARIANT}|${VARIANT}|g; s|\${NEW_URL}|${NEW_URL}|g" plot_markdown.txt
331+
![${LIBRARY} ${VARIANT}](${NEW_URL})
332+
PLOTEOF
334333
fi
335334
echo "" >> plot_markdown.txt
336335
fi

0 commit comments

Comments
 (0)