Skip to content

Commit 7b3c0a5

Browse files
authored
blog: ghost action (#18705)
1 parent 3721466 commit 7b3c0a5

File tree

1 file changed

+83
-0
lines changed

1 file changed

+83
-0
lines changed
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
title: Token Exfiltration Campaign via GitHub Actions Workflows
3+
description: Incident report of a recent attack campaign targeting GitHub Actions workflows to exfiltrate PyPI tokens, our response, and steps to protect your projects.
4+
authors:
5+
- miketheman
6+
date: 2025-09-16
7+
tags:
8+
- security
9+
- transparency
10+
---
11+
12+
## Summary
13+
14+
I recently responded to an attack campaign where malicious actors injected code into GitHub Actions workflows
15+
attempting to steal PyPI publishing tokens.
16+
PyPI was not compromised, and no PyPI packages were published by the attackers.
17+
18+
Attackers targeted a wide variety of repositories, many of which had PyPI tokens stored as GitHub secrets,
19+
modifying their workflows to send those tokens to external servers.
20+
While the attackers successfully exfiltrated some tokens, they do not appear to have used them on PyPI.
21+
22+
I've invalidated all affected tokens and notified the impacted project maintainers.
23+
If you're one of them, I have emailed you from <[email protected]>.
24+
25+
<!-- more -->
26+
27+
You can read more about the details of the attack on [GitGuardian's blog](https://blog.gitguardian.com/ghostaction-campaign-3-325-secrets-stolen/).
28+
29+
## Timeline and Response
30+
31+
On September 5th, a GitGuardian employee used the [PyPI "Report as malware" button](./2024-03-06-malware-reporting-evolved.md)
32+
to submit their findings for a project named `fastuuid` - namely they found a malicious GitHub Actions workflow
33+
attempting to exfiltrate PyPI tokens to a remote server.
34+
No compromise on PyPI was found, tokens relating to the user accounts were invalidated,
35+
and I reached out to the project owners to notify and help secure the account and project.
36+
37+
Later on September 5th, another researcher from GitGuardian emailed PyPI Security
38+
directly about their current findings, effectively an expansion of the previous attack.
39+
Due to some of the contents in that email, it ended up in our inbound Spam folder,
40+
delaying response until September 10th when I became aware of the attack via other channels,
41+
and found the original email in the Spam folder.
42+
I may follow up with our support system provider to see about improving spam filtering rules.
43+
44+
After triaging the situation, I discovered another Indicator of Compromise (IoC) in the form of a URL,
45+
which I shared with GitGuardian to assist with their ongoing investigation.
46+
47+
Over the course of the following few days, I reviewed the findings from the researchers.
48+
I observed that many of the project maintainers responded to notifications from the researchers on their open source issue trackers,
49+
either reverting the changes to their actions workflows,
50+
or removing the affected workflows entirely from history via force-push of the repository.
51+
Many of the maintainers also proactively rotated their PyPI tokens.
52+
53+
After confirming that no PyPI accounts had been compromised,
54+
on September 15th I reached out to the maintainers of the affected projects to notify them of the situation,
55+
to let them know that their tokens had been invalidated,
56+
and recommend using [Trusted Publishers](https://docs.pypi.org/trusted-publishers/)
57+
with GitHub Actions to help protect their projects in the future.
58+
59+
## What You Can Do
60+
61+
If you use GitHub Actions to publish to PyPI, I recommend the following steps to protect your projects:
62+
63+
1. Replace long-lived tokens with [Trusted Publishers](https://docs.pypi.org/trusted-publishers/.
64+
This is the most effective way to protect your projects from this type of attack.
65+
GitHub Trusted Publishers use short-lived tokens that are scoped to a specific repository,
66+
and expire after a short period of time.
67+
2. Log into your account and review your security history for any suspicious activity.
68+
You can do this by going to your [Account Settings](https://pypi.org/manage/account/)
69+
and scrolling to the ["Security History" section](https://pypi.org/manage/account/#account-events).
70+
71+
While Trusted Publisher tokens can still be exfiltrated,
72+
using Trusted Publishers significantly reduces the risk of compromise.
73+
74+
## Acknowledgements
75+
76+
Thanks to Charles Brossollet, Guillaume Valadon, and Gaëtan Ferry
77+
of [GitGuardian](https://www.gitguardian.com/) for their collaboration on this issue.
78+
79+
This investigation and incident response is made possible by the generosity of individuals and corporations
80+
supporting critical security efforts to better secure the Python community,
81+
with thanks to [Alpha-Omega](https://alpha-omega.dev/).
82+
83+
Support these efforts and more here: <https://www.python.org/sponsors/application/>

0 commit comments

Comments
 (0)