On May 18, 2026, between roughly 11:36 and 17:48 UTC, an automated campaign now tracked as Megalodon pushed 5,718 malicious commits into 5,561 distinct GitHub repositories. Every commit did the same thing: it added or modified a GitHub Actions workflow file carrying a base64-encoded bash payload designed to vacuum CI secrets and cloud credentials out of the runner and ship them to a single command-and-control endpoint. The whole campaign ran in a six-hour window, which is the part that should worry CI/CD owners most. This was not a careful, hand-crafted intrusion. It was a script.
What makes Megalodon different from the high-profile GitHub Actions incidents of the past year is the entry vector. The tj-actions and reviewdog compromises of 2025 worked by poisoning a popular third-party action that thousands of victims trusted transitively. Megalodon did not bother. It logged directly into thousands of victim accounts using credentials that infostealer malware had already scraped from developer machines, then committed a workflow straight into each repository. The supply chain here is not a shared dependency. It is the developer endpoint, and the commodity infostealer market that monetizes it.
This post walks through the verified facts as reported by SafeDep, StepSecurity, and Hudson Rock, the mechanics of the workflow injection (including the clever use of workflow_dispatch to keep a backdoor dormant), the secrets at risk, and what detection and remediation look like for any team running GitHub Actions at scale.
TL;DR
- An automated campaign codenamed Megalodon pushed 5,718 commits into 5,561 GitHub repositories on May 18, 2026, in a roughly six-hour window.
- Each commit injected a GitHub Actions workflow containing a base64-encoded bash payload that exfiltrates CI secrets, cloud credentials, SSH keys, and OIDC tokens to a C2 server at
216.126.225[.]129:8443. - The attacker did not exploit a software flaw. They authenticated with valid GitHub credentials sourced from infostealer logs. Hudson Rock reported that a large share of the abusive accounts mapped to machines previously infected by infostealers.
- Two payload variants were observed: SysDiag (triggered on every push and pull request) and Optimize-Build (triggered only via
workflow_dispatch, leaving a dormant backdoor that can be activated later via the GitHub API). - Forged author identities (build-bot, auto-ci, ci-bot, pipeline-bot) and throwaway accounts with random eight-character usernames were used to blend the commits into normal CI noise.
- No CVE applies. This is a credential-and-automation problem, not a vulnerability. The fix is endpoint hygiene, credential rotation, phishing-resistant MFA, and workflow-change detection, not a patch.
What happened
According to SafeDep, which discovered and analyzed the campaign, the attacker injected GitHub Actions workflow files into thousands of repositories within a single six-hour window on May 18, 2026. SafeDep counted 5,718 malicious commits across 5,561 unique repositories. The commits arrived from throwaway accounts using random eight-character usernames (observed examples include rkb8el9r, bhlru9nr, and lo6wt4t6) and forged commit author identities chosen to look like automation: build-bot, auto-ci, ci-bot, and pipeline-bot.
The crucial question for any incident like this is how the attacker got write access to so many repositories at once. Hudson Rock's investigation answered it: the accounts enabling Megalodon were sourced from infostealer data. A significant fraction of the unique usernames involved matched computers previously compromised by infostealer malware, the kind that scrapes browser-stored session cookies, saved credentials, and local token caches. The attacker did not phish anyone in real time and did not exploit a GitHub vulnerability. They bought or harvested working credentials and tokens, then automated commits at scale.
Once a malicious workflow landed in a repository, the next qualifying CI event executed the payload. The payload decoded a base64 bash blob and ran it inside the GitHub-hosted runner, where it enumerated and exfiltrated everything that looked like a secret. The collected data was sent over the network to a command-and-control server at 216.126.225[.]129 on port 8443.
StepSecurity independently documented the same campaign, framing it as mass GitHub Actions secret exfiltration across more than 5,500 public repositories. The convergence of three independent research teams (SafeDep, StepSecurity, and Hudson Rock) on the same facts is what gives this incident a high confidence level despite the absence of an official GitHub advisory at the time of writing.
How the attack worked
The mechanics break into three stages: account takeover, workflow injection, and exfiltration with optional dormancy.
Stage 1: account takeover via infostealer logs
The attacker started with valid credentials. Infostealer malware (Lumma, RedLine, Vidar, and the broader commodity market) routinely captures GitHub session tokens, OAuth tokens, and gh CLI credentials from infected developer machines. These end up in bulk logs sold or traded in criminal markets. With a working session token or personal access token, the attacker has the same push rights the developer has, and no MFA prompt fires because the session is already authenticated.
This is the structural reason Megalodon scaled. The attacker did not need to defeat GitHub's authentication. They inherited it.
Stage 2: workflow injection
For each compromised account, the automation committed a GitHub Actions workflow file. The payload was a base64-encoded bash command embedded in a run step. An illustrative, non-functional sketch of the shape of such a workflow:
# Illustrative reconstruction, not the real payload. Do not run.
name: Optimize-Build
on:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: optimize
run: echo "<base64-encoded-bash-here>" | base64 -d | bash
The decoded bash enumerated the runner environment and harvested credentials. Because GitHub Actions runners expose secrets to job steps as environment variables and mounted files, a single run step with shell access can read almost everything the workflow is authorized to use.
Stage 3: exfiltration and the workflow_dispatch dormancy trick
Two payload variants were observed. SysDiag triggered on every push and pull request, meaning it fired immediately and noisily on the next CI event. Optimize-Build was the more interesting one. It used the workflow_dispatch trigger, which only runs when manually invoked through the GitHub UI or the REST API.
This choice is deliberate and clever. A workflow_dispatch-only workflow sits dormant. It does not run on normal repository activity, so it does not generate the telemetry that would flag it during routine CI. The attacker can then trigger it on demand later via the GitHub API using a stolen token. As SafeDep noted, workflow_dispatch is also exempt from GitHub's anti-recursion rules that normally prevent a workflow from being spawned by GITHUB_TOKEN-triggered events, which makes it a reliable remote-execution primitive for a backdoor.
The harvested secrets, per the reporting, spanned AWS credentials, Google Cloud access tokens, SSH private keys, Docker and Kubernetes configurations, HashiCorp Vault tokens, Terraform credentials, GitHub Actions OIDC tokens, GITHUB_TOKEN, GitLab and Bitbucket tokens, generic API keys, database connection strings, and more than thirty distinct secret patterns. All of it was POSTed to 216.126.225[.]129:8443.
What detection looks like
Megalodon is noisy in some ways and quiet in others. The injection event itself leaves a clear trail; the dormant backdoor does not. Useful signals:
- New or modified
.github/workflows/*.ymlfiles in commits authored by accounts you do not recognize, especially commits whose author name is generic automation (build-bot, auto-ci, ci-bot, pipeline-bot) but whose committer account is an unfamiliar eight-character username. - Workflow
runsteps that pipe base64 intobase64 -d | bashorsh, or any step that decodes and executes inline content. Treat inlineeval/decode-and-pipe constructs in CI as a high-severity finding. - New workflows that declare only
on: workflow_dispatchand were not added through your normal pull request process. A manually-triggerable workflow that nobody on the team added is a backdoor until proven otherwise. - Outbound network connections from CI runners to
216.126.225[.]129on port 8443, or to any unexpected raw IP on a high port. CI egress should be allowlisted; raw-IP egress to a high port is anomalous. - A burst of commits across many repositories in a short window from the same or similar throwaway accounts. Org-level audit log review for the May 18 window is the fastest way to confirm or rule out exposure.
A practical first query, using the GitHub CLI, to find recently changed workflow files across an org:
# Illustrative. Lists repos and inspects recent workflow changes.
gh api -X GET "/orgs/<your-org>/repos?per_page=100" --jq '.[].full_name' \
| while read repo; do
gh api "/repos/$repo/commits?path=.github/workflows&since=2026-05-17T00:00:00Z" \
--jq '.[] | {sha: .sha, author: .commit.author.name, login: .author.login}'
done
Review any commit where login is an unfamiliar account or author.name is generic CI automation that your team does not use.
What to do Monday morning
Ordered by urgency.
- Check the org audit log for the May 18, 2026 window. Look for pushes to
.github/workflows/from accounts you do not recognize. If you find none across the six-hour window, your exposure to the injection event is low. If you find any, treat every secret that workflow could read as compromised. - Rotate exposed CI secrets immediately if you find injected workflows. Assume any credential reachable from the affected runner is burned: cloud keys, registry tokens, SSH keys, Vault and Terraform credentials, and the repository's
GITHUB_TOKENscope. Rotate before you delete the workflow, so the attacker cannot re-trigger a dormant variant against still-valid secrets. - Search every repository for
workflow_dispatch-only workflows that nobody added. These are the dormant backdoors. Removing a noisy SysDiag variant while leaving a dormant Optimize-Build variant in place leaves the door open. - Force-expire active sessions and rotate personal access tokens for any developer whose machine may be infostealer-compromised. Because the entry vector is stolen sessions, password resets alone are insufficient. Invalidate sessions and reissue tokens.
- Require phishing-resistant MFA and short-lived tokens for repository write access. Session-token theft defeats password MFA. Hardware-backed passkeys and short token lifetimes shrink the window in which a stolen credential is useful.
- Add a branch-protection or required-review rule for changes to
.github/workflows/. A workflow file is executable code with access to your secrets. It should never merge without review. - Restrict CI runner egress to an allowlist. If runners cannot reach arbitrary high-port IPs, exfiltration to a C2 like
216.126.225[.]129:8443fails even when the payload runs.
Why this keeps happening
The recurring lesson of 2025 and 2026 CI/CD incidents is that a GitHub Actions workflow is arbitrary code execution with standing access to your most sensitive secrets, and the controls around who can add or change a workflow are weaker than the controls around the code those secrets protect. Teams gate production deploys behind review, change management, and approvals, then let a single committed YAML file run shell with full secret access on the next push.
Megalodon adds a second structural failure: the developer endpoint is now a reliable supply-chain entry point. The commodity infostealer market has industrialized credential theft to the point where an attacker can acquire thousands of working GitHub sessions and automate abuse at machine speed. The six-hour, 5,561-repository blast radius is what credential-driven automation looks like. There was no novel exploit. There was a script, a list of stolen tokens, and an API.
The combination is brutal: standing secret access inside CI, weak change controls on workflow files, and a bottomless supply of stolen credentials. Any team that depends on humans noticing a malicious commit in real time has already lost, because the attacker is not operating at human speed.
The structural fix
Shortening dwell time and reducing blast radius here comes down to seeing workflow changes the moment they land and knowing which of them can actually reach a privileged secret. Safeguard inventories every GitHub Actions workflow across your repository fleet and flags newly added or modified workflows, including the workflow_dispatch-only variants that the dormant Megalodon backdoor relied on, so a workflow nobody on the team added does not sit unnoticed until it is triggered. Reachability analysis identifies which repositories actually expose privileged cloud credentials and OIDC tokens to their workflows, so rotation and response prioritize real exposure rather than chasing all 5,000-plus repositories equally. Policy enforcement can require review on any change under .github/workflows/ and block merges that introduce decode-and-execute steps. None of this prevents an attacker from logging in with stolen credentials, but it collapses the time between injection and detection from "whenever someone happens to read the diff" to the next scan.
What we know we don't know
At the time of writing there is no official GitHub advisory enumerating the full victim list, so the 5,561 figure reflects what SafeDep observed rather than a vendor-confirmed total. It is not publicly confirmed how many of the dormant workflow_dispatch backdoors were ever triggered, nor how many victims have completed credential rotation. The specific infostealer families behind the underlying credential theft are reported in aggregate by Hudson Rock rather than attributed to a single strain. And while the C2 IP and port are documented, the downstream use of the exfiltrated secrets (resale, further intrusion, or ransomware staging) is not yet public.
References
- SafeDep: Megalodon - Mass GitHub Repo Backdooring via CI Workflows
- StepSecurity: Megalodon - Mass GitHub Actions Secret Exfiltration Across 5,500+ Public Repositories
- The Hacker News: Megalodon GitHub Attack Targets 5,561 Repos with Malicious CI/CD Workflows
- SecurityWeek: Over 5,500 GitHub Repositories Infected in 'Megalodon' Supply Chain Attack
- Infostealers.com: Infostealers Just Spawned a 5,000+ Repo GitHub Supply Chain Attack
- The Register: Megalodon chums the waters in 5.5K+ GitHub repo poisonings
Internal reading: