Skip to content

Command Injection in GitHub Action

Moderate
garthvh published GHSA-6mwm-v2vv-pp96 Jul 10, 2025

Package

actions meshtastic/firmware (GitHub Actions)

Affected versions

>2.5.3

Patched versions

2.6.6

Description

Observations

GitHub Actions is an automation platform directly integrated into GitHub repositories. It allows you to create custom workflows to automate various tasks within your software development lifecycle, such as building, testing, and deploying code. These workflows are defined in YAML files and are triggered by events within your repository, like a code push or a pull request.

Certain parameters, such as issue title, are considered unsafe because an unauthorized user could fully control them. Furthermore, GitHub Action runners operate with varying levels of permissions and secret access, determined by the "permissions" configuration in the YAML file, authorization settings at the repository level, and the specific event that triggered the action (e.g., pull_request versus pull_request_target).

We noticed that the main_matrix.yml GitHub Action is triggered by the pull_request_target event, which has extensive permissions, and can be initiated by an attacker who forked the repository and created a pull request. In the shell code execution part, user-controlled input is interpolated unsafely into the code.

       run: |
          if [[ "${{ github.head_ref }}" == "" ]]; then
            TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}})
          else  
            TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}} quick)
          fi
          echo "Name: ${{ github.ref_name }} Base: ${{ github.base_ref }} } Ref: ${{ github.ref }} Targets: $TARGETS"
          echo "${{matrix.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT

Exploitation

An attacker could create a pull request from a fork with a branch name such as $(printenv>&2) that will print the environment variable of the runner or $({git,config,--get,http.https://github.com/.extraheader}>&2) to exfiltrate the GitHub token. The >&2 is meant to print the output to stderr since it is interpolated inside a string, and using the curly brackets when executing a command with an argument is needed due to GitHub’s branch name limitation.

Note: We reproduced the vulnerability in our own environment. We did not try to exploit this on the Meshtastic/firmware repository.

Impact

The action utilizes the pull_request_target trigger, which has extensive permissions. If this were to be exploited, attackers could inject unauthorized code into the repository. This could have significant negative impacts on users, such as the deployment of backdoors, the distribution of malware, and other security compromises.

Recommendations

One recommended way to handle untrusted user input in GitHub Actions is to first assign it to an intermediate environment variable and only then use it in the execution step.

jobs:
  safe-echo-body:
    runs-on: ubuntu-latest
    steps:
    -  env:
        BODY: ${{ github.event.issue.body }}
      run: |
        echo "$BODY"

Be aware of an interesting pitfall, and don't interpolate environment variables using ${{ env.BODY }}.

Severity

Moderate

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
Required
Scope
Changed
Confidentiality
Low
Integrity
None
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:R/S:C/C:L/I:N/A:N

CVE ID

CVE-2025-53637

Weaknesses

No CWEs

Credits