Fake Payment-SDK npm/PyPI Supply-Chain Campaign

21 malicious packages impersonating PaySafe / Skrill / Neteller SDKs harvest CI/CD and cloud secrets from developer & build hosts, exfiltrating to an ngrok tunnel · published 2026-07-07 · detected by Socket within ~6 min
Threat
Payment-SDK Facade Supply-Chain
Severity
HIGH Active campaign
Type
Supply-chain / Credential theft
Targets
Dev workstations & CI/CD runners
Version
v0.2 (2026-07-14)
Author
HuntPack
Confidence
High
01

Executive Summary

On 2026-07-07, Socket detected a coordinated supply-chain campaign that pushed 17 npm modules and 4 PyPI packages masquerading as SDKs for well-known payment brands — PaySafe, Skrill, and Neteller. Each npm package shipped four rapid versions (1.0.0–1.0.3); the PyPI packages shipped a single malicious 1.0.0. They were flagged malicious within roughly six minutes of publication, but any developer or CI job that installed one in that window is exposed.

The packages present a convincing SDK facade: calls immediately return { success: true, method, path } so the developer sees no error, while a delayed background routine harvests every environment variable whose name contains KEY, SECRET, TOKEN, PASS, AUTH, or API (values truncated to 100 chars), fingerprints the host, and exfiltrates to an ngrok-hosted C2. Prime targets include PAYSAFE_API_KEY, AWS_SECRET_ACCESS_KEY, GITHUB_TOKEN, and NPM_TOKEN.

The payload includes anti-analysis logic — it aborts on hosts with fewer than two CPU cores or with security keywords (sandbox, analyzer, cuckoo, vmware, vbox, malware) in the hostname/username — and hides its C2 behind a three-step decode (XOR, character shift, string reversal).

Attacker objective: steal long-lived CI/CD and cloud credentials from developer and build environments, then reuse them for downstream cloud access, further package publishing (NPM_TOKEN), or source-code access (GITHUB_TOKEN).

Defender priority: Deny the named packages in your registry proxy and scrub them from every lockfile (§7/§10); hunt Q1–Q3 for the ngrok C2 domain, the package names in install command lines, and the known payload hashes; then rotate every CI/CD and cloud secret reachable from any host that installed one — the credential exposure is the real incident, not the package file.

02

Source Review & Web Hunter Notes

TierSourceKey findingCarry fwd
2Socket (originating research)Cluster of npm+PyPI malware published 2026-07-07; 17 npm + 4 PyPI; payment-SDK facades; detected in ~6 minYes
2GBHackersEnv-var harvest (KEY/SECRET/TOKEN/PASS/AUTH/API); fake success response; ngrok C2 caliber-spinner-finishing.ngrok-free.dev:443; sandbox evasion (<2 CPU cores, security hostnames)Yes
2CyberPressConfirmed package names (paysafe-node, paysafe-checkout, skrill-payments, paysafe-sdk); XOR + char-shift + string-reversal C2 decode; 3 payload SHA-256 hashesYes

Sourcing note: This is a fresh (7-day) supply-chain event; primary attribution is Socket's automated detection, corroborated by GBHackers and CyberPress. Atomic IOCs used in this pack — the three SHA-256 payload hashes, the ngrok C2 domain, and the package names — are drawn directly from those reports and cited in §18. No indicator here is fabricated.

03

Hunt Brief & Attack Chain

Hunt hypotheses (fidelity-ordered)

#HypothesisMITRETelemetryConf
H1A host resolved the campaign's ngrok C2 domainT1071.001, T1572DnsRequestHigh
H2An install command referenced one of the malicious package namesT1195.002ProcessRollup2High
H3A known payload hash was written or executed on a hostT1195.002, T1059.007ProcessRollup2 / PeFileWrittenHigh
H4A dev/CI host reached any *.ngrok-free.dev tunnel from node/pythonT1572, T1041DnsRequestMed
H5A package manager spawned a network client during install (beacon)T1195.002, T1071ProcessRollup2Med

Attack chain

