Researchers Detail sapho11 Supply-Chain Campaign Targeting Cryptocurrency Wallet Developers

· Original article ↗

Summary

OpenSourceMalware reports that the sapho11 campaign targeted wallet projects with malicious pull requests, a credential-stealing Rust crate and maintainer phishing. The crate collected secrets during builds; two Zingo Labs pull requests remained open.

Key points

  • The report links the sapho11 GitHub account to a campaign targeting Keplr, Zcash, Vizor and Cosmos projects through pull requests, malicious packages and phishing.
  • The lwd-uri-util Rust crate, versions 0.1.0–0.1.7, used build.rs to collect environment variables, credential files, Keplr MCP vaults and keychain secrets during builds, then attempt to upload them.
  • The crate wrote collected data to a local JSON file even when upload was suppressed; the report says its opt-out did not stop collection.
  • Pull requests against Vizor attempted to exfiltrate CI and signing secrets. Another proposed AGENTS.md content that would normalize credential uploads and discourage automated reviewers from flagging them.
  • A fake security disclosure directed maintainers to a GitHub credential-phishing page hosted on Cloudflare Workers.
  • The related zip321-uri repository contained a Node.js install-hook stealer, although the report says its module configuration would likely cause it to fail on current Node.js versions as written.
  • Vizor closed all four campaign pull requests; two Zingo Labs pull requests were still open without reviews, and the report said the malicious crate had not been removed from crates[.]io.

Article Details

Attack Vectors
  • Malicious pull requests proposed sending CI environment variables and signing-related files to attacker-controlled endpoints.
  • The lwd-uri-util Rust crate used its build.rs script to collect environment variables, credential files, Keplr MCP vaults, and keychain secrets during builds.
  • The zip321-uri repository used prepare and postinstall hooks for a Node.js stealer when added as a Git dependency; the article says the hook may fail on current Node.js versions as written.
  • A fake security disclosure directed Vizor maintainers to a GitHub credential-phishing page hosted on a Cloudflare Worker.
  • Dependency changes in open Zingo Labs pull requests were obscured by whole-file CRLF rewrites, while an AGENTS.md change attempted to influence automated code reviewers.
Defensive Notes
  • If a build included lwd-uri-util, treat build-time environment variables and targeted credential files as exposed; revoke and reissue affected credentials and signing material.
  • For affected Keplr MCP vaults, move funds to freshly generated keys.
  • Search Cargo build output directories for lwd_uri_build_context.json; preserve a copy for incident response if needed, then remove it securely because it may contain plaintext secrets.
  • Review proxy, DNS, and endpoint telemetry for the listed webhook.site UUIDs and the identified .xyz and sapho11.workers.dev endpoints.
  • Review dependency build scripts and install hooks, not only application diffs; restrict secrets available to automated CI builds of pull requests.
  • Review changes to AGENTS.md and similar files with the same scrutiny as code or CI configuration.

Indicators of compromise

