Improper Sanitization of Branch Name Leads to Arbitrary Code Injection
Description
The tj-actions/branch-names GitHub Action is vulnerable to remote code execution via specially crafted branch names, enabling secret theft and unauthorized GitHub token abuse.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
The tj-actions/branch-names GitHub Action is vulnerable to remote code execution via specially crafted branch names, enabling secret theft and unauthorized GitHub token abuse.
Root
Cause
The tj-actions/branch-names GitHub Action is a composite action that retrieves branch or tag names during CI/CD workflows. A command injection vulnerability exists because the action improperly expands the github.event.pull_request.head.ref and github.head_ref context variables directly within a run step (shell: bash). Prior to version 7.0.7, these user-controlled variables were interpolated into the script without proper sanitization, allowing an attacker to inject arbitrary commands through a specially crafted branch name [1][2].
Attack
Vector
An attacker can exploit this vulnerability by creating a pull request with a malicious branch name containing shell metacharacters (e.g., backticks or $()). When a GitHub Actions workflow uses tj-actions/branch-names on that pull request (e.g., in response to pull_request_target or any trigger where the head ref is trusted), the injected commands execute in the runner context. No authentication beyond the ability to open a pull request against the repository is required; however, the victim repository must have a workflow that uses an affected version of the action [1].
Impact
Successful exploitation allows an attacker to execute arbitrary shell commands with the privileges of the GITHUB_TOKEN. This can result in exfiltration of repository secrets, unauthorized modifications to the repository, or compromise of downstream CI/CD pipelines. The injected commands run in the same environment that processes the action, giving the attacker full access to the runner's secrets and token permissions [1][2].
Mitigation
The vulnerability is fixed in version 7.0.7. The fix moves the use of context variables into environment variables before passing them to the run step, preventing direct command interpolation. The commit 4923d1c and subsequent hardening commit 6c999ac demonstrate this change. Users must update their workflow pin from @v7 or earlier to @v7.0.7 or later. No workarounds exist; upgrading is the only mitigation [1][2][3][4].
- GitHub - tj-actions/branch-names: :octocat: Github action to retrieve branch or tag names with support for all events.
- NVD - CVE-2023-49291
- Merge pull request #271 from tj-actions/security/prevent-arbitrary-co… · tj-actions/branch-names@4923d1c
- Merge pull request #272 from tj-actions/security/remove-vulnerable-ev… · tj-actions/branch-names@6c999ac
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
tj-actions/branch-namesGitHub Actions | < 7.0.7 | 7.0.7 |
Affected products
2- Range: < 7.0.7
Patches
36c999acf206fMerge pull request #272 from tj-actions/security/remove-vulnerable-events-from-test
1 file changed · +0 −2
.github/workflows/test.yml+0 −2 modified@@ -8,8 +8,6 @@ on: - main release: types: [published, created] - pull_request_review: - pull_request_target: pull_request: branches: - main
726fe9ba5e9dsecurity: remove vulnerable events from test
1 file changed · +0 −2
.github/workflows/test.yml+0 −2 modified@@ -8,8 +8,6 @@ on: - main release: types: [published, created] - pull_request_review: - pull_request_target: pull_request: branches: - main
4923d1ca41f9Merge pull request #271 from tj-actions/security/prevent-arbitrary-code-injection-via-untrusted-inputs
1 file changed · +36 −17
action.yml+36 −17 modified@@ -37,12 +37,18 @@ runs: using: "composite" steps: - id: branch + env: + GITHUB_REF: ${{ github.ref }} + GITHUB_BASE_REF: ${{ github.event.pull_request.base.ref || github.base_ref }} + GITHUB_HEAD_REF: ${{ github.event.pull_request.head.ref || github.head_ref }} + GITHUB_EVENT_BASE_REF: ${{ github.event.base_ref }} + INPUTS_STRIP_TAG_PREFIX: ${{ inputs.strip_tag_prefix }} run: | # "Set branch names..." - if [[ "${{ github.ref }}" != "refs/tags/"* ]]; then - BASE_REF=$(printf "%q" "${{ github.event.pull_request.base.ref || github.base_ref }}") - HEAD_REF=$(printf "%q" "${{ github.event.pull_request.head.ref || github.head_ref }}") - REF=$(printf "%q" "${{ github.ref }}") + if [[ "$GITHUB_REF" != "refs/tags/"* ]]; then + BASE_REF=$(printf "%q" "$GITHUB_BASE_REF") + HEAD_REF=$(printf "%q" "$GITHUB_HEAD_REF") + REF=$(printf "%q" "$GITHUB_REF") BASE_REF=${BASE_REF/refs\/heads\//} HEAD_REF=${HEAD_REF/refs\/heads\//} @@ -53,42 +59,55 @@ runs: echo "head_ref_branch=$(eval printf "%s" "$HEAD_REF")" >> "$GITHUB_OUTPUT" echo "ref_branch=$(eval printf "%s" "$REF_BRANCH")" >> "$GITHUB_OUTPUT" else - BASE_REF=$(printf "%q" "${{ github.event.base_ref }}") - BASE_REF=${BASE_REF/refs\/heads\/${{ inputs.strip_tag_prefix }}/} + BASE_REF=$(printf "%q" "$GITHUB_EVENT_BASE_REF") + BASE_REF=${BASE_REF/refs\/heads\/$INPUTS_STRIP_TAG_PREFIX/} echo "base_ref_branch=$(eval printf "%s" "$BASE_REF")" >> "$GITHUB_OUTPUT" fi shell: bash - id: current_branch + env: + GITHUB_REF: ${{ github.ref }} + GITHUB_EVENT_NAME: ${{ github.event_name }} + HEAD_REF_BRANCH: ${{ steps.branch.outputs.head_ref_branch }} + REF_BRANCH: ${{ steps.branch.outputs.ref_branch }} run: | # "Set the current branch name..." - if [[ "${{ github.ref }}" != "refs/tags/"* ]]; then - if [[ ${{ github.event_name }} == *"pull_request"* ]]; then - echo "current_branch=${{ steps.branch.outputs.head_ref_branch }}" >> "$GITHUB_OUTPUT" + if [[ "$GITHUB_REF" != "refs/tags/"* ]]; then + if [[ "$GITHUB_EVENT_NAME" == *"pull_request"* ]]; then + echo "current_branch=$HEAD_REF_BRANCH" >> "$GITHUB_OUTPUT" else - echo "current_branch=${{ steps.branch.outputs.ref_branch }}" >> "$GITHUB_OUTPUT" + echo "current_branch=$REF_BRANCH" >> "$GITHUB_OUTPUT" fi fi shell: bash - id: default + env: + GITHUB_REF: ${{ github.ref }} + CURRENT_BRANCH: ${{ steps.current_branch.outputs.current_branch }} + DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} + FORK: ${{ github.event.pull_request.head.repo.fork }} run: | # "Set the default branch name..." - if [[ "${{ github.ref }}" != "refs/tags/"* ]]; then - if [[ "${{ steps.current_branch.outputs.current_branch }}" == "${{ github.event.repository.default_branch }}" && "${{ github.event.pull_request.head.repo.fork }}" != "true" ]]; then + if [[ "$GITHUB_REF" != "refs/tags/"* ]]; then + if [[ "$CURRENT_BRANCH" == "$DEFAULT_BRANCH" && "$FORK" != "true" ]]; then echo "is_default=true" >> "$GITHUB_OUTPUT" - echo "default_branch=${{ github.event.repository.default_branch }}" >> "$GITHUB_OUTPUT" + echo "default_branch=$DEFAULT_BRANCH" >> "$GITHUB_OUTPUT" else echo "is_default=false" >> "$GITHUB_OUTPUT" - echo "default_branch=${{ github.event.repository.default_branch }}" >> "$GITHUB_OUTPUT" + echo "default_branch=$DEFAULT_BRANCH" >> "$GITHUB_OUTPUT" fi fi shell: bash - id: tag + env: + GITHUB_REF: ${{ github.ref }} + INPUTS_STRIP_TAG_PREFIX: ${{ inputs.strip_tag_prefix }} run: | # "Set the tag name..." - if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then - REF=$(printf "%q" "${{ github.ref }}") - TAG=${REF/refs\/tags\/${{ inputs.strip_tag_prefix }}/} + if [[ "$GITHUB_REF" == "refs/tags/"* ]]; then + REF=$(printf "%q" "$GITHUB_REF") + TAG="${REF/refs\/tags\/$INPUTS_STRIP_TAG_PREFIX/}" echo "tag=$(eval printf "%s" "$TAG")" >> "$GITHUB_OUTPUT" echo "is_tag=true" >> "$GITHUB_OUTPUT"
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-8v8w-v8xg-79rfghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-49291ghsaADVISORY
- github.com/tj-actions/branch-names/commit/4923d1ca41f928c24f1c1b3af9daaadfb71e6337ghsax_refsource_MISCWEB
- github.com/tj-actions/branch-names/commit/6c999acf206f5561e19f46301bb310e9e70d8815ghsax_refsource_MISCWEB
- github.com/tj-actions/branch-names/commit/726fe9ba5e9da4fcc716223b7994ffd0358af060ghsax_refsource_MISCWEB
- github.com/tj-actions/branch-names/security/advisories/GHSA-8v8w-v8xg-79rfghsax_refsource_CONFIRMWEB
- securitylab.github.com/research/github-actions-untrusted-inputghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.