GHSA-C3XH-98XP-6QHF: Partial Fix for Command Injection in Discord Notification Workflow
Summary
The workflow previously embedded untrusted issue or pull request titles directly into an inline shell assignment, enabling command injection in GitHub Actions. The patch changes interpolation style and narrows the event fields to issue-only values, which may reduce exposure for pull_request-triggered paths, but it does not demonstrate robust shell-safe handling of attacker-controlled data. Based on the available diff, this is not a complete remediation of the root cause.
Analysis
Vulnerability
GHSA-C3XH-98XP-6QHF describes a command injection flaw in a GitHub Actions workflow that sends Discord notifications. The vulnerable pattern placed attacker-controlled GitHub metadata, specifically issue or pull request titles, into an inline Bash script. Because titles are untrusted and can contain shell metacharacters or command substitution syntax, direct interpolation into shell source can lead to arbitrary command execution on the runner.
The commit reference shows the vulnerable workflow assigning the title inside the script body using GitHub expression expansion:
ISSUE_TITLE="${{ github.event.issue.title || github.event.pull_request.title }}"
ISSUE_URL="${{ github.event.issue.html_url || github.event.pull_request.html_url }}"
AUTHOR="${{ github.actor }}"In this construction, GitHub evaluates the expression before the shell runs. If the resulting text contains shell-significant content, quoting alone is not a reliable defense when the untrusted value is injected into the shell program itself rather than passed through a shell-safe transport. This matches the advisory summary and the workflow diff in the referenced commit: commit 157840482e592bd4f8e0617539e73cdbef26f1ac.
Patch
The patch changes the workflow from inline shell assignments to YAML-style environment variable declarations and removes the pull request fallback in the shown lines:
ISSUE_TITLE: ${{ github.event.issue.title }}
ISSUE_URL: ${{ github.event.issue.html_url }}
AUTHOR: ${{ github.actor }}From the available snippet, two effects are visible:
- Untrusted values are no longer shown being embedded directly as shell assignment statements in the script body.
- The workflow now references
github.event.issue.*only, instead ofissue || pull_request, which may disable the vulnerable data path for pull request events if the workflow still runs in those contexts.
However, the diff excerpt is narrow and does not show the full step structure. If these values are later consumed unsafely by shell commands, the underlying injection risk can persist. A complete fix would require ensuring attacker-controlled data is never interpreted as shell syntax, for example by avoiding inline shell composition, using action inputs or structured payload generation, or passing data through environment variables and consuming it with strict quoting in a way that does not re-evaluate content.
Review
Pros
- The patch appears to move untrusted event data out of direct inline Bash assignment syntax, which is the specific dangerous pattern called out by the advisory.
- Restricting references to
github.event.issue.*may reduce attack surface by removing the pull request title path shown in the vulnerable code. - The change is small and low-risk operationally, which is useful for quickly reducing exposure in CI workflows.
Cons
- The available diff does not show a definitive shell-safe sink. If the environment variables are later interpolated into shell commands without safe handling, command injection may still be reachable.
- Removing the pull request fallback changes behavior as well as security posture. If pull request notifications were intended, this may be a functional regression rather than a principled remediation.
- The patch does not, from the shown lines, establish a robust invariant such as JSON serialization, argumentized command execution, or elimination of shell parsing for attacker-controlled fields.
Verdict
Partial fix.
The patch likely mitigates the exact inline-script interpolation pattern documented in the advisory, but the evidence in the commit snippet is insufficient to conclude that the root cause is fully removed. The root cause is unsafe interpretation of untrusted GitHub metadata by a shell. The shown change reduces direct exposure and may disable one event path, yet it does not by itself prove that all downstream uses of ISSUE_TITLE and related fields are shell-safe. Engineers should review the full workflow and any subsequent command construction in the same step to confirm that attacker-controlled values are never reintroduced into shell syntax. Relevant sources: commit diff, GitHub Security Advisory, and third-party report.
Recommended Labs
Try this vulnerability pattern yourself with hands-on labs.
- Script Injection.github
Best direct match for the GHSA topic. The advisory describes untrusted GitHub issue/PR titles being interpolated into an inline Bash script in GitHub Actions, which is a CI/CD script injection pattern. This lab is GitHub-focused, hands-on, and aligned with OWASP A03:2021 Injection.
- Static Code Injection.js
Useful follow-on defensive lab for practicing safe handling of untrusted input that reaches executable contexts. While language-specific, it reinforces the core fix pattern behind this GHSA: avoid directly embedding attacker-controlled data into code or command execution paths.
- BadVal.js
Good supporting lab for defensive practice around argument/command injection style bugs. It helps build intuition for input validation, safer APIs, and avoiding dangerous execution sinks—concepts directly applicable when patching shell-invoking GitHub workflows.