Back to skill

Security audit

USDC Krump EVVM x402 Payment

Security checks for vulnerabilities and agentic risk

Overview

This crypto-payment skill is purpose-aligned, but it asks users to expose wallet credentials to unpinned scripts and has confusing payment-flow documentation.

Review carefully before installing. Use only low-value test wallets, pin any external repository commit and tool versions before running examples, avoid raw private keys where possible, configure Privy spending and recipient policies, and verify the exact token, adapter, chain, recipient, and amount before any deposit or payment.

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)

T08 · Insecure Dependencies

Error
Location
SKILL.md:56
Finding
Unpinned External Code and Undeclared Runtime Package Execute with Payer Credentials## Vulnerability Details **File Location**: `SKILL.md:56-61`, `SKILL.md:110-113`, `examples/README-two-agents-x402.md:27-35`, `package.json:22-29` **Vulnerability Type**: Supply-chain exposure through mutable external source code and undeclared `npx` tooling **Risk Level**: High ### Vulnerable Code and Instructions `SKILL.md:56-61` directs users to run code from an external, mutable repository while exposing a payer private key: ```markdown EVVM Core moves **internal ledger balances**; it does not pull tokens from the wallet. For the **EVVM Native x402 adapter**, the payer must deposit USDC.k into EVVM first. **Run this in the full USDC Krump repo** (clone from [github.com/arunnadarasa/usdckrump](https://github.com/arunnadarasa/usdckrump)): ```bash cd lz-bridge PRIVATE_KEY=0x<payer_key> DEPOSIT_AMOUNT=1000000 npm run evvm:deposit-usdck ``` ``` `SKILL.md:110-113` instructs users to invoke `tsx` through `npx`: ```markdown ```bash AGENT_A_PRIVATE_KEY=0x... AGENT_B_ADDRESS=0x... npx tsx examples/two-agents-x402-native.ts ``` ``` The package does not declare `tsx`: ```json "dependencies": { "ethers": "^6.13.0" }, "devDependencies": { "@types/node": "^20.19.33", "typescript": "^5.9.3" } ``` ### Technical Analysis The payment deposit procedure is not contained in the audited artifact. Instead, the Skill directs users to clone a mutable GitHub repository and run its scripts with `PRIVATE_KEY` present in the process environment. No commit hash, release archive checksum, package integrity value, or other immutable reference is specified. Any code in the external repository—including lifecycle scripts and transitive npm dependencies—can read the payer private key. Because the key grants signing authority rather than merely read access, compromise of that execution environment can lead directly to unauthorized blockchain transactions. In addition, the documented examples invoke `npx tsx` ...[truncated 1347 chars]
Remediation
## Remediation Suggestions 1. Bundle the required deposit implementation inside the reviewed project instead of directing users to mutable external code. 2. If external code is unavoidable, pin an immutable Git commit or signed release and publish a verified checksum. 3. Add `tsx` as an explicitly pinned project dependency and invoke the local binary through a package script rather than permitting `npx` to retrieve it dynamically. 4. Commit a lockfile and use reproducible installation commands such as `npm ci`. 5. Pin security-sensitive dependencies to reviewed versions rather than broad compatible ranges. 6. Prefer Privy or a hardware/restricted signer over exposing raw private keys to scripts. 7. Apply wallet policies limiting chain, contract, token, recipient, and maximum transaction value. 8. Document the exact code and dependencies that receive access to payer credentials before users execute the deposit flow.

T09 · Insecure Skill Coding Practices

