Back to skill

Security audit

x402-CLI

Security checks for vulnerabilities and agentic risk

Overview

The skill is transparent about enabling agents to spend real cryptocurrency, but it gives broad non-confirmed payment and network authority that users should review carefully before installing.

Install only with a fresh, minimally funded wallet and an external approval or policy layer that verifies the exact URL, recipient, network, asset, amount, and maximum spend before every `request pay`. Do not expose personal wallets or broad secrets to this process, avoid arbitrary/internal URLs, be cautious with `--header` and `--data`, and avoid `--save` when request bodies or responses may contain sensitive data.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (5)

T09 · Insecure Skill Coding Practices

Warning
Location
x402_cli.py:197
Finding

Undefined Runtime Type Annotation Prevents CLI Startup

Content
View full analysis
Tuple[int, Dict[str, Any]]: ``` ### Technical Analysis `x402ClientSync` is neither defined in the module nor imported from a dependency. The file also does not enable postponed evaluation through `from __future__ import annotations`. Consequently, Python evaluates the annotation while defining `_x402_request` and raises `NameError` during module loading. This occurs before `main()` runs and before the CLI can emit its documented structured error response. The issue renders all commands unavailable, including commands that do not perform payments, such as `discover list`, `discover search`, and `request info`. ### Attack Path 1. A user or Agent invokes any command, such as: ```bash python x402_cli.py discover list ``` 2. Python imports and evaluates the module. 3. Execution reaches the `_x402_request` function definition. 4. Python attempts to resolve `x402ClientSync`. 5. Because the name is undefined, module loading terminates with `NameError`. 6. The requested operation never executes, and the documented JSON output contract is bypassed. No attacker-controlled input is required; this is an unconditional availability defect. ### Impact Assessment - Complete denial of service for all advertised CLI functionality. - Discovery, endpoint inspection, and payment operations cannot execute. - Automation expecting one JSON object receives an unstructured interpreter exception instead. - No additional system privilege is obtained by an attacker. - The sensitive network and payment paths are unreachable in the audi ...[truncated 49 chars]
Remediation
View remediation
Tuple[int, Dict[str, Any]]: ``` 2. Alternatively, import the intended synchronous client class explicitly. 3. Consider adding: ```python from __future__ import annotations ``` This prevents immediate annotation evaluation, but it should not substitute for using the correct type. 4. Add startup and smoke tests that import the module and execute every parser path. 5. Add static type checking to CI so undefined annotation names fail before release. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
x402_cli.py:141
Finding

Unrestricted Destination URLs Enable Server-Side Request Forgery

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
x402_cli.py:749
Finding

Payment Spend Limit Accepts Non-Finite, Negative, and Unbounded Values

Content
View full analysis
x402Client: # Create the eth wallet for the agent to use evm_wallet_secret = os.getenv("CLIENT_EVM_WALLET_SECRET") if evm_wallet_secret is None: raise CliError( "CLIENT_EVM_WALLET_SECRET is not set; set it via a .env file or the shell environment.", ErrorCode.MISSING_ENV_VAR, ) evm_wallet = Account.from_key(evm_wallet_secret) # Init the x402 client x402_client = x402Client().register_policy(max_amount(usdc_spend_limit * 10**USDC_DECIMALS)) ``` Argument parsing imposes no range, finiteness, or precision constraints: ```python pay_parser.add_argument( "--spend-limit", type=float, default=DEFAULT_USDC_SPEND_LIMIT, help="Maximum USDC to authorize for this payment request", ) ``` ### Technical Analysis The financial limit is parsed as a binary floating-point value and is accepted without checking that it is: - Finite. - Greater than zero. - Within a system-level maximum. - Representable precisely in six-decimal USDC units. - Safe for conversion to the amount format expected by `max_amount`. Inputs such as negative values, `nan`, `inf`, or unexpectedly large values can reach the third-party payment-policy implementation. Exact behavior then depends on dependency validation and conversion semantics. Even for ordinary finite values, no administrator-controlled hard ceiling exists. A manipulated Agent can override the documented default of 1 USDC and authorize a much larger amount. The warning is informational and does not require confirmation. ### Attack Path 1. An attacker manipulates the Agent or workflow that constructs t ...[truncated 1339 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
x402_cli.py:308
Finding

Sensitive Saved Responses Use Predictable Names and Insecure File Creation

