Aephix accepted into the Databricks Startup Program
← Research
Threat report Sep 17, 2026

n8n-nodes-social-facebook: Go WASM binary harvests Facebook Business credentials

The npm package n8n-nodes-social-facebook v0.2.0 distributes an 8 MB Go-compiled WebAssembly binary renamed from .wasm to .we that targets Facebook Business Manager tokens, user access tokens, and Ads Manager credentials through the Graph API v23.0. Quota enforcement and plan-gated access suggest credential harvesting as a managed service.

The npm package n8n-nodes-social-facebook v0.2.0, published under the account kerituni12, ships an 8 MB Go-compiled WebAssembly binary inside what presents as an n8n community node for Facebook automation. The binary targets Facebook Business Manager tokens, user access tokens, and Ads Manager credentials through the Graph API v23.0 and persists stolen sessions to the host filesystem. A built-in quota manager enforces plan-based rate limits and syncs with a remote server, consistent with a credential-harvesting service operated for multiple customers rather than a single attacker’s personal use.

The artifact

n8n-nodes-social-facebook v0.2.0 was first published on Sep 13, 2025 under the npm account kerituni12. The package.json repository field points to the botzvn GitHub organization. The n8n manifest declares two workflow nodes (Facebook.node.js, FacebookHttpRequest.node.js) and one credential provider (FacebookApi.credentials.js), all present under dist/nodes/Meta/ and dist/credentials/Meta/.

The files array also ships entries absent from any legitimate n8n node: dist/main.we (8,051,620 bytes), dist/we.js (145 KB), and a dist/utils/ directory with eight modules including init.js, common.js, debug-auth.js, rup.js, and wasm-utils.js. Roughly 63,000 _0x hex-index variable names span the thirteen shipped JavaScript files, all processed by gulp-javascript-obfuscator with RC4 string encryption. we.js is an obfuscated copy of Go’s standard wasm_exec.js runtime, a file normally shipped as readable source. Runtime dependencies include socks-proxy-agent and https-proxy-agent, neither required by n8n’s built-in HTTP client.

What it does

init.js runs at module load and injects Node.js built-in modules as named global variables: fs, os, path, and zlib. A fifth global provides node-fetch wrapped with HttpsProxyAgent and SocksProxyAgent, giving the binary outbound HTTP through configurable proxies. The Go WASM runtime has no native I/O imports. All 23 WASM imports are standard gojs bridge functions (syscall/js.valueCall, syscall/js.valueGet). These globals break the sandbox. The binary reaches the host filesystem, network, and OS through the JavaScript bridge.

we.js instantiates the Go WASM runtime and loads main.we from disk using the fs global that init.js placed. The .we extension is a renamed .wasm: the file begins with standard \x00asm magic bytes. Renaming it avoids scanner heuristics that match on the .wasm extension.

String extraction from main.we reveals the Go module path gowasm with subpackages core, config, handler, facebook, services, and httpclient, backed by 36 Go source files recovered from debug symbols. The binary harvests three classes of Facebook credential by scraping page HTML with regex: user access tokens matching EAAB via window\.__accessToken, page access tokens via Graph API exchange, and ads user access tokens matching EAAG from the Ads Manager onboarding page. Session parameters (fb_dtsg, jazoest, __hsi, __spin_t, compat_iframe_token) are scraped from live Facebook responses using dedicated extraction patterns. The binary also reads the Business Manager inbox (FetchUsersInboxJS), sends messages as stolen pages (SendPageMessageWithApiKeyJS), modifies post privacy (SetPostPrivacyJS via CometPrivacySelectorSavePrivacyMutation), and publishes Reels through a four-step upload pipeline. All API calls target graph.facebook.com/v23.0, business.facebook.com, adsmanager.facebook.com, and vupload-edge.facebook.com.

Stolen sessions persist to .fb_sessions.json in the user’s home directory, encrypted with ChaCha20-Poly1305 AEAD via a SecureHiddenStorage layer that also uses RC4 and a custom Base64 encoding for key material. Anti-tamper checks refuse operations when the encryption key has changed or data integrity fails. Quota data is cached separately in .q.dat and .n8n_q_cache. The binary manages a full session lifecycle: creation, retrieval by type and by ID, refresh via cookie rotation (RefreshFacebookSessionJS), and bulk clearing.

rup.js imports child_process.execFile, writes a buffer to a temp file in os.tmpdir(), executes it, and cleans up with fs.unlinkSync. The export is named uploadReelFb, framing it as video processing, but the capability is unconstrained: the WASM binary can trigger arbitrary command execution on the host.

debug-auth.js exports validateDebugAuthKey. It splits an input into a timestamp and signature, computes HMAC with a hardcoded secret (six concatenated obfuscated fragments), and verifies via crypto.timingSafeEqual. Keys are valid for 60 seconds. This provides the operator a time-limited authenticated backdoor.