StepActionTelemetry / hunt angle
1 · DeliveryMalicious packages published to npm/PyPI under payment-brand namesRegistry audit; lockfile/manifest grep (§7)
2 · InstallDeveloper or CI installs the package (typo/confusion or dependency pull)ProcessRollup2: npm/pip CommandLine with package name (Q2)
3 · EvadePayload aborts on <2 CPU cores or security-keyword hostnames; decodes C2 (XOR/shift/reverse)Low direct telemetry — anti-sandbox is in-process
4 · HarvestReads env vars matching KEY/SECRET/TOKEN/PASS/AUTH/API; fingerprints hostIn-process (JS/Python) — not directly visible; infer from install + egress
5 · ExfilSends secrets to ngrok C2 over 443DnsRequest for C2 domain (Q1); ngrok tunnel egress (Q4)
04

Consolidated IOC Table

TypeValueConfActionContext
domaincaliber-spinner-finishing.ngrok-free.devhighdetectC2 / exfil endpoint (:443)
sha256ce09810adca70ebec87bc455380ef629ceaa2a0d926149d9115604060167682chighdetectCampaign payload
sha256b2ea8d69f6792a87327ffde2ee4551bb6b99617f53e1ba71bf9a70f45dbc57eahighdetectCampaign payload
sha2568a70a5c1075f2dea4db94633ddc64b0d03d0385fdeda7c226acc944331febf43highdetectCampaign payload
npm pkgpaysafe-checkout, paysafe-node, paysafe-jshighdetectMalicious (versions 1.0.0–1.0.3)
npm pkgskrill-payments, netellerhighdetectMalicious (brand facade)
pypi pkgpaysafe-sdk, paysafe-payments, paysafe-api, paysafe-kychighdetectMalicious (version 1.0.0)
behaviorEnv harvest of KEY/SECRET/TOKEN/PASS/AUTH/API → ngrokhighhuntCredential exfil routine
infra*.ngrok-free.dev egress from a build/CI hostmediumhuntTunnel abuse (many campaigns)

The package-name and hash IOCs are point-in-time (the packages were pulled quickly); the ngrok domain is perishable. Treat the SHA-256 and domain as short-lived detect entries and the package names primarily as a registry/lockfile audit (§7).

05

Affected Surface & Telemetry Matrix

SurfaceRequired telemetryPriorityGap risk
Developer workstations (node/python)ProcessRollup2 (install cmds), DnsRequest, NetworkConnectIP4HighPersonal/BYOD dev machines may lack sensor
CI/CD build runnersProcessRollup2, DnsRequest; CI job logsCriticalEphemeral runners / containers often unmonitored by EDR
Source repos & lockfilesManifest/lockfile content (grep) — nativeCriticalNot EDR-visible; needs SCA / repo scan
CI/CD & cloud secretsN/A — preventive (rotation, short-lived tokens)CriticalExfil is in-process; assume exposure on any install

Telemetry reality: the malicious logic runs inside the node/python interpreter, so the harvest step (env read) is not directly visible to EDR. Detection leans on the install command, the DNS/egress to C2, the payload hash, and lockfile audits — plus fast secret rotation as the real mitigation.

06

ATT&CK Mapping

TacticTechniqueObserved behaviorQuery / Control
Initial AccessT1195.002 Compromise Software Supply ChainMalicious payment-SDK packages installed from npm/PyPIQ2, Q3 · registry deny
ExecutionT1059.007 JavaScript / T1059.006 PythonPackage payload runs at import/installQ5 · --ignore-scripts
Defense EvasionT1497 Virtualization/Sandbox EvasionAborts on <2 CPU cores / security hostnames— (in-process)
Defense EvasionT1027 Obfuscated Files or InformationC2 hidden via XOR + char-shift + string-reversalQ3 (hash)
Credential AccessT1552.001 Unsecured Credentials in Files/EnvHarvests env vars matching KEY/SECRET/TOKEN/PASS/AUTH/APIsecret rotation · §12
Command & ControlT1572 Protocol Tunneling · T1071.001 Web ProtocolsExfil via ngrok tunnel over 443Q1, Q4 · egress block
ExfiltrationT1041 Exfiltration Over C2 ChannelSecrets + host fingerprint sent to ngrok C2Q1, Q4
07

Native Audit-Log Hunts (non-CQL)