Content
View full analysis
str: timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") return f"x402_{command_name}_{timestamp}.json" def _save_discovery_output(output: Any, command_name: str, output_dir: Optional[str] = None) -> str: target_dir = Path(output_dir or ".") target_dir.mkdir(parents=True, exist_ok=True) output_path = target_dir / _generate_discovery_filename(command_name) with output_path.open("w", encoding="utf-8") as file: json.dump(output, file, indent=2) file.write("\n") return str(output_path) ``` Sensitive request and response data is passed into this generic save routine: ```python payload = { "input": {"header": _redact_sensitive_headers(request_header), "data": request_data}, "response": response, } return _save_discovery_output(payload, command_name, output_dir) ``` ### Technical Analysis The filename is predictable to one-second resolution, and the file is opened with ordinary write mode. This behavior: - Follows symbolic links. - Overwrites an existing path. - Does not use exclusive creation. - Does not explicitly set owner-only permissions. - Can collide when multiple operations save within the same second. - Creates parent directories without validating whether they are trusted or shared. Although common authentication header values are redacted, request bodies and service responses are deliberately stored without redaction. Those fields may contain credentials, personal data, internal API results, or paid content. The feature is opt-in and accompanied by a warning, which reduces accidental exposure but does not address unsafe file creation. ### Attack Path 1. An attacker has write access to the selected output directory, such as a shared ...[truncated 1133 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
SKILL.md:54
Finding

Wallet Workflow Relies on Unverified Third-Party Packages and Skills

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (15)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · x402_cli.py (reported line 174)May include surrounding context.

python
evm_wallet_secret = os.getenv("CLIENT_EVM_WALLET_SECRET")
    if evm_wallet_secret is None:
        raise CliError(
            "CLIENT_EVM_WALLET_SECRET is not set; set it via a .env file or the shell environment.",
            ErrorCode.MISSING_ENV_VAR,
        )
    evm_wallet = Account.from_key(evm_wallet_secret)

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
95% confidence
Finding

The disclosure confirms the CLI can autonomously initiate irreversible cryptocurrency payments without a blocking confirmation or built-in approval control. In an agent context, this is dangerous because instruction misunderstanding, prompt injection, or malicious service selection can directly cause real financial loss with no recovery path.

Content

Scanner excerpt · DISCLOSURES.md (reported line 7)May include surrounding context.

md
This CLI enables autonomous spending of real cryptocurrency (USDC on Base mainnet). When you invoke `request pay`, funds are moved irreversibly. This is not a simulation or test environment—transactions are final and cannot be reversed.

## 2. No Confirmation Gate in the CLI

The CLI itself provides no confirmation prompt or approval workflow before sending payment. A warning is printed to stderr before payment, but this does not block execution. If you require human approval, implement that gate in your agent orchestration layer *before* calling the CLI.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
97% confidence
Finding

This finding documents that payment execution proceeds even though only a warning is printed to stderr, meaning there is no effective safeguard against autonomous or accidental spending. Because the skill is specifically designed for agent use and handles real funds, the absence of an approval barrier materially increases the likelihood of unauthorized or mistaken transactions.

Content

Scanner excerpt · DISCLOSURES.md (reported line 9)May include surrounding context.

md
## 2. No Confirmation Gate in the CLI

The CLI itself provides no confirmation prompt or approval workflow before sending payment. A warning is printed to stderr before payment, but this does not block execution. If you require human approval, implement that gate in your agent orchestration layer *before* calling the CLI.

## 3. Irreversible Blockchain Transactions

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill declares powerful capabilities in prose, but does not enforce them through a formal permission or allowed-tools scope. That creates a governance gap: hosts or reviewers cannot reliably constrain environment access, network use, and file writes based on machine-readable policy, increasing the chance of over-privileged execution or unsafe composition with other agent tooling.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
97% confidence
Finding

The skill explicitly enables irreversible on-chain payments without a confirmation gate. In an autonomous agent setting, this is dangerous because prompt injection, malicious discovery results, operator mistakes, or compromised orchestration can directly trigger financial loss with no final approval checkpoint.

Content

Scanner excerpt · SKILL.md (reported line 116)May include surrounding context.

md
|---|---|---|
| `--spend-limit` | `1.0` | Maximum USDC to authorize for the payment request |

**⚠️ This authorizes an on-chain payment the moment it runs — there is no confirmation prompt.** A warning is printed to stderr immediately beforehand as a last reminder, but it does not block execution. Always inspect with `request info` first.