Warning
Location
src/privy-signer.ts:28
Finding
Privy Signer Discards Its Provider and Cannot Reliably Broadcast Contract Transactions## Vulnerability Details **File Location**: `src/privy-signer.ts:28-35`, `src/privy-signer.ts:126-134`, `src/index.ts:158-177` **Vulnerability Type**: Incorrect custom signer/provider integration **Risk Level**: Medium ### Vulnerable Code The signer constructor calls `super()` without associating a provider, while `rpcUrl` is only stored: ```typescript constructor(options: PrivySignerOptions) { super(); this.walletId = options.walletId; this.appId = options.appId; this.appSecret = options.appSecret; this.chainId = options.chainId; this.rpcUrl = options.rpcUrl; } ``` The `connect` implementation ignores the supplied provider: ```typescript connect(provider: ethers.Provider | null): ethers.Signer { // Return new instance with provider return new PrivySigner({ walletId: this.walletId, appId: this.appId, appSecret: this.appSecret, chainId: this.chainId, rpcUrl: this.rpcUrl }); } ``` The payment path nevertheless uses this signer for a state-changing contract call and waits for a transaction receipt: ```typescript // Step 3: Call adapter (using Privy to sign the transaction) const adapter = new EVVMPaymentAdapter(adapterAddress, privySigner); const tx = await adapter.payViaEVVMWithX402({ from, to, toIdentity, amount, validAfter: authValidAfter, validBefore: authValidBefore, nonce: x402Nonce, v: x402Sig.v, r: x402Sig.r, s: x402Sig.s, receiptId, evvmNonce, isAsyncExec: useAsyncNonce, evvmSignature: evvmSig.signature }); const receipt = await tx.wait(); ``` ### Technical Analysis An ethers signer used for state-changing contract calls must be connected to a provider capable of obtaining transaction parameters and broadcasting a signed transaction. This custom signer never retains the provider supplied through `connect`, and the stored `rpcUrl` is not used to construct one. Although `sign ...[truncated 1563 chars]
Remediation
## Remediation Suggestions 1. Construct and retain an `ethers.JsonRpcProvider` from the configured RPC URL, or accept an explicit provider in `PrivySignerOptions`. 2. Associate that provider with the `AbstractSigner` base class according to the ethers v6 custom-signer contract. 3. Change `connect(provider)` so the returned signer actually uses the supplied provider. 4. Implement and test the complete transaction lifecycle: address resolution, nonce retrieval, gas estimation, fee population, Privy signing, raw transaction broadcast, and receipt confirmation. 5. Validate that the configured provider reports chain ID `1315` before signing or broadcasting. 6. Add integration tests against a controlled Story Aeneid endpoint and mock Privy service. 7. Avoid automatic retries after signing failures unless transaction hashes and nonces are checked first, preventing duplicate or ambiguous payment attempts.

T09 · Insecure Skill Coding Practices

Note
Location
SKILL.md:196
Finding
Documentation Incorrectly Claims That the Skill Does Not Transmit Secrets## Vulnerability Details **File Location**: `SKILL.md:196`, `src/privy-signer.ts:47-63`, `src/privy-signer.ts:81-91`, `src/privy-signer.ts:104-115`, `src/privy-signer.ts:138-142` **Vulnerability Type**: Misleading disclosure of credential transmission **Risk Level**: Low ### Vulnerable Documentation and Code The security documentation states: ```markdown Credentials are **user-supplied only**; this skill does not store or transmit secrets. Only create wallets or initiate payments when the user has **explicitly requested** a payment and you have configured the required credentials (see **Required credentials**). ``` However, transaction signing transmits an HTTP Basic authorization credential to Privy: ```typescript const response = await fetch(`https://auth.privy.io/api/v1/wallets/${this.walletId}/sign_transaction`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Basic ${Buffer.from(`${this.appId}:${this.appSecret}`).toString('base64')}` }, body: JSON.stringify({ chain_id: this.chainId, transaction: { to: tx.to, value: tx.value?.toString(), data: tx.data, gas: tx.gasLimit?.toString(), gasPrice: tx.gasPrice?.toString(), nonce: tx.nonce?.toString() } }) }); ``` Wallet lookup also transmits the same credentials: ```typescript const response = await fetch(`https://auth.privy.io/api/v1/wallets/${this.walletId}`, { headers: { 'Authorization': `Basic ${Buffer.from(`${this.appId}:${this.appSecret}`).toString('base64')}` } }); ``` ### Technical Analysis The App ID and App Secret are combined and Base64-encoded for HTTP Basic authentication. Base64 is encoding, not encryption; confidentiality depends on TLS. These credentials are sent to the fixed HTTPS endpoint `auth.privy.io` for wallet lookup and signing operations. Sending credentials to Privy is necessary for the declared ...[truncated 1730 chars]
Remediation
## Remediation Suggestions 1. Replace the inaccurate statement with an explicit disclosure that Privy credentials are transmitted over TLS to `https://auth.privy.io` for authentication. 2. State that the code does not intentionally send credentials to any other destination. 3. Document every Privy endpoint used and the wallet information or signing payload sent to it. 4. Recommend narrowly scoped Privy credentials and mandatory wallet policies for chain, contract, recipient, and spending limits. 5. Validate the destination URL as a fixed trusted origin and prohibit redirects that could forward authorization headers to another host. 6. Use short-lived or delegated credentials where Privy supports them, rather than a broadly privileged long-lived App Secret. 7. Ensure error handling never logs authorization headers, secrets, or complete sensitive API responses. 8. Document credential rotation and incident-response procedures.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (41)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The mismatch described here combines several dangerous issues: claimed Privy credential use without actual use, claimed adapter support without actual payment execution, and generation of EIP-3009-style signatures despite documentation saying that model does not apply to the native path. In aggregate, this can mislead users into creating transferable authorizations or exposing keys under an incorrect understanding of what the skill does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The mismatch described here combines several dangerous issues: claimed Privy credential use without actual use, claimed adapter support without actual payment execution, and generation of EIP-3009-style signatures despite documentation saying that model does not apply to the native path. In aggregate, this can mislead users into creating transferable authorizations or exposing keys under an incorrect understanding of what the skill does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The mismatch described here combines several dangerous issues: claimed Privy credential use without actual use, claimed adapter support without actual payment execution, and generation of EIP-3009-style signatures despite documentation saying that model does not apply to the native path. In aggregate, this can mislead users into creating transferable authorizations or exposing keys under an incorrect understanding of what the skill does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The mismatch described here combines several dangerous issues: claimed Privy credential use without actual use, claimed adapter support without actual payment execution, and generation of EIP-3009-style signatures despite documentation saying that model does not apply to the native path. In aggregate, this can mislead users into creating transferable authorizations or exposing keys under an incorrect understanding of what the skill does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The mismatch described here combines several dangerous issues: claimed Privy credential use without actual use, claimed adapter support without actual payment execution, and generation of EIP-3009-style signatures despite documentation saying that model does not apply to the native path. In aggregate, this can mislead users into creating transferable authorizations or exposing keys under an incorrect understanding of what the skill does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The mismatch described here combines several dangerous issues: claimed Privy credential use without actual use, claimed adapter support without actual payment execution, and generation of EIP-3009-style signatures despite documentation saying that model does not apply to the native path. In aggregate, this can mislead users into creating transferable authorizations or exposing keys under an incorrect understanding of what the skill does.

