### Summary
Using pull_request_target
on .github/workflows/integration_tests.yml
followed by the checking out the head.sha of a forked PR can be exploited by attackers, since untrusted code can be executed having full access to secrets (from the base repo). By exploiting the vulnerability is possible to exfiltrate GITHUB_TOKEN
and secrets SPOTIPY_CLIENT_ID
, SPOTIPY_CLIENT_SECRET
. In particular GITHUB_TOKEN
which can be used to completely overtake the repo since the token has content write privileges.
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.
pull_request_target:
types: [opened, synchronize, reopened]
Along with code checkout on head.sha, an attacker is able to control the code and change the workflow to execute random code.
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
PoC
An attacker has multiple injection point inside the workflow .github/workflows/integration_tests.yml
.
By adding in the repo a malicious python package it's possible to install it via workflow pip install .
and execute the malicious code.
To prove this is possible we did a test by adding a malicious packaged to extract the GITHUB_TOKEN
. With the token extracted I was able to create a testing tag pga-v1.1.55 which has been deleted after 2 minutes.

Impact
Usually with GITHUB_TOKEN and write permissions, an attacker is able to completely overtake the repo.
GITHUB_TOKEN Permissions
Actions: write
Attestations: write
Checks: write
Contents: write
Deployments: write
Discussions: write
Issues: write
Metadata: read
Models: read
Packages: write
Pages: write
PullRequests: write
RepositoryProjects: write
SecurityEvents: write
Statuses: write
Fix
We suggest to remove pull_request_target
from all the workflows and more importantly to remove/fix it in all branches that contain it, or manage to use it properly without checking out untrusted code.
We also advice to properly set the GITHUB_TOKEN permissions properly based on that the workflow needs to do, restricting what it's not necessary.
Kindly reported by @AlbertoPellitteri and @darryk10
References
### Summary
Using
pull_request_target
on.github/workflows/integration_tests.yml
followed by the checking out the head.sha of a forked PR can be exploited by attackers, since untrusted code can be executed having full access to secrets (from the base repo). By exploiting the vulnerability is possible to exfiltrateGITHUB_TOKEN
and secretsSPOTIPY_CLIENT_ID
,SPOTIPY_CLIENT_SECRET
. In particularGITHUB_TOKEN
which can be used to completely overtake the repo since the token has content write privileges.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.Along with code checkout on head.sha, an attacker is able to control the code and change the workflow to execute random code.
PoC
An attacker has multiple injection point inside the workflow

.github/workflows/integration_tests.yml
.By adding in the repo a malicious python package it's possible to install it via workflow
pip install .
and execute the malicious code.To prove this is possible we did a test by adding a malicious packaged to extract the
GITHUB_TOKEN
. With the token extracted I was able to create a testing tag pga-v1.1.55 which has been deleted after 2 minutes.Impact
Usually with GITHUB_TOKEN and write permissions, an attacker is able to completely overtake the repo.
Fix
We suggest to remove
pull_request_target
from all the workflows and more importantly to remove/fix it in all branches that contain it, or manage to use it properly without checking out untrusted code.We also advice to properly set the GITHUB_TOKEN permissions properly based on that the workflow needs to do, restricting what it's not necessary.
Kindly reported by @AlbertoPellitteri and @darryk10
References