TypeIndicatorContext
EMAILsapho11@wp[.]plEmail address used as the author address on commits from the malicious sapho11 account.
SHA25610304aa2c167bb0d66800020fb1f983bc62bb5bec89239de9fddb129b523149aSHA-256 hash of the malicious lwd-uri-util-0.1.1.crate package.
SHA256129be19ca4d1d997d168af561e5cea12b0a401716a05720daf48072e470d7db5SHA-256 hash of the malicious lwd-uri-util-0.1.0.crate package.
SHA2563b290a899d741be14f9bb9f3545279911f774608362f348654f10823774c2f87SHA-256 hash of the malicious lwd-uri-util-0.1.5.crate package.
SHA256476a207e057ec463ff045a2c0115c8a34ea8eab70e0abe4c1efd90ceb8b5161cSHA-256 hash of the malicious lwd-uri-util-0.1.4.crate package.
SHA2565c848823a78313c47596bdf3c260e8862a02c7e48fa8ce718aca332f7b80c4fdSHA-256 hash of the malicious lwd-uri-util-0.1.6.crate package.
SHA2566d35f023e3d87f8d4bc91a3bc670ae4681e9d85937146b9b0683d0f33eb0f55aSHA-256 hash of the malicious lwd-uri-util-0.1.2.crate package.
SHA2567c0fbaf582b9b4e674c108ed5b0cb2835b11369fbdb1ce7ac29d63e9321a6981SHA-256 hash of the malicious lwd-uri-util-0.1.7.crate package.
SHA25680c54ff4fe231c363db0c75cbb81f566ea4d10c266ec594165d840df13ab0973SHA-256 hash of the malicious lwd-uri-util-0.1.3.crate package.
SHA256ac82fd28228bfb55acbb9bfdd2f3a4b926c6d65e2965db5a34c11d1a76fbd762SHA-256 hash of the src/lib.rs file from lwd-uri-util 0.1.7, part of the identified malicious crate.
SHA256c469240c313d7da0d40b901e51e642b4efd61906e28849c1059b70451065cccaSHA-256 hash of the Cargo.toml file from lwd-uri-util 0.1.7, part of the identified malicious crate.
SHA256d8671b8aed8771dba6b57bd51d2e42914c0df87bd9e9d148478a0fbc121e81e6SHA-256 hash of the HTML served by the attacker’s GitHub credential-phishing page.
SHA256f466d5621525a4cf229e4a8377cd7285da5797eee77384253f1040a722765953SHA-256 hash of the malicious lwd-uri-util 0.1.7 build.rs file.
URLhxxps[:]//api[.]sdklfghaljksdhfkjasdfhlasdhfjklasdf[.]xyz/v1/tipcheckExfiltration sink embedded in early lwd-uri-util versions; the article reports that this misspelled domain did not resolve.
URLhxxps[:]//api[.]sdklfghaljksdhfkjasdfhlkasdhfjklasdf[.]xyz/v1/tipcheckAttacker-controlled endpoint used in malicious Vizor pull request code; the article says this correctly spelled domain was prepared for the campaign.
URLhxxps[:]//github[.]com/chainapsis/vizor-wallet/pull/1199Malicious pull request that proposed sending environment data to attacker infrastructure.
URLhxxps[:]//github[.]com/chainapsis/vizor-wallet/pull/1200Malicious pull request that proposed collecting release credentials and signing files for exfiltration.
URLhxxps[:]//github[.]com/chainapsis/vizor-wallet/pull/1201Pull request that attempted to normalize uploading sensitive environment snapshots in reviewer guidance.
URLhxxps[:]//github[.]com/chainapsis/vizor-wallet/pull/1202Malicious pull request that added the lwd-uri-util dependency.
URLhxxps[:]//github[.]com/sapho11/lwd-uri-utilMalicious repository containing the lwd-uri-util crate source.
URLhxxps[:]//github[.]com/sapho11/zip321-uriMalicious repository containing a Node.js stealer intended to run through package install hooks.
URLhxxps[:]//github[.]com/zingolabs/zingo-common/pull/85Open pull request adding the malicious lwd-uri-util dependency.
URLhxxps[:]//github[.]com/zingolabs/zingolib/pull/3148Open pull request adding the malicious lwd-uri-util dependency.
URLhxxps[:]//session-check[.]sapho11[.]workers[.]dev/authCredential-phishing page impersonating GitHub sign-in and presented as a private security disclosure.
URLhxxps[:]//session-check[.]sapho11[.]workers[.]dev/auth/loginCredential collection endpoint used by the GitHub phishing page.
URLhxxps[:]//session-check[.]sapho11[.]workers[.]dev/v1/tipcheckAttacker-controlled exfiltration endpoint used by early lwd-uri-util versions.
URLhxxps[:]//webhook[.]site/0a60608b-63de-480c-a441-38a8d107a9eaAttacker-used exfiltration sink listed for lwd-uri-util versions 0.1.0–0.1.3.
URLhxxps[:]//webhook[.]site/14b3cc9b-3275-4b63-8b93-f4d2669fbdc1Attacker-used exfiltration sink for lwd-uri-util versions 0.1.4–0.1.7 and the zip321-uri stealer.

MITRE ATT&CK

T1005 · Data from Local SystemThe crate collected local environment data, credential files, signing material, and Keplr MCP vault files.T1027 · Obfuscated Files or InformationThe crate stored sink URLs and scanner-evasion keywords in base64-encoded form and decoded them at runtime.T1041 · Exfiltration Over C2 ChannelCollected JSON data was POSTed to attacker-used webhook.site and other exfiltration endpoints.T1056.003 · Web Portal CaptureThe phishing page cloned GitHub sign-in and collected usernames and passwords through a web form.T1059.001 · PowerShellOn Windows, the payload used hidden, non-interactive PowerShell with Invoke-WebRequest to upload collected data.T1059.004 · Unix ShellOn Unix-like systems, the payload launched curl through a detached /bin/sh -c command.T1059.007 · JavaScriptThe zip321-uri repository used an install.js script as a prepare and postinstall hook for its Node.js stealer.T1071.001 · Web ProtocolsThe payload communicated with its endpoints using HTTP or HTTPS requests, including POST requests carrying collected data.T1195.001 · Compromise Software Dependencies and Development ToolsThe campaign added a malicious Rust crate whose build.rs collected secrets when downstream projects built the dependency.T1497.001 · System ChecksFrom version 0.1.4, the payload suppressed network uploads when environment names or values contained sandbox and scanner canary markers.T1552.001 · Credentials In FilesThe stealer read credentials from files including .git-credentials, .netrc, .env files, and configuration files.T1552.004 · Private KeysThe Node.js stealer targeted SSH private-key files, and the Rust payload collected signing-key files.T1555.001 · KeychainOn macOS, the Rust payload used security find-generic-password to retrieve secrets from the keychain.T1566.002 · Spearphishing LinkA fake security disclosure issue sent Vizor maintainers to a credential-phishing page.T1583.001 · DomainsThe article reports that the campaign’s correctly spelled .xyz domain was registered through Namecheap two months before the sapho11 account was created.

Threat Actors

Vendors

Products

Tools

Related Articles