registry  /  tapmarket-connect  /  0.1.1

tapmarket-connect@0.1.1

Give your AI assistant the power to hire paid specialists on TapMarket — with spending limits enforced on-chain.

AI Security Review

scanned 12h ago · by lpm-firewall-ai

Review flagged AI-agent configuration or capability changes. This remains warn-only unless evidence shows foreign-agent hijack through preinstall/install/postinstall, hidden persistence, exfiltration, remote code execution, or other concrete malicious behavior.

Static reason
High-risk behavior combination matched malicious policy.
Trigger
User runs `npx tapmarket-connect setup`, then an MCP client invokes `serve` and `hire_specialist`.
Impact
Claude Desktop can invoke TapMarket tools that spend from the created wallet within the package's smart-account permissions and send task inputs to TapMarket service endpoints.
Mechanism
explicit MCP agent capability setup for paid TapMarket actions
Rationale
Static inspection supports warning for explicit AI-agent capability setup and payment actions, but not a malicious block: there are no lifecycle hooks, no stealth execution, and no observed key/credential exfiltration. Because it mutates Claude MCP config and enables paid agent actions, it should not be marked fully clean.
Evidence
package.jsoncli.jsserver.jsinit-lib.jscatalog.jsowner-tools.js~/.tapmarket/wallet.json~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%/Claude/claude_desktop_config.json~/.config/Claude/claude_desktop_config.json~/.tapmarket/hires.jsonl
Network endpoints7
fund.tappayment.io/fundfaucet.circle.comsepolia.base.orgrpc.zerodev.app/api/v3/${ZERODEV_PROJECT_ID}/chain/84532hermes.tappayment.io/assessscribe.tappayment.io/writesepolia.basescan.org/tx/

Decision evidence

public snapshot
AI called this Suspicious at 82.0% confidence as Dangerous Capability with medium false-positive risk.
Evidence for warning
  • cli.js setup writes Claude Desktop MCP config to run `npx -y tapmarket-connect@latest serve`.
  • cli.js setup creates ~/.tapmarket/wallet.json containing ownerKey/sessionApproval and posts wallet address to fund.tappayment.io.
  • server.js exposes MCP hire_specialist tool that spends USDC via ZeroDev/Base Sepolia and sends user input to catalog endpoints.
  • catalog.js routes user-supplied specialist input to hermes.tappayment.io and scribe.tappayment.io.
  • server.js logs hire records to ~/.tapmarket/hires.jsonl.
Evidence against
  • package.json has no preinstall/install/postinstall lifecycle scripts.
  • Claude config mutation is gated behind explicit `tapmarket-connect setup`, not install/import time.
  • No child_process, eval/vm/Function, native binary loading, or hidden remote payload execution found.
  • Network endpoints are package-aligned payment/faucet/specialist RPC endpoints for the advertised TapMarket connector.
  • Wallet keys are generated locally and read locally; inspected code does not exfiltrate ownerKey or sessionApproval.
Behavioral surface
Source
EnvironmentVarsFilesystemNetwork
Supply chain
HighEntropyStringsUrlStrings
ManifestNo manifest risk signals triggered.
scanned 5 file(s), 21.4 KB of source, external domains: faucet.circle.com, fund.tappayment.io, hermes.tappayment.io, rpc.zerodev.app, scribe.tappayment.io, sepolia.base.org, sepolia.basescan.org

Source & flagged code

3 flagged · loading source
server.jsView file
19L20: const WALLET_FILE = process.env.TAPMARKET_WALLET ?? new URL("./wallet.json", import.meta.url).pathname; L21: if (!existsSync(WALLET_FILE)) { ... L24: } L25: const wallet = JSON.parse(readFileSync(WALLET_FILE, "utf8")); L26: ... L35: const usdcAbi = parseAbi(["function approve(address,uint256)", "function balanceOf(address) view returns (uint256)"]); L36: const publicClient = createPublicClient({ chain: baseSepolia, transport: http("https://sepolia.base.org") }); L37: const account = await deserializePermissionAccount( ... L77: if (!spec) return { content: [{ type: "text", text: `Unknown specialist '${args.specialist}'. Use list_specialists.` }], isError: true }; L78: const route = { url: spec.endpoint, body: spec.shape }; L79: const esc = await publicClient.readContract({ address: TAP_MARKET, abi: marketAbi, functionName: "escrows", args: [BigInt(spec.listingId), account.address] });
Critical
Credential Exfiltration

Source appears to send environment or credential material to an external endpoint.

server.jsView on unpkg · L19
19Trigger-reachable chain: manifest.bin -> cli.js -> server.js L19: L20: const WALLET_FILE = process.env.TAPMARKET_WALLET ?? new URL("./wallet.json", import.meta.url).pathname; L21: if (!existsSync(WALLET_FILE)) { ... L24: } L25: const wallet = JSON.parse(readFileSync(WALLET_FILE, "utf8")); L26: ... L35: const usdcAbi = parseAbi(["function approve(address,uint256)", "function balanceOf(address) view returns (uint256)"]); L36: const publicClient = createPublicClient({ chain: baseSepolia, transport: http("https://sepolia.base.org") }); L37: const account = await deserializePermissionAccount( ... L77: if (!spec) return { content: [{ type: "text", text: `Unknown specialist '${args.specialist}'. Use list_specialists.` }], isError: true }; L78: const route = { url: spec.endpoint, body: spec.shape }; L79: const esc = await publicClient.readContract({ address: TAP_MARKET, abi: marketAbi, functionName: "escrows", args: [BigInt(spec.listingId), account.address] });
Critical
Trigger Reachable Dangerous Capability

A package entrypoint or install-time lifecycle script reaches a source file with blocking dangerous behavior.

server.jsView on unpkg · L19
package.jsonView file
scripts registry_only=start
Critical
Manifest Confusion

Tarball package.json differs from the npm registry version manifest for scripts or dependency sets.

package.jsonView on unpkg

Findings

3 Critical3 Medium4 Low
CriticalCredential Exfiltrationserver.js
CriticalTrigger Reachable Dangerous Capabilityserver.js
CriticalManifest Confusionpackage.json
MediumNetwork
MediumEnvironment Vars
MediumStructural Risk Force Deep Review
LowScripts Present
LowFilesystem
LowHigh Entropy Strings
LowUrl Strings