Skip to content

Secrets exfiltration via `pull_request_target`

Critical
alexander-schranz published GHSA-3jpv-mmxc-xr8x Jul 16, 2025

Package

PHP-CMSIG/search

Affected versions

no-version-effected

Patched versions

no-version-effected

Description

Summary

Using pull_request_target on .github/workflows/docs.yml, checking out the head.sha of a forked PR can be exploited by attackers, since untrusted code can be executed from the PR having full access to secrets (from the base repo) without any maintainer interaction. By exploiting the vulnerability is possible to exfiltrate the GITHUB_TOKEN. This GITHUB_TOKEN, having content: write permissions, can be abused to completely overtake the repo.

Details

The pull_request_target in GitHub Actions is a major security concern - especially in public repositories - because it executes untrusted code from a PR, but with the context of the base repository, including access to its secrets.

on:
    pull_request_target:

Along with code checkout on head.sha, an attacker is able to control the code and change the workflow to execute random code:

              - name: Checkout project
              uses: actions/checkout@v4
              with:
                  ref: "${{ github.event.pull_request.head.sha }}"

POC

An attacker could leverage the Install dependency step inside the workflow .github/workflows/integration_tests.yml to run arbitrary code:

            - name: Install dependencies
              run: |
                  pip install -r docs/requirements.txt

By locally adding in the PR a malicious python package, which gets installed in the docs/requirements.txt step, an attacker could get a shell on the github action workflow, and could consequently exfiltrate the GITHUB_TOKEN secret.
To prove this token was privileged we created a tag named poc-v1.1.55 which has been deleted after 2 minutes.

Screenshot 2025-07-10 alle 12 02 22

Impact

Usually a GITHUB_TOKEN with contents: write permissions allows an attacker a wide range of ways to completely overtake the repo:

GITHUB_TOKEN Permissions
  Contents: write
  Metadata: read

Kindly reported by @AlbertoPellitteri and @darryk10

Patches

Because of requirements of secrets we had to keep the pull_request_target, instead we updated Github Organisation settings to change permissions in https://github.com/organizations/PHP-CMSIG/settings/actions the Workflow permissions to Read repository contents and packages permissions.

Additional we did split the build and deploy process up into 2 different CI Jobs. Only the deploy which runs only on merged Pull Requests and so reviewed changes have write permission to update github pages.

Best Regards @alexander-schranz

References

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
None
User interaction
None
Scope
Unchanged
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:N/UI:N/S:U/C:H/I:H/A:N

CVE ID

No known CVE

Weaknesses

Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')

The product constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component. Learn more on MITRE.

Credits