## Output Contract

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
97% confidence
Finding

This workflow normalizes autonomous payment execution after discovery and inspection, but still leaves the final spend action non-interactive and fully agent-driven. Because discovery results and remote payment terms come from untrusted external services, an agent can be manipulated into sending funds to attacker-controlled endpoints or paying for unintended services.

Content

Scanner excerpt · SKILL.md (reported line 193)May include surrounding context.

→ confirm scheme/network/amount/payTo match what you expect → confirm input/output format via extensions.bazaar in the discovery entry ↓ 3. request pay <resource_url> (moves real funds — no confirmation prompt) → signs payment with CLIENT_EVM_WALLET_SECRET, sends it, returns the service response

text

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
98% confidence
Finding

The documented security model deliberately places the risk boundary at wallet balance instead of transaction authorization controls. That is unsafe in many agent deployments because bounded funds limit maximum loss but do not prevent unauthorized or adversarially induced payments, making theft or abuse expected rather than exceptional when the agent is exposed to untrusted inputs.

Content

Scanner excerpt · SKILL.md (reported line 202)May include surrounding context.

md
## Networks & Security Model

- **Base mainnet only** (`eip155:8453`). Testnets are not supported and will fail — confirm your wallet holds Base-mainnet funds before calling `request pay`.
- **No confirmation gate by design.** This skill is built for autonomous use: an agent can discover, inspect, and pay without stopping for human approval. The risk boundary is the wallet's funding limit, not the CLI. Wrap it in your own orchestration if you need a human-in-the-loop step.

### Capabilities (explicit declaration)

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · x402_cli.py (reported line 89)May include surrounding context.

python
Returns:
        The parsed JSON catalog response (dict or list).
    """
    base_url = "https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources"

    params = {"limit": limit, "offset": offset}

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · x402_cli.py (reported line 112)May include surrounding context.

python
Returns:
        The parsed JSON catalog response (dict or list).
    """
    base_url = "https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources"

    params = {"limit": limit, "offset": offset}

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

The CLI sends arbitrary user-supplied headers and request bodies to an arbitrary URL, which can exfiltrate secrets or sensitive data to third parties and can be abused for SSRF-style access to internal services if the agent can reach them. In this skill context, that risk is amplified because the tool is explicitly designed for agent automation and can combine external transmission with immediate paid requests.

Content

Scanner excerpt · x402_cli.py (reported line 149)May include surrounding context.

python
try:
        match request_type.lower():
            case "post":
                service_response = requests.post(url, headers=header, json=request_data, timeout=timeout)
            case "get":
                service_response = requests.get(url, headers=header, params=request_data, timeout=timeout)
            case _:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 225)May include surrounding context.

md
"resources": {
            "items": [
                {
                    "resource": "https://api.example.com/service",
                    "description": "Service description",
                    "accepts": [
                        {

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · x402_cli.py (reported line 369)May include surrounding context.

python
"resources": {
            "items": [
                {
                    "resource": "https://api.example.com/service",
                    "description": "Service description",
                    "accepts": [
                        {

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · x402_cli.py (reported line 421)May include surrounding context.

python
"resources": {
            "items": [
                {
                    "resource": "https://api.example.com/service",
                    "description": "Service description",
                    "accepts": [
                        {

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
97% confidence
Finding

The tool can autonomously authorize blockchain payments to third-party endpoints without an interactive confirmation step, creating a direct path from agent prompt/input to irreversible real-money spend. In an agent setting this is especially dangerous because untrusted instructions or discovered services could trigger unwanted transactions before human review.

Content

Scanner excerpt · x402_cli.py (reported line 545)May include surrounding context.

python
5. Returns the service response
    
    WARNING: THIS SPENDS REAL MONEY ON BASE MAINNET IMMEDIATELY
    No confirmation prompt is shown — the payment is authorized the moment this runs.
    Always call request info first to verify the endpoint.
    
    Example output structure (successful payment + service response):

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

Scanner excerpt · NOTICE.md (reported line 27)May include surrounding context.

md
- Overpay for a service
- Interact with defective, unavailable, or malicious endpoints

**Users are solely responsible for implementing appropriate safeguards outside this software**, including but not limited to:
- Wallet-level spend limits and policies
- Service allowlists and address allowlists
- Network restrictions and RPC provider selection