Skip to content

Code Injection in Canary CI Workflow via Issue Comment

Critical
dai-shi published GHSA-gr7v-jghp-mwvf Apr 16, 2026

Package

actions wakujs/waku (GitHub Actions)

Affected versions

>=v0.21.15

Patched versions

None

Description

Summary

A code injection vulnerability exists in the Canary CI GitHub Actions workflow (.github/workflows/canary-ci.yml). Because the workflow directly interpolates the contents of an issue comment into a shell script using GitHub Actions expression syntax (${{ }}), any user capable of commenting on a pull request can inject arbitrary code into the workflow execution context. This can lead to unauthorized access, secret exfiltration, and potential repository compromise.

Details

The vulnerability is located in the parse-version job of .github/workflows/canary-ci.yml. Specifically, within the "Get React version from comment" step, the workflow uses expression syntax to directly inject the comment body into a run shell script block:

- name: Get React version from comment
  id: get-version
  run: |
    comment="${{ github.event.comment.body }}"

GitHub Actions evaluates the ${{ }} expression before the shell script is executed, performing a direct string substitution into the script body. This means that any shell metacharacters (such as double quotes and semicolons) present in the comment body are inserted verbatim into the script source code. The shell then interprets these characters as part of the script's syntax, allowing an attacker to break out of the intended variable assignment and inject arbitrary code that executes in the context of the GitHub Actions runner.

PoC

  1. Navigate to an existing Pull Request (or create a new one) on the target repository.
  2. Post the following malicious payload as a comment:
/canary-ci run"; echo "=== PWNED ==="; whoami; echo "
  1. The issue_comment event defined in canary-ci.yml will trigger the workflow.
  2. Navigate to the Actions tab and inspect the logs for the "Get React version from comment" step in the parse-version job.
  3. Due to the expression evaluation, the shell script that actually executes becomes:
comment="/canary-ci run"; echo "=== PWNED ==="; whoami; echo ""
  1. The log will output the execution of the injected code, demonstrating successful exploitation:
スクリーンショット 2026-04-16 11 20 43

Impact

Vulnerable File: .github/workflows/canary-ci.yml
Vulnerability Type: Code Injection (CWE-94)

Who is impacted:
Repository maintainers, project infrastructure, and any downstream users relying on the integrity of the project's code and releases.

Impact Details:

  • Confidentiality: An attacker can exfiltrate sensitive environment variables and secrets exposed to the runner, including the GITHUB_TOKEN.
  • Integrity: Using compromised tokens, an attacker could potentially modify source code, push malicious commits, or alter release artifacts.
  • Availability: Runner resources could be abused for unauthorized activities. If self-hosted runners are used, the attacker could completely compromise the host system, leading to CI/CD pipeline downtime.

Remediation Advice

To fix this vulnerability in .github/workflows/canary-ci.yml, pass the comment body to the script securely via an environment variable. Environment variables are set before the shell script is parsed, so their contents are never interpreted as code:

env:
  COMMENT_BODY: ${{ github.event.comment.body }}
run: |
  comment="$COMMENT_BODY"

Severity

Critical

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
Low
User interaction
None
Scope
Changed
Confidentiality
High
Integrity
High
Availability
None

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N

CVE ID

No known CVE

Weaknesses

Improper Control of Generation of Code ('Code Injection')

The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment. Learn more on MITRE.

Credits