Back to skill

Security audit

AgentXPay

Security checks for vulnerabilities and agentic risk

Overview

This skill is openly a blockchain payment tool, but it can spend or lock funds and call arbitrary external URLs without enforceable approval controls.

Review before installing. Use only test wallets or tightly limited wallets, configure spending caps outside the agent, avoid production private keys, restrict allowed service endpoints, and require a separate human approval workflow before payments, subscriptions, escrow creation, wallet funding, spending-limit changes, or agent authorization.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
src/runtime.ts:79
Finding
Unrestricted outbound requests enable server-side request forgery and automatic payment abuse<![CDATA[ ## Vulnerability Details **File Location**: `src/runtime.ts:79-100`; related schema: `src/schemas.ts:37-58` **Vulnerability Type**: Server-Side Request Forgery (SSRF) and unsafe automatic payment handling **Risk Level**: High ### Vulnerable Code ```ts const fetchOptions: RequestInit & { autoPayment: boolean; maxRetries?: number; serviceId?: string; pricePerCall?: string; } = { method: params.method, headers: { "Content-Type": "application/json", ...(params.headers || {}), }, autoPayment: true, }; // Pass on-chain serviceId and pricePerCall to SDK for validation (mismatch throws error) if (params.serviceId) { fetchOptions.serviceId = params.serviceId; } if (params.pricePerCall) { fetchOptions.pricePerCall = params.pricePerCall; } if (params.body) { fetchOptions.body = JSON.stringify(params.body); } const response = await this.client.fetch(params.url, fetchOptions); ``` The corresponding tool schema accepts an unrestricted string: ```ts url: { type: "string", description: "AI service endpoint URL", }, method: { type: "string", enum: ["GET", "POST", "PUT", "DELETE"], description: "HTTP method (default: POST)", }, body: { type: "object", description: "Request body (will be JSON-serialized)", }, headers: { type: "object", description: "Additional HTTP headers", additionalProperties: { type: "string" }, }, ``` ### Technical Analysis `params.url` is supplied by the tool caller and passed directly to `client.fetch`. The implementation does not: - Require HTTPS. - Restrict destinations to trusted service-registry endpoints. - Reject loopback, private, link-local, multicast, or reserved IP ranges. - Protect cloud metadata endpoints. - Resolve and validate hostnames against DNS rebinding. - Revalidate redirect destinations. - Restrict sensitive caller-controlled request headers. The request also sets `autoPayment: true`. Consequently, the same primitive that performs an unrestricted outbound request ca ...[truncated 1607 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Permit only `https:` URLs in production. 2. Bind paid requests to endpoints retrieved from a trusted and verified on-chain registry. 3. Resolve destination hostnames before connecting and reject: - Loopback addresses. - RFC 1918 private networks. - Link-local addresses. - Carrier-grade NAT ranges. - Multicast and reserved ranges. - IPv6 local, link-local, and IPv4-mapped private addresses. 4. Disable redirects or repeat full URL and IP validation after every redirect. 5. Protect against DNS rebinding by connecting only to the validated resolved address while preserving correct TLS hostname verification. 6. Remove arbitrary header support or allowlist harmless headers. Explicitly reject `Authorization`, `Cookie`, `Host`, proxy headers, and internal authentication headers. 7. Require `serviceId`, expected price, expected chain ID, and expected endpoint for every automatic payment. 8. Introduce strict timeouts, response-size limits, retry limits, and outbound network egress controls. 9. Separate an unpaid discovery request from payment execution and require explicit authorization before signing a transaction. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/runtime.ts:484
Finding
Financially sensitive tools execute without enforceable user approval or mandatory transaction limits<![CDATA[ ## Vulnerability Details **File Location**: `src/runtime.ts:484-503`; related operations: `src/runtime.ts:408-426`, `src/index.ts:109-124`, `src/schemas.ts:137-156` **Vulnerability Type**: Missing authorization workflow for irreversible financial operations **Risk Level**: High ### Vulnerable Code The composite tool automatically selects and pays a service: ```ts // 3. x402 auto-pay call (pass on-chain serviceId and pricePerCall for validation) const result = await this.payAndCall({ url: selected.endpoint, method: "POST", body: { prompt: params.task }, serviceId: selected.id, pricePerCall: ethers.parseEther(selected.pricePerCall).toString(), }); const latencyMs = Date.now() - startTime; return { selectedService: { id: selected.id, name: selected.name, price: selected.pricePerCall, category: selected.category, }, response: result.data, payment: result.payment, latencyMs, }; ``` The maximum budget is optional: ```ts maxBudget: { type: "string", description: 'Maximum budget in MON, e.g., "0.05"', }, preferCheapest: { type: "boolean", description: "If true, selects the cheapest matching service", }, }, required: ["task"], ``` Subscription execution also proceeds directly after selecting a plan: ```ts // Subscribe const result = await this.client.subscribe(serviceId, plan.planId, plan.price); // Verify access const signerAddress = await this.wallet.getAddress(); const hasAccess = await this.client.subscriptions.checkAccess( signerAddress, serviceId ); ``` The registry dispatches supplied parameters without approval or runtime schema enforcement: ```ts async callTool( name: string, params: Record<string, unknown> ): Promise<unknown> { const registration = this.toolMap.get(name); if (!registration) { throw new Error( `Unknown tool: ${name}. Available tools: ${Array.from(this.toolMap.keys()).join(", ")}` ); } try { const result = await registration.handler(params); ...[truncated 2207 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Split every financial operation into two phases: - `prepare` or `quote`, which performs no transaction. - `execute`, which requires explicit approval. 2. Issue a short-lived, single-use approval token from a trusted user interface. Bind it cryptographically to: - Chain ID. - Contract address. - Destination or provider. - Service and plan identifiers. - Exact amount and maximum fees. - Endpoint. - Operation type. - Expiration time. 3. Make `maxBudget` mandatory for `smartCall` and reject zero, negative, malformed, or excessive values. 4. Enforce hard per-transaction, daily, and cumulative limits in runtime code independently of prompt instructions. 5. Require separate explicit approval for subscriptions, escrow creation, wallet funding, spending-limit changes, and agent authorization. 6. Validate every tool invocation against a strict runtime schema with `additionalProperties: false`, address validation, integer bounds, and decimal amount bounds. 7. Display a transaction preview before approval and verify that the submitted transaction exactly matches the preview. 8. Default to the least expensive valid service only after verifying service activity, registry provenance, endpoint identity, and chain configuration. 9. Record an immutable audit trail of quote, approval identity, approval timestamp, and resulting transaction hash. ]]>

T08 · Insecure Dependencies

Warning
Location
package.json:27
Finding
Stale lockfile and npx-based execution make the private-key-bearing runtime non-reproducible<![CDATA[ ## Vulnerability Details **File Location**: `package.json:27,36-48`; `pnpm-lock.yaml:9-14`; `scripts/run-tool.ts:1-5` **Vulnerability Type**: Insecure and non-reproducible dependency execution **Risk Level**: Medium ### Vulnerable Code The package manifest declares SDK version `^0.3.0` and invokes `tsx` through `npx`: ```json "scripts": { "build": "tsup", "build:standalone": "tsup --config tsup.standalone.ts", "dev": "tsup --watch", "test": "vitest run", "test:watch": "vitest", "clean": "rm -rf dist", "tool": "npx tsx scripts/run-tool.ts" }, "dependencies": { "@agentxpay/sdk": "^0.3.0", "ethers": "^6.13.0" }, "devDependencies": { "tsup": "^8.3.0", "typescript": "^5.6.0", "vitest": "^2.1.0" } ``` The committed lockfile instead records SDK version `0.2.0` with a different specifier: ```yaml dependencies: '@agentxpay/sdk': specifier: ^0.2.0 version: 0.2.0 ethers: specifier: ^6.13.0 version: 6.16.0 ``` The runner also uses an `npx` shebang: ```ts #!/usr/bin/env npx tsx /** * AgentXPay Skill — CLI Tool Runner * * Usage: * npx tsx scripts/run-tool.ts <tool_name> [params_json] */ ``` ### Technical Analysis The manifest and lockfile disagree on the security-critical payment SDK version. A frozen installation should fail, while an installation that updates or ignores the lockfile may install a different SDK from the one represented by the committed dependency graph. The `tool` command and script shebang invoke `tsx` through `npx`, but `tsx` is not directly declared in `package.json`. Depending on the environment and `npx` configuration, a missing local executable may be downloaded at execution time. These dependencies run in the same Node.js process that receives `PRIVATE_KEY` and transaction configuration. Therefore, mutable or unexpectedly resolved dependency code has access to wallet credentials and transaction-signing capabilities. No evidence was found that the named dependencies are themselve ...[truncated 1387 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Regenerate `pnpm-lock.yaml` from the current manifest and commit the synchronized result. 2. Enforce `pnpm install --frozen-lockfile` in CI and production deployments. 3. Pin exact versions of security-critical dependencies, especially the payment SDK, rather than using floating caret ranges. 4. Add `tsx` as an exact direct development dependency if source execution is required. 5. Prefer executing a prebuilt, reviewed JavaScript artifact with `node` instead of invoking `npx` at runtime. 6. Configure `npx` to reject network installation, or eliminate it from production execution paths. 7. Verify registry provenance and package integrity in CI. 8. Generate and review a software bill of materials for release artifacts. 9. Run dependency code in a constrained environment with restricted filesystem and outbound-network access. 10. Keep the signing key outside the general Node.js process where possible, using a hardware signer, isolated signing service, or transaction-policy wallet. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (46)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description presents a blockchain payment and subscription skill with wallet and escrow capabilities. However, the supplied code chunk is solely a packaging/build configuration file for tsup. It specifies bundling settings and an external dependency but contains no operational logic related to blockchain payments, x402, Monad, wallet management, subscriptions, or escrow. This is a material mismatch in primary purpose and implemented capabilities.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description is about runtime AgentXPay functionality on Monad/x402: discovering services, making payments, managing wallets, subscriptions, and escrow. The supplied code does none of that. It is only build tooling configuration for tsup, specifying how to bundle the package and which dependencies to inline or externalize. While such tooling may support the overall project, this chunk’s primary purpose is materially different from the declared skill behavior, so this is a clear description-behavior mismatch.

Vague Triggers

High
Confidence
97% confidence
Finding
The recommended smart-call flow permits activation from generic task descriptions and then autonomously discovers, selects, pays for, and calls an external service. This is a strong prompt-to-payment risk: a normal user request could trigger external transmission of task data and on-chain spending without a discrete approval step, which is particularly sensitive given wallet management and automated retry/payment behavior.

Missing User Warnings

High
Confidence
95% confidence
Finding
The manifest describes autonomous blockchain payment, wallet management, subscriptions, and escrow, but does not warn that the skill can initiate actions affecting user funds. In this context, missing a prominent risk disclosure is dangerous because integrators may install or auto-enable the skill without appreciating the financial consequences.

Missing User Warnings

High
Confidence
99% confidence
Finding
The pay action constructs calldata and executes an on-chain payment through the managed wallet, causing irreversible value transfer with no user-facing confirmation at the point of spend. Even with checks for authorization, balance, and allowance, an agent or upstream prompt flow could still trigger unintended payments to services within those constraints.

Missing User Warnings

High
Confidence
97% confidence
Finding
Creating escrow locks user funds until release or expiry, and this function executes the escrow transaction directly based on caller-supplied parameters. Because funds become unavailable and recovery may depend on contract logic or deadlines, silent escrow creation carries a high risk of financial loss or operational lockup if triggered unintentionally.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The README advertises autonomous on-chain payment, wallet management, subscriptions, and escrow operations without any visible warning, confirmation requirement, spending limits, or explanation of financial risk. In an agent skill, this is dangerous because integrators may enable capabilities that let an LLM initiate irreversible blockchain transactions or recurring payments with real funds based only on model decisions or prompt-triggered workflows.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README explicitly promotes autonomous service discovery, on-chain payments, wallet management, and subscriptions, but provides no warning about irreversible financial actions, private key or wallet-risk considerations, or the need for explicit user authorization. In an agent context, this increases the chance that downstream integrators enable spending or subscription behavior without adequate consent, limits, or human review, which can lead to unintended asset loss.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The tool descriptions for auto-pay service calls and smart-call behavior imply that the agent may discover external services, send requests to them, and trigger blockchain payments automatically, yet there is no warning about data exfiltration, third-party trust, or paid network side effects. This is dangerous because users or integrators may treat the tool as a normal API helper while it can both disclose prompts/data to external endpoints and spend funds in a single automated flow.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill declares powerful capabilities involving environment variables and network access, including use of a blockchain private key, but does not restrict tool scope with explicit permissions or allowed-tools. In this context, missing scope boundaries increases the chance that the agent can invoke sensitive payment or network behaviors more broadly than intended, especially because the skill is user-invocable and designed to spend funds.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The tool examples use broad natural-language triggers for actions that may lead to network access and potentially paid service selection. Because the skill is user-invocable and intended for autonomous service discovery, vague activation phrases can cause the agent to invoke capabilities without clear user consent, increasing the risk of unintended spending or data disclosure to external endpoints.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The paid-call workflow can be activated by generic user requests like 'help me call this AI API,' yet it performs automatic 402 payment and retries against a remote endpoint. In this skill context, that is especially dangerous because it combines autonomous network calls, handling of payment metadata from the remote service, and direct fund expenditure using PRIVATE_KEY, making prompt-triggered unintended purchases plausible.

Rp1

Medium
Category
MCP Rug Pull
Confidence
81% confidence
Finding
Referencing execution via 'npx tsx' without a pinned version creates a supply-chain risk because the resolved package version may change over time or be influenced by the environment. In a payment-oriented skill that can access PRIVATE_KEY and make on-chain transactions, even a small dependency substitution could lead to credential theft or unauthorized transactions.

Vague Triggers

Medium
Confidence
85% confidence
Finding
The description advertises broad autonomous payment capability for AI agents without narrowing triggers, authorization boundaries, or operator expectations. For a wallet/payment skill, overly broad activation language increases the chance that hosts or users enable high-risk financial actions more permissively than intended.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding
The script invokes `npx tsx`, which can resolve and fetch an executable at run time instead of using a fully pinned local binary. In a security-sensitive payment skill, this weakens build/runtime supply-chain integrity because a different `tsx` version could be executed than the one reviewed.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The documentation promotes `client.fetch(..., { autoPayment: true })` for handling HTTP 402 responses automatically, but it does not prominently warn that this can spend on-chain funds and transmit request data to third-party services. In an agentic context, this creates a real risk of unintended micropayments, repeated charges, or data disclosure if the endpoint is malicious, misconfigured, or called without explicit operator approval.

External Transmission

Medium
Category
Data Exfiltration
Content
#### `client.fetch(url, options)` — x402 自动付费请求

```typescript
const response = await client.fetch("https://ai-service.com/api/chat", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ prompt: "Hello" }),
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The API reference lists many value-transferring methods such as `payPerUse`, `deposit`, `withdraw`, `subscribe`, escrow actions, and wallet `execute` without user-facing warnings about irreversibility, authorization sensitivity, or financial risk. In a skill meant for autonomous agents, understated documentation can lead integrators to expose dangerous operations without proper policy controls, resulting in fund loss or abuse.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The document explicitly describes an agent automatically reacting to HTTP 402 responses by submitting an on-chain payment and retrying the request, but it provides no requirement for user approval, spending limits, payee allowlisting, or human-visible warnings. In the context of an agent payment skill, this omission is dangerous because a malicious or compromised service could induce repeated or inflated payments, or redirect agents to pay attacker-controlled addresses, leading to direct fund loss.

Rp1

Medium
Category
MCP Rug Pull
Confidence
91% confidence
Finding
The shebang uses `env npx tsx`, which can fetch and execute whatever `tsx` version is resolved at runtime instead of a pinned, reviewed dependency. In a payment and wallet-management skill, that creates a supply-chain risk where a compromised package, unexpected version drift, or hostile registry resolution could execute arbitrary code with access to `PRIVATE_KEY` and blockchain transaction capabilities.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding
The usage example instructs operators to run `npx tsx`, reinforcing an execution pattern that may resolve an unpinned tool version at runtime. While this line is documentation rather than executable logic, it still increases the chance that users will run a mutable external package in an environment holding wallet secrets.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding
This usage example promotes `npx tsx` for a tool that can trigger payment and service calls. If `npx` resolves a malicious or unexpected `tsx`, arbitrary code could run before the script, exposing environment variables and transaction authority.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding
The example continues to encourage runtime package resolution through `npx tsx`. In this skill, the context is more sensitive than a normal CLI because the process consumes RPC endpoints, private keys, and contract addresses for on-chain payments.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding
This documentation line teaches operators to invoke the wallet-management command via unpinned `npx tsx`. Because the command manages wallets and authorization, any supply-chain compromise in the transient runner could directly affect funds and wallet control.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding
This example also relies on `npx tsx` for a wallet authorization flow. Even though it is only sample text, it normalizes a risky operational pattern in a high-value blockchain context where compromise could expose signing keys or alter transaction behavior.

Static analysis

No suspicious patterns detected.