Threat · curated 8 Sep 2026

When “Auto-Signing” Sends Your Wallet: A Malicious MCP Server on npm

Dossier

Coverage timeline

8 Sep 2026knostic.aiprimary

Single-source incident — first reported, latest, and curated coincide.

Why it matters

The gadgethumans-mcp package shows how a malicious MCP server distributed through npm can weaponize AI-agent "auto-signing" to silently exfiltrate crypto wallet private keys, removing the human-in-the-loop safeguard and giving attackers full control of victim funds.

The npm package `gadgethumans-mcp` (version 1.0.9) is a malicious MCP server that claims to "auto-sign" x402 crypto micropayments but performs no local signing; when a WALLET_PRIVATE_KEY is configured it copies the raw private key into an X-402-Wallet HTTP header and transmits it to an attacker-controlled endpoint (hxxps://swarm.gadgethumans[.]com/api/x402/execute) on every recognized MCP tool call. A recipient of the exfiltrated key can seize control of the wallet and move its assets.

campaign

Summary

Knostic's AgentMesh, with threat-intelligence partner Nextron, identified gadgethumans-mcp, a malicious Model Context Protocol (MCP) server distributed on npm that promises to 'auto-sign' x402 micropayments but instead exfiltrates the developer's raw cryptocurrency wallet private key. When WALLET_PRIVATE_KEY is set, the package copies the key verbatim into an X-402-Wallet HTTP header and transmits it to an attacker-controlled endpoint (by default swarm.gadgethumans.com/api/x402/execute) on every recognized MCP tool call — undisclosed behavior that would let the recipient move any assets controlled by that wallet.[0]

The deception is verifiable in a single 287-line index.js file: the package declares three signing-capable libraries (viem, @x402/core, @x402/evm) but imports none of them and contains no local signing, so the key is never used to produce a signature — it is simply forwarded. The package appeared under two GitHub repositories (removed scotia1973-bot/gadgethumans-mcp version 1.0.3 and still-public gadgethumans-dev/gadgethumans-mcp version 1.0.9) with byte-for-byte identical runtime code, part of a broader nine-package GadgetHumans ecosystem across npm and PyPI.[0]

gadgethumans-mcp recorded 2,327 downloads across July and August 2026 and the wider ecosystem recorded 7,028; however these counts include scanners, crawlers and CI and do not represent unique users or confirmed victims. Analysis was static only, no funds theft or victims were confirmed, and statements about the author's intent are analyst assessments rather than confirmed findings.[0]

Attack chain

  1. Distribution / Staging: The attacker publishes gadgethumans-mcp to npm (version 1.0.9 published 2026-08-02) with README, smithery.yaml and server.json manifests that instruct users to configure WALLET_PRIVATE_KEY for 'automatic' x402 payments, presenting a plausible micropayment use case. The same code was previously distributed under the removed scotia1973-bot repository as version 1.0.3.[0]
  2. Victim configuration / Credential capture setup: A developer installs the MCP server and sets WALLET_PRIVATE_KEY in their environment, expecting local auto-signing. The package reads the key directly from process.env.WALLET_PRIVATE_KEY into WALLET_KEY.[0]
  3. Trigger: When any recognized MCP tool call is handled and a wallet key is configured, the package selects the /execute endpoint (default swarm.gadgethumans.com/api/x402/execute) rather than the ordinary /mcp endpoint.[0]
  4. Exfiltration: The package copies the raw private key verbatim into the X-402-Wallet header (alongside X-402-Agent and X-402-Expected-Cost) and sends it via fetch() to the attacker endpoint on every outbound tool-call request, with no hashing, signing, or transformation applied.[0]
  5. Potential impact: A recipient of a valid private key could create new signatures, authorize transactions, and move the assets controlled by the associated wallet account; the key cannot be reset while preserving the same wallet address. No stolen funds or victims were confirmed.[0]

Disclosure timeline

DateEvent
July 2026gadgethumans-mcp records 1,152 npm downloads during the month; the wider ecosystem records the bulk of its two-month activity.[0]
2026-08-02T08:17:40ZVersion 1.0.9 of gadgethumans-mcp is published to npm.[0]
2026-08-02T08:20:05ZMatching public GitHub commit (618b5d8b125794a708339124571c6a9338a2f126) is created under gadgethumans-dev/gadgethumans-mcp, about two and a half minutes after npm publication.[0]
August 2026gadgethumans-mcp records a further 1,175 npm downloads (2,327 total across the two months).[0]
8 September 2026Knostic publishes its analysis; version 1.0.9 remains the latest published npm version, a follow-up check finds no new PyPI releases, and the gadgethumans-dev repository remains public.[0]

Actor profile

GadgetHumans ecosystem operators (scotia1973-bot / gadgethumans-dev / scottyg73)

An unattributed operator (or operators) behind the GadgetHumans ecosystem, spanning the GitHub accounts scotia1973-bot (removed) and gadgethumans-dev (public), the npm account publishing @gadgethumans/x402 and @gadgethumans/pay2commit, and the PyPI account scottyg73 that maintained six related packages. Shared branding, the gadgethumans.com domains, and x402 references link the infrastructure to the same project, though the byte-identical code across two GitHub accounts does not prove both accounts were operated by the same person. Only gadgethumans-mcp was confirmed to transmit raw private keys; the other packages are treated as related infrastructure. Author intent could not be established via static analysis.[0]

How it works

In the standard x402 flow the client signs a payment authorization locally using the wallet private key and sends only the signed Payment Payload (e.g. in a PAYMENT-SIGNATURE header); the key never leaves the machine. gadgethumans-mcp inverts this: index.js lines 11-13 read WALLET_PRIVATE_KEY into WALLET_KEY, lines 195-197 route tool calls to ENDPOINT/execute when a key is present, and lines 204-208 assign WALLET_KEY directly to the X-402-Wallet header with no hashing, address derivation, or signing. Lines 215-224 then POST the request — including that header — to the remote endpoint inside the MCP tool-call handler, so the raw key is sent on every recognized tool call.[0]

The contradiction is corroborated by unused dependencies: package.json (lines 40-45) declares @x402/core, @x402/evm and viem, all capable of local signing, but none is imported and searches for privateKeyToAccount, signTypedData and createWalletClient return no matches. The documentation claim of 'auto-sign' directly conflicts with code that performs no signing and instead exfiltrates the secret.[0]

Affected versions and patch status

ProductAffectedPatch status
npm package gadgethumans-mcpVersion 1.0.3 (via removed scotia1973-bot/gadgethumans-mcp) and version 1.0.9 (via public gadgethumans-dev/gadgethumans-mcp); both contain byte-for-byte identical index.js with the private-key transmission. npm reports downloads at package level, so the behavior cannot be separated by version.No fix; version 1.0.9 remained the latest published npm version as of 8 September 2026. Users are advised to remove the package and treat any configured key as compromised.[0]
@gadgethumans/pay2commit (npm)Version 1.0.1 contains a separate user-assisted command-injection risk; no private-key transmission was found in either published version.Not stated; exploitation of the command-injection risk could not be determined by static analysis.[0]
Related GadgetHumans packages (@gadgethumans/x402 npm; six PyPI packages incl. gadgethumans-api-hub-mcp)All 14 versions of @gadgethumans/x402 and all 33 releases of the six PyPI packages reviewed; no wallet-private-key transmission found, though gadgethumans-api-hub-mcp forwards tool inputs (password-strength, JWT-decode, arbitrary HTTP values) to the GadgetHumans API without clear warning.Treated as related infrastructure rather than confirmed malicious packages; no patch status stated.[0]

Indicators of Compromise

TypeIndicatorContext
othergadgethumans-mcpMalicious npm package (registry identifier com.gadgethumans/gadgethumans-mcp) confirmed to transmit the raw wallet private key.[0]
domainswarm.gadgethumans.comAttacker-controlled host receiving the exfiltrated private key; default endpoints /api/x402/execute (when key configured) and /mcp (no key).[0]
domainapi.gadgethumans.comGadgetHumans API host referenced by related PyPI packages that forward tool inputs off-machine; part of the linked ecosystem infrastructure.[0]
file-hash60a60a2483cca540273afc117956fbb70e81bc99f888fd162a9961e16d8171deSHA-256 of the runtime index.js, identical in both versions 1.0.3 and 1.0.9.[0]
file-hash6b75c899337d34e4e2005b3c934b3a67836ea3a48656e43f2d258201cbf69e8bSHA-256 of the earlier (1.0.3) package artifact.[0]
file-hash2644f9ac79e65214fb2ab92a76119614843ae091d72655347d3edaaed600a560SHA-256 of the later (1.0.9) package artifact.[0]
otherscotia1973-bot/gadgethumans-mcpRemoved GitHub repository linked to version 1.0.3 of the malicious package.[0]
othergadgethumans-dev/gadgethumans-mcpStill-public GitHub repository hosting version 1.0.9 (commit 618b5d8b125794a708339124571c6a9338a2f126).[0]
otherX-402-WalletHTTP header used to carry the raw wallet private key to the remote endpoint (context-dependent; X-402-Agent and X-402-Expected-Cost accompany it).[0]
otherWALLET_PRIVATE_KEYEnvironment variable the package instructs users to set; its value is exfiltrated verbatim.[0]

Key takeaways

  • The rise of MCP and agent 'auto-signing' removes human-in-the-loop safeguards: a package with a plausible micropayment justification can request a wallet private key and exfiltrate it verbatim, turning a reasonable-looking request into full wallet compromise.[0]
  • The malicious behavior required no obfuscation or packed payload — it is visible in a 287-line file where one line of documentation ('auto-sign') and one line of code (raw key into an HTTP header) directly contradict each other.[0]
  • Effective discovery must correlate maintainers, repositories, domains, package metadata, and protocol references across multiple registries; the malicious code reappeared under a second GitHub account and sat within a broader nine-package npm/PyPI ecosystem.[0]
  • Download counts (2,327 for the package, 7,028 for the ecosystem) do not equal unique users, installations, exploitation, or victims, and static analysis alone cannot confirm intent or misuse — findings should be scoped accordingly.[0]

Defensive actions

  • Search MCP configurations for gadgethumans-mcp, including installer-targeted paths ~/.claude/claude_desktop_config.json, ~/.cursor/mcp.json, ~/.cline/cline_mcp_settings.json, and ~/.codex/config.toml.: These are the configuration files the package's installer targets; presence indicates the malicious MCP server may be active.[0]
  • If WALLET_PRIVATE_KEY was configured for this package, disable the MCP server, treat the key as compromised, and use trusted wallet software to move assets to a newly generated wallet, then review and revoke outstanding token approvals.: A private key cannot be reset while preserving control of the same address; any recipient of the key can authorize transactions and drain the wallet.[0]
  • Remove the package and delete WALLET_PRIVATE_KEY from local configuration and CI secrets.: The key is transmitted on every recognized tool call, so eliminating both the package and the secret stops further exposure.[0]
  • Apply taint tracking from secret-shaped environment variables (e.g. process.env.WALLET_PRIVATE_KEY) to outbound request construction, and flag declared-but-unimported security libraries and documentation claims that contradict code behavior.: The direct, untransformed path from a private-key env var to a header value to fetch(), combined with unused signing libraries and a false auto-signing claim, is the high-confidence detection signal for this class of deception.[0]