The highest-value hunts for a package-supply-chain event live in your source repos, lockfiles, and registry proxy — not on the endpoint. Run these across every repo and build cache.

Lockfile / manifest audit (repos + build caches)

# Search every repo, lockfile, and node_modules/site-packages cache for the names:
paysafe-checkout  paysafe-node  paysafe-js  paysafe-sdk
paysafe-payments  paysafe-api   paysafe-kyc  skrill-payments  neteller
# Files to grep: package.json, package-lock.json, yarn.lock, pnpm-lock.yaml,
#                requirements.txt, poetry.lock, Pipfile.lock
# Any hit = a host/repo that pulled the package -> treat as exposed, rotate its secrets.

Registry proxy / SCA logs

# In Artifactory/Nexus/Verdaccio or your SCA tool, query download events for the
# package names above since 2026-07-07. Map each download to a host / CI job / user.

CI/CD secret exposure & provider abuse

# For every host that installed a package: enumerate which secrets were in its env
# (KEY/SECRET/TOKEN/PASS/AUTH/API) and rotate them. Then review provider-side logs:
#   - GitHub: audit log + token usage for GITHUB_TOKEN
#   - AWS: CloudTrail for the AWS_SECRET_ACCESS_KEY principal
#   - npm: publish events for NPM_TOKEN

Step 3–4 (sandbox evasion + env harvest) run inside the interpreter and leave little endpoint telemetry — the lockfile/registry audit is what actually scopes the blast radius. Pair it with the DNS/egress hunts (Q1, Q4) to catch hosts that reached the C2.

08

CrowdStrike LogScale CQL Hunt Queries

Pick your tenant's cloud first — every "Open in Falcon" button below uses this selection.
Q1 · DNS resolution of the campaign C2 (ngrok tunnel)
CONF HIGHFP LOWCOST LOW

Looks for: any host resolving the campaign's exact ngrok C2 domain — a direct, high-fidelity exfil indicator.

// HUNT: DNS resolution of the payment-SDK campaign C2 (ngrok tunnel)
// CONF: high  FP: low  COST: low | REQUIRES: DnsRequest telemetry
#event_simpleName=DnsRequest
| DomainName=/(^|\.)caliber-spinner-finishing\.ngrok-free\.dev$/i
| table([ComputerName, DomainName, ContextBaseFileName, aid], limit=200)
Q2 · Install command references a malicious package
CONF HIGHFP LOWCOST LOW

Looks for: a package-manager process whose command line contains one of the known-malicious package names — catches the install even where the C2 was unreachable.

// HUNT: npm/pip install command referencing a known-malicious payment-SDK package
// CONF: high  FP: low  COST: low | REQUIRES: process telemetry with CommandLine
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| ParentBaseFileName=/^(node|npm|npx|yarn|pnpm|pip[0-9.]*|python[0-9.]*)$/i
| CommandLine=/(paysafe-checkout|paysafe-node|paysafe-js|paysafe-sdk|paysafe-payments|paysafe-api|paysafe-kyc|skrill-payments|neteller)/i
| table([ComputerName, UserName, ParentBaseFileName, CommandLine, aid], limit=200)
Q3 · Known payload present by SHA-256
CONF HIGHFP LOWCOST LOW

Looks for: the three published payload hashes written or executed on any host.

// HUNT: Known payment-SDK malware payload by SHA256
// CONF: high  FP: low  COST: low | REQUIRES: process or file-write telemetry with hashes
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2|PeFileWritten|NewExecutableWritten/
| SHA256HashData=/^(ce09810adca70ebec87bc455380ef629ceaa2a0d926149d9115604060167682c|b2ea8d69f6792a87327ffde2ee4551bb6b99617f53e1ba71bf9a70f45dbc57ea|8a70a5c1075f2dea4db94633ddc64b0d03d0385fdeda7c226acc944331febf43)$/i
| table([ComputerName, UserName, FileName, SHA256HashData, aid], limit=200)
Q4 · Dev/CI host reaching any ngrok-free tunnel
CONF MEDFP MEDCOST LOW

Looks for: node/python resolving any *.ngrok-free.dev tunnel — a broader net for campaign infrastructure rotation. FP: some developers use ngrok legitimately.

