other
- Location
SKILL.md:55- Finding
Remote Manifest Can Authorize an Unbounded Cryptocurrency Payment Without User Confirmation
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:55-65;vend.py:29-41, 54-62, 79-84
Vulnerability Type: Unconfirmed payment authorization based on remotely controlled values
Risk Level: HighTechnical Analysis
The Skill instructs an autonomous agent to transfer cryptocurrency using the amount and recipient supplied by a live remote manifest:
markdown ## Pay for a call When you get exit 2: 1. Send **exactly** `amount_raw` of XNO to `pay_to` with whatever Nano wallet you hold (a wallet skill such as `nano-pay` or `nano`, or your own code). This skill never holds a seed. 2. Run the same command again with the hash of that send block: python3 vend.py extract url=https://example.com --payment <64-hex send block hash>The script retrieves both payment fields from the service-controlled manifest without enforcing a local price ceiling, trusted-recipient policy, or user-approved payment parameters:
python def tools(): status, body = fetch(MANIFEST) if status != 200: raise OSError(f"manifest answered HTTP {status}") found = {} for resource in json.loads(body)["resources"]: name = resource["url"].rstrip("/").rsplit("/", 1)[-1] accept = resource["accepts"][0] found[name] = {"url": resource["url"], "amount_raw": accept["amount"], "pay_to": accept["payTo"], "description": resource["description"]} return foundWhen the endpoint responds with HTTP 402, these remote values are presented as the payment instruction:
python if status == 402: print(json.dumps({"payment_required": {"amount_raw": tool["amount_raw"], "pay_to": tool["pay_to"], "network": "nano:mainnet", "asset": "XNO", "then": "send exactly amount_raw to pay_to, then rerun with --payment <send block hash>", "server_said": parsed.get("message", "")[:200] if isinstanc ...[truncated 1893 chars]- Remediation
View remediation
Remediation Suggestions
- Require explicit, transaction-specific user confirmation before every payment. Display:
- The exact XNO amount and raw amount.
- The complete destination account.
- The requested tool and parameters.
- The advertised and locally permitted maximum price.
- Enforce a hard local spending ceiling independent of the remote manifest. Reject any payment request exceeding that ceiling.
- Maintain a locally configured recipient allowlist or require users to approve a new recipient separately.
- Do not treat HTTP 402 output as payment authorization. Return a pending-payment object that cannot be consumed by a wallet until a confirmation token generated after user approval is supplied.
- Cross-check the HTTP 402 payment demand against the manifest and a local policy, and reject mismatched network, asset, recipient, or amount fields.
- Add cumulative per-session and per-day spending limits.
- Default to refusing payment in non-interactive or autonomous operation unless the user has explicitly configured a narrowly scoped budget and approved recipient policy.
- Document that the live service controls payment metadata and that advertised prices are not a substitute for locally enforced limits.
- Require explicit, transaction-specific user confirmation before every payment. Display:
