Microsoft Threat Intelligence has uncovered an active supply chain attack involving malicious npm packages registered under organizational scopes that mirror real internal corporate namespaces, employing dependency confusion technique to deploy an obfuscated reconnaissance payload.
On May 28 and May 29, 2026, a threat actor operating under three maintainer aliases mr.4nd3r50n (mr.4nd3r50n@yandex[.]ru), ce-rwb (ogvanta@yandex[.]ru), and t-in-one (t-in-one@yandex[.]ru) published malicious packages across two publishing bursts. The packages impersonate internal corporate packages across nine different organizational scopes using a dependency confusion technique, and several spoof internal enterprise infrastructure URLs (GitHub Enterprise, Jira, documentation portals) in their package.json to appear legitimate. Once installed, the packages download and execute an obfuscated reconnaissance payload from an attacker-controlled command-and-control (C2) server.
All packages in the cluster ship the same heavily obfuscated postinstall stager and connect to the same C2 endpoint, a ~17 KB JavaScript dropper used for for environment fingerprinting and credential reconnaissance. The payload runs silently during npm install and operates in “reconnaissance-only” mode, collecting system information, hostnames, environment variables, and developer context. The architecture includes a RECON_ONLY flag that can be toggled server-side for full exploitation in follow-on attacks. Based on our investigation and feedback to the npm team these repos and users were taken down.
Key capabilities observed in the campaign include automatic execution through npm lifecycle hooks, obfuscator.io-style anti-analysis techniques, platform-specific payload delivery (Windows, macOS, Linux), continuous integration and continuous delivery (CI/CD) environment detection and bypass, cache-based deduplication to evade repeated-execution monitoring, and a two-phase attack design (reconnaissance now, exploitation later).
The campaign spans dozens of scoped packages published under three npm maintainer accounts that our forensic analysis attributes to a single operator (detailed in the Attribution section below). The attack proceeds through:

The actor adopted three social-engineering techniques designed to drive installs through misconfigured package managers or developer trust transference:
The attacker registered packages under organizational scopes that mirror real internal corporate namespaces: @cloudplatform-single-spa, @wb-track, @data-science, @ce-rwb, @payments-widget, @travel-autotests, @t-in-one, @capibar.chat, and @sber-ecom-core. Package names like svp-baas, enterprise, monitoring, ssh-keys, shared-front, payments-widget-sdk, add_application_service_token, ui-kit, and sberpay-widget target specific internal services — the last of which directly impersonates Sberbank’s SberPay payment widget.
Every package sets its package.json homepage, repository, bugs, and author fields to fabricated but realistic-looking internal infrastructure URLs. For example:
These URLs follow the pattern of enterprise GitHub, Jira, and documentation portals, lending an air of legitimacy designed to evade casual inspection during code review.
mr.4nd3r50n uses version 100.100.100, an absurdly high version number designed to win npm’s server resolution against any real internal package version. ce-rwb uses a more realistic 3.5.22 to blend in with legitimate release histories. t-in-one mixes both tactics: the ten @t-in-one packages ship at 5.7.1, while @capibar.chat/ui-kit (99.5.7) and @sber-ecom-core/sberpay-widget (99.5.8) use inflated numbers — and both of the latter scopes were pre-staged with 99.0.7 releases on 2026-05-04, weeks before the main bursts.

npm install. Version 100.100.100 ensures the malicious package wins dependency resolution over any real internal version.Every package in the cluster declares an automatic install-time hook in package.json:
"scripts": {
"build": "tsc --noEmit || true",
"test": "node test/index.test.js",
"postinstall": "node scripts/postinstall.js",
"prepublishOnly": "echo 'Building...'"
}
The malicious code executes the moment a victim runs npm install; no require() from victim code is needed. The build and test scripts are cosmetic, designed to make the package appear to have a legitimate development workflow.
scripts/postinstall.js is approximately 7 KB of heavily obfuscated JavaScript using obfuscator.io-style techniques:

The deobfuscated execution flow proceeds through eight distinct stages:

The environment variables passed to the spawned payload reveal a deliberate two-phase attack architecture:
| Variable | Purpose |
| *_RECON_ONLY | Set to “1” by default; limits payload to reconnaissance |
| *_PKG | Identifies which internal package triggered the execution |
| *_VER | Package version for campaign tracking |
| *_SECRET | Hard-coded authentication token for C2 communication |
The RECON_ONLY flag is hard-coded to “1” in the current campaign, indicating the attacker is in Reconnaissance — collecting environment information, hostnames, installed packages, and developer context. The architecture supports a Full exploitation mode where the flag can be toggled server-side to enable data exfiltration, credential theft, or backdoor installation on previously fingerprinted targets.
This two-phase design is sophisticated: it minimizes the risk of detection during initial deployment while building a target inventory for selective, high-value exploitation later.
Forensic analysis of npm registry metadata across every package in the cluster provides high-confidence evidence that the three accounts (mr.4nd3r50n, ce-rwb, and t-in-one) are operated by the same individual. The single strongest piece of evidence is a shared hardcoded authentication value, l95HdDaz3kQx1Zsg3WxH6HvKANf51RY1, sent as the X-Secret HTTP header on every outbound C2 request from every package in all three accounts.

Both accounts’ payloads connect to the exact same C2 server: https://oob.moika[.]tech/payload. Sharing offensive infrastructure across “separate” personas is the strongest single indicator of a single operator. Maintaining separate C2 servers would be trivial, so using the same one indicates the shared infrastructure supports our assessment that the activity is associated with a single operator.
mr.4nd3r50n’s early versions (v99.99.99) were published with Node.js 20.20.1 / npm 10.8.2. ce-rwb’s packages were published with Node.js 20.20.0 / npm 10.8.2. t-in-one’s @t-in-one packages were published with Node.js 20.20.1 / npm 10.8.2 — matching mr.4nd3r50n exactly. The minor variance across the three accounts suggests the same machine at slightly different patch levels, or a small set of machines configured from the same provisioning script.
Both actors use the exact same templating system for generating fake package metadata:
This level of template consistency, down to identical changelog entries across every package, including the @t-in-one README that points developers at a fabricated internal registry at npm.t-in-one[.]io with matching docs.t-in-one[.]io and jira.t-in-one[.]io references — indicates a single automated package generator.
mr.4nd3r50n published 26 packages between 18:47–18:51 UTC on May 28. ce-rwb published 7 packages between 19:02–19:03 UTC on May 28 — a 12-minute gap consistent with one person completing one publishing batch, switching npm accounts, and starting the next. t-in-one returned the following day, publishing 10 @t-in-one packages between 09:01:56 and 09:02:39 UTC on May 29 (a 43-second automated burst), with the @capibar.chat and @sber-ecom-core republishes following minutes later. The ~14-hour overnight gap between ce-rwb and t-in-one, paired with the unchanged C2 host and identical X-Secret, indicates the same operator returning to expand the campaign rather than a separate group.
The @cloudplatform-single-spa/logaas package reveals a critical piece of the actor’s history:

This timeline shows mr.4nd3r50n began as a bug bounty researcher probing npm dependency confusion in April 2024 followed by the malicious packages observed in this campaign.y approximately two years later. The ce-rwb account has no prior publishing history, suggesting it was created specifically for the May 2026 campaign as a secondary persona to broaden the attack surface across additional organizational scopes.
All packages use the scope @cloudplatform-single-spa:
| Package | Description |
| svp-baas | Database/Backend-as-a-Service |
| enterprise | Enterprise platform |
| vpn | VPN service |
| monitoring | Monitoring platform |
| dataplatform-trino | Trino data platform |
| marketplace-gigachat | GigaChat marketplace |
| support | Support tools |
| svp-s3-storage | S3 storage service |
| ml-ai-agents-agent | ML/AI agents |
| ssh-keys | SSH key management |
| security-groups | Security groups |
| employees | Employee directory |
| cp-api-gw | API gateway |
| base-static-page | Static page framework |
| administration | Administration panel |
| ml-ai-agents-agent-system | AI agent system |
| arenadata-db | ArenaData database |
| business-solutions | Business solutions |
| dataplatform-metastore | Data metastore |
| cloud-dns | Cloud DNS |
| dataplatform | Data platform |
| datagrid | Data grid |
| floating-ips | Floating IP management |
| cnapp-ui | CNAPP security UI |
| svp-interfaces | SVP interfaces |
| logaas | Logging-as-a-Service |
| Package | Scope Targeted |
| @wb-track/shared-front | WB-Track (warehouse/logistics tracking) |
| @data-science/llm | Data Science / LLM platform |
| @ce-rwb/ce-tools-editor-admin | CE-RWB internal editor tools |
| @ce-rwb/ce-tools-editor-render | CE-RWB internal editor tools |
| @ce-rwb/ce-tools-editor-core | CE-RWB internal editor tools |
| @payments-widget/payments-widget-sdk | Payments processing SDK |
| @travel-autotests/npm-proto | Travel platform test protobuf |
t-in-one returned on May 29 with a third npm account, t-in-one (t-in-one@yandex[.]ru), and expanded the campaign across three previously unused scopes. The ten @t-in-one package names are deliberately credential- and token-themed so they read as internal auth modules; @capibar.chat/ui-kit is a textbook dependency confusion artifact against an internal UI kit; and @sber-ecom-core/sberpay-widget directly impersonates Sberbank’s SberPay payment widget — making the campaign’s financial-sector targeting explicit. Unlike the May 28 wave, the May 29 stager ships a three-layer-obfuscated postinstall (~13 KB) and adds a functional T_IN_ONE_NO_TELEMETRY kill switch and a run-once marker directory at ~/.cache/._t-in-one_init/. The C2 host, payload endpoints, and hardcoded X-Secret value are identical to the May 28 wave.
| Package | Scope Targeted |
| @t-in-one/add_application | T-in-one — credential/auth module |
| @t-in-one/add_app_middleware_token | T-in-one — credential/auth module |
| @t-in-one/get_application_hid | T-in-one — credential/auth module |
| @t-in-one/form_product_token | T-in-one — credential/auth module |
| @t-in-one/application_id_storage_key_token | T-in-one — credential/auth module |
| @t-in-one/only_difference_payload | T-in-one — credential/auth module |
| @t-in-one/prefill_credit_data_token | T-in-one — credential/auth module |
| @t-in-one/prefill_bundle_data_token | T-in-one — credential/auth module |
| @t-in-one/add_application_tid | T-in-one — credential/auth module |
| @t-in-one/add_application_service_token | T-in-one — credential/auth module |
| @capibar.chat/ui-kit | Capibar Chat — internal UI kit |
| @sber-ecom-core/sberpay-widget | Sberbank — impersonation of SberPay payment widget |
Microsoft recommends the following mitigations to reduce the impact of this threat:
Microsoft Defender Antivirus detects and blocks the obfuscated postinstall stager and the detached recon payload on access. During reproduction in our analysis environment, the dropped ._<scope>_init.js stager was automatically quarantined the moment the package tarball was extracted to disk, preventing the C2 beacon to oob.moika[.]tech and blocking the platform-specific second-stage download. Microsoft Defender for Endpoint provides additional behavior-based coverage for the npm lifecycle script-abuse and detached child-process patterns observed in this campaign.
Microsoft Defender XDR customers can refer to the list of applicable detections below. Microsoft Defender XDR coordinates detection, prevention, investigation, and response across endpoints, identities, email, and apps to provide integrated protection against attacks like the threat discussed in this blog. Customers with provisioned access can also use Microsoft Security Copilot in Microsoft Defender to investigate and respond to incidents, hunt for threats, and protect their organization with relevant threat intelligence.
| Tactic | Observed activity | Microsoft Defender coverage |
| Execution | Suspicious script execution during npm install or package lifecycle activity tied to the affected scopes | Microsoft Defender Antivirus – Trojan:JS/ObfusNpmJs.SA Microsoft Defender for Endpoint |
| Defense Evasion | Three-layer-obfuscated postinstall.js (obfuscator.io + custom base64 + integer-shuffle string table) and install-time kill switch (T_IN_ONE_NO_TELEMETRY) | Microsoft Defender Antivirus – Trojan:JS/ObfusNpmJs Microsoft Defender for Endpoint |
| Credential Access | Reconnaissance and potential harvesting of environment variables, tokens, and developer secrets via the detached payload | Microsoft Defender for Endpoint – Credential access attempt – Suspicious cloud credential access by npm-spawned process – Environment variable enumeration indicative of credential access Microsoft Defender for Cloud |
| Command and Control | Outbound HTTPS connections from build systems or developer machines to oob.moika[.]tech carrying the hardcoded X-Secret header | Microsoft Defender for Endpoint – Connection to a custom network indicator – Suspicious outbound connection from Node.js process to low-reputation domain |
| Persistence | Run-once marker directory at ~/.cache/._t-in-one_init/ and ._<scope>_init.js payloads dropped in os.tmpdir() and launched with detached: true | Microsoft Defender for Endpoint – Suspicious persistence file creation in user cache directory – Detached Node.js process surviving parent npm install exit |
Microsoft Security Copilot is embedded in Microsoft Defender and provides security teams with AI-powered capabilities to summarize incidents, analyze files and scripts, summarize identities, use guided responses, and generate device summaries, hunting queries, and incident reports.
Customers can also deploy AI agents, including the following Microsoft Security Copilot agents, to perform security tasks efficiently:
Security Copilot is also available as a standalone experience where customers can perform specific security-related tasks, such as incident investigation, user analysis, and vulnerability impact assessment. In addition, Security Copilot offers developer scenarios that allow customers to build, test, publish, and integrate AI agents and plugins to meet unique security needs.
Microsoft Defender XDR customers can reference the Threat analytics report for this campaign in the Microsoft Defender portal at https://security.microsoft.com/threatanalytics3 for the latest indicators, recommended actions, and mitigation status across their estate.
The following sample queries let you search for a week’s worth of events. To explore up to 30 days of raw data, go to the Advanced Hunting page > Query tab, and update the time range to Last 30 days.
Hunt for suspicious npm lifecycle script execution involving the affected scopes.
Searches for Node.js and npm activity involving install lifecycle behavior and references to the nine affected scoped packages.
DeviceProcessEvents
| where FileName in~ ("node.exe", "npm.cmd", "npm.exe", "npx.cmd", "npx.exe")
| where ProcessCommandLine has_any ("preinstall", "postinstall", "install")
| where ProcessCommandLine has_any (
"@cloudplatform-single-spa", "@wb-track", "@data-science",
"@ce-rwb", "@payments-widget", "@travel-autotests",
"@t-in-one", "@capibar.chat", "@sber-ecom-core")
| project Timestamp, DeviceName, FileName, ProcessCommandLine,
InitiatingProcessFileName, InitiatingProcessCommandLine,
AccountName
Hunt for affected package versions in software inventory.
Searches device software inventory for any installed packages from the affected scopes.
DeviceTvmSoftwareInventory
| where SoftwareName has_any (
"cloudplatform-single-spa", "wb-track", "data-science",
"ce-rwb", "payments-widget", "travel-autotests",
"t-in-one", "capibar.chat", "sber-ecom-core")
| project DeviceName, OSPlatform, SoftwareVendor, SoftwareName,
SoftwareVersion
Hunt for outbound C2 activity to oob.moika[.]tech.
Searches for any device network connection to the campaign C2 host.
DeviceNetworkEvents
| where Timestamp > ago(7d)
| where RemoteUrl has "oob.moika.tech"
or RemoteUrl has_any ("npm.t-in-one.io", "docs.t-in-one.io",
"jira.t-in-one.io")
| project Timestamp, DeviceName, RemoteUrl, RemoteIP, RemotePort,
InitiatingProcessFileName, InitiatingProcessCommandLine,
AccountName
Hunt for suspicious outbound activity from Node.js processes.
Searches for network connections initiated by Node.js or npm processes referencing the affected scopes or node_modules paths.
DeviceNetworkEvents
| where InitiatingProcessFileName in~ ("node.exe", "npm.exe", "npx.exe")
| where InitiatingProcessCommandLine has_any (
"@cloudplatform-single-spa", "@wb-track", "@data-science",
"@ce-rwb", "@payments-widget", "@travel-autotests",
"@t-in-one", "@capibar.chat", "@sber-ecom-core", "node_modules")
| project Timestamp, DeviceName, RemoteUrl, RemoteIP,
InitiatingProcessFileName, InitiatingProcessCommandLine,
AccountName
Hunt for dropped stager payloads in temp and cache directories.
Searches device file events for the ._<scope>_init.js payload pattern and the May 29 run-once marker directory.
DeviceFileEvents
| where Timestamp > ago(7d)
| where FileName matches regex @"^\._.*_init\.js$"
or FolderPath has_any (
".cache/._cloudplatform-single-spa_init",
".cache/._wb-track_init",
".cache/._t-in-one_init")
| project Timestamp, DeviceName, FolderPath, FileName, ActionType,
InitiatingProcessFileName, InitiatingProcessCommandLine
Hunt for the campaign-wide X-Secret header in outbound HTTP traffic.
Searches for outbound web traffic carrying the hardcoded X-Secret value used by all three operator accounts (requires TLS decryption or proxy logging that captures request headers or bodies).
DeviceNetworkEvents
| where Timestamp > ago(7d)
| where AdditionalFields has "l95HdDaz3kQx1Zsg3WxH6HvKANf51RY1"
or RemoteUrl has "oob.moika.tech"
| project Timestamp, DeviceName, RemoteUrl, RemoteIP, AdditionalFields,
InitiatingProcessFileName, InitiatingProcessCommandLine
Hunt for affected dependency references in developer directories.
Searches for package manifest or lockfile activity referencing the affected scoped packages.
DeviceFileEvents
| where FileName in~ ("package.json", "package-lock.json", "yarn.lock",
"pnpm-lock.yaml", ".npmrc")
| where FolderPath has_any ("node_modules", "src", "repo", "workspace")
| where AdditionalFields has_any (
"@cloudplatform-single-spa", "@wb-track", "@data-science",
"@ce-rwb", "@payments-widget", "@travel-autotests",
"@t-in-one", "@capibar.chat", "@sber-ecom-core")
| project Timestamp, DeviceName, FolderPath, FileName,
InitiatingProcessFileName, InitiatingProcessCommandLine
| Indicator | Type | Description |
| mr.4nd3r50n | npm maintainer | Threat actor (mr.4nd3r50n) — 26 packages, May 28 wave |
| ce-rwb | npm maintainer | Threat actor (ce-rwb) — 7 packages, May 28 wave |
| mr.4nd3r50n@yandex[.]ru | mr.4nd3r50n contact email | |
| ogvanta@yandex[.]ru | ce-rwb contact email | |
| t-in-one | npm maintainer | Threat actor (t-in-one) — 12 packages across @t-in-one, @capibar.chat, @sber-ecom-core, May 29 wave |
| t-in-one@yandex[.]ru | t-in-one contact email | |
| l95HdDaz3kQx1Zsg3WxH6HvKANf51RY1 | Shared secret | Hardcoded X-Secret HTTP header value sent on every outbound C2 request from all three accounts — single-operator attribution marker |
| npm.t-in-one[.]io | Lure domain | Fabricated internal-registry hostname referenced in @t-in-one README to lend legitimacy |
| docs.t-in-one[.]io / jira.t-in-one[.]io | Lure domain | Fabricated documentation and issue-tracker hostnames in @t-in-one package metadata |
| `oob.moika[.]tech` | Domain | C2 server for payload delivery |
| `https://oob.moika[.]tech/payload/win` | URL | Windows payload endpoint |
| `https://oob.moika[.]tech/payload/mac` | URL | macOS payload endpoint |
| `https://oob.moika[.]tech/payload/linux` | URL | Linux payload endpoint |
| Indicator | Type | Description |
| `scripts/postinstall.js` | Filename | Obfuscated stager (~7 KB) |
| `._cloudplatform-single-spa_init.js` | Filename | Dropped payload in tmpdir |
| `._wb-track_init.js` | Filename | Dropped payload (ce-rwb variant) |
| `~/.cache/._cloudplatform-single-spa_init/` | Directory | Cache/dedup directory |
| `~/.cache/._wb-track_init/` | Directory | Cache/dedup directory (ce-rwb) |
| `*_RECON_ONLY=1` | Env var | Reconnaissance mode flag |
| `*_PKG` | Env var | Package name identifier |
| `*_VER` | Env var | Package version identifier |
| `*_SECRET` | Env var | C2 authentication token |
| ._t-in-one_init.js | Filename | Dropped payload in tmpdir — t-in-one (May 29 wave) |
| ~/.cache/._t-in-one_init/ | Directory | Run-once marker directory used by the May 29 stager for per-host deduplication |
| T_IN_ONE_NO_TELEMETRY | Env var | Functional install-time kill switch honored by the May 29 obfuscated stager (the May 28 *_NO_TELEMETRY variables are README fiction only) |
| X-Secret: l95HdDaz3kQx1Zsg3WxH6HvKANf51RY1 | HTTP header | Hardcoded authentication header sent on every outbound C2 request from all three accounts |
For the latest security research from the Microsoft Threat Intelligence community, check out the Microsoft Threat Intelligence Blog.
To get notified about new publications and to join discussions on social media, follow us on LinkedIn, X (formerly Twitter), and Bluesky.
To hear stories and insights from the Microsoft Threat Intelligence community about the ever-evolving threat landscape, listen to the Microsoft Threat Intelligence podcast.
Review our documentation to learn more about our real-time protection capabilities and see how to enable them within your organization.