// HUNT: Node/Python process resolving an ngrok free tunnel (staged-package exfil)
// CONF: medium  FP: medium  COST: low | REQUIRES: DnsRequest with process context
// TUNING: allowlist developers/teams with sanctioned ngrok use; scope to build/CI host groups first
#event_simpleName=DnsRequest
| DomainName=/\.ngrok-free\.dev$/i
| ContextBaseFileName=/^(node|npm|npx|python[0-9.]*|pip[0-9.]*)$/i
| table([ComputerName, DomainName, ContextBaseFileName, aid], limit=200)
Q5 · Package manager spawns a network client during install
CONF MEDFP MEDCOST LOW

Looks for: an install-time process spawning a network client — the shape of a post-install beacon. FP: many legitimate postinstall scripts fetch binaries.

// HUNT: npm/pip install spawning a network client (post-install exfil beacon)
// CONF: medium  FP: medium  COST: low | REQUIRES: process telemetry
// TUNING: exclude known-good postinstall build steps and internal registry mirrors; scope to CI host groups
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| ParentBaseFileName=/^(npm|npx|yarn|pnpm|pip[0-9.]*)$/i
| FileName=/^(curl|wget|nc|ncat|socat|node|python[0-9.]*)$/i
| table([ComputerName, UserName, ParentBaseFileName, FileName, CommandLine, aid], limit=200)
09

CrowdStrike Custom IOA Recommendations

IOA / controlPatternExclusionsAction
Malicious Package InstallCommandLine of npm/pip contains a name from the campaign listNone (names are attacker-chosen)Detect (high) → alert IR
Campaign C2 IOCDomain + 3 SHA-256 as Falcon Custom IOCsNoneDetect/Prevent (short expiry)
ngrok Egress from CI*.ngrok-free.dev from a build-runner host groupSanctioned ngrok users/teamsDetect → review

Deployment path: load the domain + hashes as Custom IOCs immediately (short expiry — they are perishable). Promote Q2 to a detection; keep Q4/Q5 as hunts until tuned. The durable control is the registry deny-list + secret rotation, not the IOC block.

10

Machine-Readable IOC Appendix

Falcon IOC Management CSVbulk import
type,value,action,severity,expiration,description,tags
domain,caliber-spinner-finishing.ngrok-free.dev,detect,high,2026-10-14,Payment-SDK campaign C2,campaign:PaymentSDK-SupplyChain
sha256,ce09810adca70ebec87bc455380ef629ceaa2a0d926149d9115604060167682c,prevent,high,2027-01-14,Payment-SDK payload,campaign:PaymentSDK-SupplyChain
sha256,b2ea8d69f6792a87327ffde2ee4551bb6b99617f53e1ba71bf9a70f45dbc57ea,prevent,high,2027-01-14,Payment-SDK payload,campaign:PaymentSDK-SupplyChain
sha256,8a70a5c1075f2dea4db94633ddc64b0d03d0385fdeda7c226acc944331febf43,prevent,high,2027-01-14,Payment-SDK payload,campaign:PaymentSDK-SupplyChain
Malicious Package Listregistry deny / lockfile grep
# npm:
paysafe-checkout
paysafe-node
paysafe-js
skrill-payments
neteller
# PyPI:
paysafe-sdk
paysafe-payments
paysafe-api
paysafe-kyc
Behavioral Signaturesharvest & exfil
# Env-var name patterns harvested (truncated to 100 chars):
KEY  SECRET  TOKEN  PASS  AUTH  API
# High-value targets: PAYSAFE_API_KEY, AWS_SECRET_ACCESS_KEY, GITHUB_TOKEN, NPM_TOKEN
# Exfil: HTTPS to *.ngrok-free.dev (C2 decoded via XOR + char-shift + string-reversal)
# Anti-analysis: aborts if CPU cores under 2 OR hostname/user contains
#   sandbox | analyzer | cuckoo | vmware | vbox | malware
CI/Dev Hardening Auditprevent recurrence
# Confirm these are in place after remediation:
npm ci --ignore-scripts            # CI installs do not run postinstall
pip install --require-hashes ...   # hash-pinned installs
# Registry proxy allow-list enabled; named packages denied
# Egress allow-list on build runners (registries only; no ngrok)
# CI secrets are short-lived OIDC tokens, not long-lived KEY/TOKEN env values
11