n8n-nodes-social-facebook v0.2.0 n8n community node (npm) init.js exposes fs, os, path main.we (8 MB Go WASM binary) Loaded by obfuscated we.js Facebook Graph API v23.0 User, page, ads tokens .fb_sessions.json Persists to home directory Remote quota server SyncQuotaWithServer Aephix
The community node breaks the WASM sandbox by injecting Node.js globals, then loads a Go binary that harvests Facebook Business credentials and syncs quota with a remote server.

The campaign

The quota server is a Cloudflare Workers endpoint at hxxps://quota-service-worker[.]kerituni123[.]workers[.]dev, contacted via the /get-and-save path using a dedicated SimpleHTTPClient separate from the Facebook-facing HTTP client. HandleApiKeyAndQuotaCheck fires before every Facebook API operation. The binary sends a userId and receives an APIKeyInfo struct containing apiKey, teamId, deviceId, permissions, and lastSyncTime. ProcessQuotaCheckAndIncrement increments a usage counter before allowing each action. When the counter exceeds the plan limit: “Quota limit exceeded: Used %d/%d requests. Please upgrade your plan.”

Team-based licensing ("Invalid API key for user %s team %s"), per-device tracking, and a permissions field for feature gating are not features a lone attacker builds. The n8n community node is a distribution channel for a credential-harvesting operation that sells tiered access to compromised Facebook Business accounts. The proxy agent dependencies allow operators or their customers to route API calls through rotating proxies, reducing the chance that Facebook ties the traffic to a single origin.

Why the operation matters here

Removing n8n-nodes-social-facebook from the registry takes out one delivery vehicle. The operator’s Go WASM codebase, quota server, and proxy infrastructure remain intact for repackaging. The Go build ID, the gowasm module path, and the quota protocol are stable selectors for the operation’s tooling across future artifacts under different names.

IndicatorValue
Packagen8n-nodes-social-facebook v0.2.0
npm accountkerituni12
npm shasume78a3aa89bcbac6408bb8c0a7902f8d7efa80e44
GitHub orgbotzvn
C2 endpointhxxps://quota-service-worker[.]kerituni123[.]workers[.]dev
C2 path/get-and-save
WASM binarydist/main.we (8,051,620 bytes, renamed .wasm)
SHA-256 (main.we)9e4c888c36a9c8e5da7958f5cccb2672849a90939af85d1993db206004ecaa29
SHA-256 (we.js)e4a80ec115a5fcb9df46b8327b2cbb57c62d86b3e7867ac8ea2185cf130d25bc
SHA-256 (init.js)17d055dfeec498d32a54c417a8c7b87164da295958fa9c6afdefd28ab00bda3d
SHA-256 (debug-auth.js)6c5dd915295d8890ee0089e572322cf58b2588dbd9d9d90d997f593679201454
Go build IDTidBu8BKCLbD4fWIrrkT/Dyk0hepIo_ucc0Jc1kdm/VVeUmeTqF0L4USntkCxN/EaJ86auSW9yFT3VECzM9
VCS revision7acabc12f2975c6c0ba5831ad8c12fbca7c260e2
Go modulegowasm (7 subpackages, 36 source files)
Session file~/.fb_sessions.json
Quota files~/.q.dat, ~/.n8n_q_cache
Token regex (user)window\.__accessToken\s*=\s*"(EAAB[^"]+)"
Token regex (ads)\["(EAAG\w+)
DTSG regex"DTSGInitialData",\[\],\{[\s\S]*?"token":"([^"]+)"
Targeted APIgraph.facebook.com/v23.0, business.facebook.com, adsmanager.facebook.com, vupload-edge.facebook.com
Proxy depssocks-proxy-agent, https-proxy-agent

What a defender can do

Uninstall n8n-nodes-social-facebook and delete any dist/main.we file on the host. Check for and remove .fb_sessions.json, .q.dat, and .n8n_q_cache from every home directory on n8n runner machines. Revoke all Facebook user, page, and ads access tokens from Meta Business Settings, then rotate any credentials stored in n8n’s credential manager for Facebook integrations. Audit installed n8n community nodes for WASM binaries, .we files, or gulp-javascript-obfuscator in their dependency trees. None of these steps reveal whether other packages from the same operation are already installed under a different name.

Where Aephix fits

The build ID and quota protocol that identify this operation’s tooling can reappear in unrelated package names. Before you install a community node or connect to any automation server, Aephix Vantage gives you a free, cross-ecosystem view of what is already known to be malicious, so a package with a hostile history is visible before it reaches your workflow runner. Every week, Weekly Sleuth reports the malicious packages, models, skills, MCP servers, extensions, and containers confirmed that week alongside the wider operations behind them, with a confidence level and supporting evidence, so subscribers act against the operation rather than the single artifact.