Ae1

High
Category
analysis-evasion
Content
- ✅ **Two-Agent Examples**: Direct x402, legacy adapter, and **native adapter** (`two-agents-x402-native.ts`)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- ✅ **Two-Agent Examples**: Direct x402, legacy adapter, and **native adapter** (`two-agents-x402-native.ts`)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- ✅ **Two-Agent Examples**: Direct x402, legacy adapter, and **native adapter** (`two-agents-x402-native.ts`)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `two-agents-x402-simulation.ts` — Two agents with legacy Bridge adapter
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `two-agents-x402-direct.ts` — Direct x402 transfer (no EVVM)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `agent-payment-privy-example.ts` — Privy wallets
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `agent-payment-example.ts` — Private keys (legacy)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill references capabilities that rely on environment secrets and external network access, but it does not declare any tool scope or permissions boundary. In an agent setting, missing capability declarations can cause overbroad execution, weak reviewability, and accidental authorization of secret access or outbound calls beyond what operators expect.

Session Persistence

Medium
Category
Rogue Agent
Content
## Scope

This skill provides **instructions and parameter reference** for USDC Krump (USDC.k) payments via x402 on Story Aeneid. Executable code, examples, and scripts (e.g. EVVM deposit, two-agent flows) live in the full [USDC Krump repository](https://github.com/arunnadarasa/usdckrump); use that repo to run scripts or integrate the payment logic. Only create wallets or initiate payments when the user has **explicitly requested** a payment and the required credentials are configured.

## Required credentials
Confidence
60% confidence
Finding
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Rp1

Medium
Category
MCP Rug Pull
Confidence
79% confidence
Finding
The documentation instructs users to run `npx tsx` without pinning a version, which can fetch and execute whatever package version is current at runtime. This creates a supply-chain risk because a compromised or malicious upstream release could be executed in the user's environment with access to local files, secrets, or wallet material.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The README instructs users to pass raw private keys directly on the command line without any explicit warning about shell history, process listing exposure, or use of funded wallets. In a crypto payment skill, this is especially dangerous because leaked keys can immediately lead to irreversible asset theft or unauthorized on-chain actions.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The README tells users to approve and deposit USDC.k into EVVM and then execute payment flows, but it does not clearly warn that these steps move real or testnet assets and may be irreversible depending on environment configuration. In a payment-oriented skill, omission of asset-transfer risk messaging increases the chance of accidental deposits, overfunding, or misuse of wallets during experimentation.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
This code performs a safety-critical financial operation by calling `payViaEVVM(...)` using a private key, but there is no confirmation prompt, user-facing warning before execution, or explanatory comment warning that this sends funds. For an example skill, this could lead to accidental real payment execution if copied or run as-is.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The example performs a legacy BridgeUSDC USDC.d transfer path only, despite the skill being ներկայացված as an EVVM/USDC.k payment skill. This mismatch can mislead operators into using the wrong asset and payment flow, causing failed integrations, incorrect fund transfers, or bypass of expected adapter-specific safety assumptions.

Intent-Code Divergence

Medium
Confidence
93% confidence
Finding
The header explicitly states 'x402 only' direct USDC.d transfer and 'No EVVM adapter,' directly contradicting the skill's stated EVVM/USDC.k purpose. In a payment skill, this kind of contradictory guidance is dangerous because users may execute a legacy transfer path with real credentials and funds under false assumptions about supported assets and settlement behavior.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.