Detection Validation Gates

GateCheckPass criteria
Telemetry readyDnsRequest + ProcessRollup2 flowing from dev and CI host groupsRecent events visible for representative hosts
IOC loadedDomain + 3 SHA-256 imported as Custom IOCsQ1/Q3 have data to match; IOC status active
Positive testIn a lab, run npm install paysafe-node (from a private stub) and a DNS lookup to the C2Q1 & Q2 fire
BaselineRun Q4/Q5 over 7 daysAllowlist sanctioned ngrok / postinstall before alerting
Scope completeLockfile/registry audit (§7) run across all reposEvery install mapped to a host; its secrets rotated
12

Hardening — Tiered

Immediate (this week)
  • Deny the named packages in your registry proxy and remove them from every lockfile / build cache. (MITRE M1042 Disable or Remove Feature or Program)
  • Rotate every CI/CD and cloud secret reachable from any host that installed a package (GITHUB_TOKEN, NPM_TOKEN, AWS keys, PAYSAFE_API_KEY, etc.). (key hygiene; supports M1027)
  • Block egress to *.ngrok-free.dev from build runners and, where feasible, from developer networks. (M1037 Filter Network Traffic)
  • Load the domain + 3 hashes as Custom IOCs (short expiry) and hunt Q1–Q3. (M1021 / detection)
Near term (1–4 weeks)
  • Front all installs with a private registry proxy (Artifactory/Nexus/Verdaccio) on an allow-list; enable SCA/Socket scanning that blocks newly-published, low-reputation packages. (M1016 Vulnerability Scanning)
  • Disable install-time scripts in CInpm ci --ignore-scripts, hash-pinned pip installs — so a malicious package can't auto-execute. (M1038 Execution Prevention)
  • Replace long-lived CI secrets with short-lived OIDC tokens, minimally scoped, so a harvested value expires fast. (M1026 Privileged Account Mgmt · M1041 Encrypt Sensitive Information)
Strategic (1–3 months)
  • Enforce lockfile integrity + dependency pinning + provenance (npm provenance / SLSA attestations) in CI so unexpected packages fail the build. (best-practice — SLSA / OpenSSF) no formal benchmark
  • Network-isolate build runners with egress allow-listed to package registries only. (M1030 Network Segmentation)
  • Continuous secret scanning + automated rotation across repos and CI. (M1016)
13

Deployable Playbooks

1 · Purge & deny the packages

# Remove any installed copy and scrub lockfiles, then reinstall clean:
npm uninstall paysafe-checkout paysafe-node paysafe-js skrill-payments neteller
pip uninstall -y paysafe-sdk paysafe-payments paysafe-api paysafe-kyc
# Registry proxy deny-list (Verdaccio example): add the names under an unmatched
# package rule so they can never resolve internally.
# Clear caches so a poisoned copy is not reused:
npm cache clean --force
pip cache purge

2 · Harden CI install steps

# package installs must NOT run arbitrary scripts:
npm ci --ignore-scripts
# python: pin hashes so only vetted artifacts install:
pip install --require-hashes -r requirements.txt
# Egress allow-list on the runner (example iptables intent): permit registry
# endpoints only; drop everything else, including ngrok.

3 · Rotate & verify exposed secrets

# For each host that installed a package, for each secret in its env matching
# KEY|SECRET|TOKEN|PASS|AUTH|API:
#   1. Issue a replacement (prefer short-lived OIDC).
#   2. Revoke the old value.
#   3. Review provider logs for use since 2026-07-07:
#        GitHub audit log (GITHUB_TOKEN), AWS CloudTrail (access keys),
#        npm publish events (NPM_TOKEN).
14

Containment Runbook

