The ZenClaw Discord Integration GitHub Actions workflow is vulnerable to shell command injection. The issue title field, controllable by any GitHub user, is interpolated directly into a run shell block via a GitHub Actions template expression. An attacker can craft an issue title containing a subshell expression that executes arbitrary commands on the runner during variable assignment, enabling exfiltration of the DISCORD_WEBHOOK_URL secret. The trigger requires no repository privileges.
File: .github/workflows/zenclaw-discord.yml
Commit: 07e65c72656a8213fc9ece2b3f4fc719032cfc5d
URL: https://github.com/SHAdd0WTAka/Zen-Ai-Pentest/blob/07e65c72656a8213fc9ece2b3f4fc719032cfc5d/.github/workflows/zenclaw-discord.yml
Step: Prepare Notification
Trigger: issues: [opened] — no repository privileges required
In the Prepare Notification step, the issue title is assigned to a shell variable using direct GitHub Actions template interpolation inside a case block:
issues)
...
DESCRIPTION="${{ github.event.issue.title }}"
;;
The GitHub Actions template engine resolves ${{ github.event.issue.title }} at workflow compilation time, embedding the raw issue title as literal text in the bash script before execution. The value is assigned inside a double-quoted string, which in bash evaluates subshell expressions of the form $(...) and backtick expressions `...` at runtime.
Although a subsequent sanitization step is applied:
DESCRIPTION=$(echo "$DESCRIPTION" | tr '\n' ' ' | cut -c1-1000)
This sanitization runs after the assignment — the subshell in the title has already executed by the time tr and cut process the output. The sanitization is therefore ineffective as a security control against command injection.
The resulting DESCRIPTION value is then written to $GITHUB_OUTPUT:
echo "description=$DESCRIPTION" >>...
Exploitability
AV:NAC:LPR:NUI:NScope
S:CImpact
C:HI:HA:N10.0/CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N