Back to skill

Security audit

Neckr0ik X402 Payments

Security checks for vulnerabilities and agentic risk

Overview

This payment skill is not clearly malicious, but it overstates real payment capabilities and handles wallet private keys unsafely.

Do not use this skill with a real wallet private key or real funds as packaged. Treat its payment, balance, and receipt behavior as mock/demo behavior unless it is revised to implement real signing and verification, remove plaintext key storage, stop echoing secrets, and clearly document limits and storage locations.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/x402.py:391
Finding
Wallet Private Key Exposed Through Command-Line Arguments, Plaintext Storage, and Terminal Output<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:160-164`; `scripts/x402.py:89-103`; `scripts/x402.py:329-333`; `scripts/x402.py:391-408` **Vulnerability Type**: Plaintext sensitive-data exposure **Risk Level**: High ### Vulnerable Code The documentation directs users to pass a wallet private key as a command-line argument: ```bash # Set wallet private key (stored securely) neckr0ik-x402-payments config set wallet.private_key <key> # Or use environment variable export X402_PRIVATE_KEY=<key> ``` The configuration value is accepted as an ordinary command-line argument: ```python # config command config_parser = subparsers.add_parser('config', help='Configure x402') config_subparsers = config_parser.add_subparsers(dest='config_command') config_set = config_subparsers.add_parser('set', help='Set configuration') config_set.add_argument('key', help='Configuration key (e.g., wallet.address)') config_set.add_argument('value', help='Configuration value') ``` Configuration data is written as unencrypted JSON without explicitly establishing owner-only file permissions: ```python def _load_config(self) -> dict: """Load configuration.""" if self.config_file.exists(): return json.loads(self.config_file.read_text()) return {"chain": "base", "token": "usdc"} def _save_config(self, config: dict): """Save configuration.""" self.config_file.write_text(json.dumps(config, indent=2)) ``` The supplied value is stored and then printed in full: ```python elif args.command == 'config': if args.config_command == 'set': config = client._load_config() # Parse key path keys = args.key.split('.') # Set nested value current = config for key in keys[:-1]: if key not in current: current[key] = {} current = current[key] current[keys[-1]] = args.value client._save_config(config) print(f"✓ Set {args.key} = {args.value}") ``` # ...[truncated 2968 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Do not accept private keys as ordinary command-line arguments** - Remove the documented `config set wallet.private_key <key>` workflow. - If interactive entry is unavoidable, use `getpass.getpass()` so the key is not echoed. - Warn users that shell arguments and shell history are unsuitable for secrets. 2. **Avoid storing raw private keys** - Prefer OS-backed secret stores such as Keychain, Credential Manager, Secret Service, or a dedicated hardware/software wallet. - Prefer an external signer API so this Skill never receives the private key. - If persistence is essential, encrypt the key using a user-provided secret or platform-protected key. 3. **Enforce restrictive filesystem permissions** - Create `~/.x402` with mode `0700`. - Create secret-bearing files atomically with mode `0600`. - Verify and reject unsafe ownership, symlinks, and overly permissive existing files before reading or writing. - Separate non-sensitive configuration from wallet secrets. 4. **Never print secret values** - Replace: ```python print(f"✓ Set {args.key} = {args.value}") ``` with: ```python print(f"✓ Set {args.key}") ``` - Redact known secret fields in all diagnostics and exception paths. 5. **Align documentation and implementation** - Do not claim that private keys are “stored securely” until secure storage is implemented. - If `X402_PRIVATE_KEY` support is retained, implement it explicitly and document the risks of environment-variable exposure. - Since the audited payment implementation is simulated and does not use the key, remove private-key collection entirely until real local signing is safely implemented. 6. **Add regression tests** - Verify secrets never appear in stdout or stderr. - Verify generated secret files have owner-only permissions. - Verify secret values are not stored in ordinary configuration JSON. - Verify malformed paths or pre ...[truncated 55 chars]
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documentation claims autonomous blockchain payments, payment signing, settlement, and server-side acceptance of payments, but the analyzed material indicates those behaviors are missing or simulated. For a payments skill, this mismatch is dangerous because users may rely on it for financial operations, assume protections or settlement guarantees that do not exist, and expose funds, credentials, or business logic under false assumptions.

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The `pay` function presents itself as paying for API access, but it only fabricates a transaction hash and uses a hard-coded `signature="simulated"` receipt. In a payments skill, simulated payment proof is especially dangerous because agents or operators may believe funds were transferred and then send the fake receipt to third parties, causing fraud-like behavior, service abuse attempts, accounting errors, or trust boundary violations.

Lp3

Medium
Category
MCP Least Privilege
Confidence
80% confidence
Finding
The skill advertises capabilities involving network access, local configuration, and key management but does not declare any explicit tool scope or permissions boundaries. In an agent environment, this can lead to overbroad execution authority and make it harder for users or orchestrators to constrain file and network operations before handling sensitive wallet material.

External Transmission

Medium
Category
Data Exfiltration
Content
### Check if endpoint supports x402

```bash
neckr0ik-x402-payments check https://api.example.com/premium
```

### Pay for API access
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Check if endpoint supports x402

```bash
neckr0ik-x402-payments check https://api.example.com/premium
```

### Pay for API access
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Check if endpoint supports x402

```bash
neckr0ik-x402-payments check https://api.example.com/premium
```

### Pay for API access
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
### Check if endpoint supports x402

```bash
neckr0ik-x402-payments check https://api.example.com/premium
```

### Pay for API access
Confidence
50% 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
95% confidence
Finding
The skill instructs users to configure a wallet private key and describes autonomous payments without prominent warnings about irreversible fund transfers, private-key sensitivity, chain fees, or the risk of automatic spending. In a financial context, omission of these warnings materially increases the chance of accidental loss, unsafe key handling, or unauthorized spending by downstream agents.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The skill metadata and module docstring advertise payment acceptance and serving capabilities that are not implemented. In an agent setting, this kind of capability misrepresentation is dangerous because downstream systems may trust the skill to safely accept or process payments when it only performs client-side probing and simulation, leading to incorrect automation decisions and potential financial or operational failures.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The embedded usage text advertises a `serve` command, but the CLI parser never implements it. For agent-operated tooling, undocumented or nonexistent commands can cause failed workflows, unsafe fallback behavior, or incorrect assumptions that the tool can expose paid endpoints when it cannot.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The `get_balance` function claims to retrieve wallet balances but returns hard-coded values unrelated to any configured wallet or chain. In a financial automation context, false balance reporting can directly cause unsafe payment decisions, overspending assumptions, skipped funding checks, and misleading audit records.

Missing User Warnings

Low
Confidence
84% confidence
Finding
This code persists transaction metadata to ~/.x402/history.jsonl, which affects user data on disk. Although the function has an internal docstring, there is no user-facing disclosure at the point of use or in CLI help that running payments will create or append to a history file.

Static analysis

No suspicious patterns detected.