PhaseActionsOwnerEvidence
ScopeGrep all repos/lockfiles/registry logs for the 9 package names; run Q1–Q3 across dev + CI hosts to find installs and C2 contactThreat Hunt / AppSecRepo hits; query exports
IsolateBlock *.ngrok-free.dev egress; deny packages in registry; quarantine any host with a Q3 hash hitSOC / PlatformEgress + registry rule changes
EradicateUninstall packages; clear npm/pip caches; rebuild affected CI images from clean basePlatform / DevUninstall + cache-clean logs
RotateRotate ALL secrets reachable from any affected host (CI/CD, cloud, VCS, npm); prefer short-lived tokensIAM / PlatformRotation record
Verify abuseReview GitHub/AWS/npm provider logs for use of exposed tokens since 2026-07-07IR / CloudProvider log review
RecoverRe-enable installs behind registry allow-list + --ignore-scripts; monitor Q1/Q2 as detectionsPlatform / SOCCI config; detection status
15

Detection Coverage Map

TechniqueBehaviorCQLIOA/IOCCoverage
T1195.002Malicious package installedQ2, Q3YesGood
T1071.001 / T1572C2 / exfil to ngrokQ1, Q4IOCGood
T1041Secret exfiltrationQ1, Q4Partial (payload/DNS only)
T1552.001Env-var credential harvestGAP (in-process)
T1497Sandbox evasionGAP (in-process)
T1059.007/.006Post-install executionQ5Partial

Known gaps: (1) The env-var harvest and anti-sandbox checks run inside the node/python interpreter and produce no discrete EDR event — they are covered only indirectly (install + C2 + hash) and, decisively, by secret rotation. (2) Ephemeral CI runners often lack an EDR sensor, so the lockfile/registry audit (§7) is the authoritative scoping method, not CQL. (3) Q4/Q5 are FP-prone (legit ngrok / postinstall fetches) — tune before alerting.

16

Hunt Summary Ticket

TITLE:      Fake Payment-SDK npm/PyPI Supply-Chain Campaign (PaySafe/Skrill/Neteller)
SEVERITY:   High — active credential-theft supply-chain campaign (published 2026-07-07)
SCOPE:      Dev workstations + CI/CD runners that installed a package since 2026-07-07
HYPOTHESIS: A host installed a malicious payment-SDK package and exfiltrated env
            secrets (KEY/SECRET/TOKEN/PASS/AUTH/API) to an ngrok C2.
QUERIES:    Q1 C2 DNS · Q2 package-name install · Q3 payload hash
            Q4 ngrok tunnel · Q5 install-time net client · native lockfile audit (s7)
DO FIRST:   1) Grep all repos/lockfiles for the 9 package names
            2) Load domain + 3 SHA-256 as Custom IOCs; run Q1-Q3
            3) Rotate every secret on any host that installed one
FINDINGS:   ____________________________________________________________
GAPS:       Env harvest + sandbox evasion in-process; ephemeral CI runners unmonitored
ACTIONS:    Deny packages · block ngrok egress · rotate secrets · --ignore-scripts in CI
OWNER:      ____________________          VERSION: v0.2 (2026-07-14)
17

Changelog

v0.22026-07-24CQL correctness pass. All table() calls now carry an explicit row limit: the default is 200 and truncation is silent, so a capped result was indistinguishable from a complete one. Atomic-IOC sweeps (filters over 5+ hashes or C2 IPs) use limit=max so a wide infection is never silently under-scoped; behavioural hunts use limit=200, where exceeding the cap indicates the query needs tuning. Where present, event names that do not exist in the Falcon data model were corrected (e.g. ServiceInstalled is a Sysmon concept, not a Falcon event; ElfFileWritten is ELFFileWritten) — such queries could never return a row. No detection logic, fields, or IOCs changed.
v0.12026-07-14Initial HuntPack — 5 CQL queries, lockfile/registry native audits, IOC set (C2 domain + 3 payload hashes + 9 package names), tiered hardening, containment runbook.
18

References

TierSourceUsed forAccessed
2GBHackers — npm and PyPI malware campaign exfiltrates CI/CD secretsEnv-var harvest, ngrok C2 domain, sandbox evasion, package names2026-07-14
2CyberPress — Fake SDKs target developersPackage names, obfuscation chain, 3 SHA-256 payload hashes2026-07-14
2Upwind — npm/PyPI supply-chain campaignCampaign scope / CI-CD targeting context2026-07-14

Generated 2026-07-14 · HuntPack · Defensive detection & hardening content only. No victim organizations named.