Back to skill

Security audit

Uniswap V4

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its Uniswap purpose, but it should be reviewed because it can create real, long-lived token approvals and the artifact still contains unsafe legacy scripts.

Install only if you intend to let an agent interact with Uniswap and, when PRIVATE_KEY is provided, sign irreversible transactions. Use a dedicated low-balance wallet, review token, amount, recipient, slippage, chain, and spender before any write operation, avoid auto-approve unless you understand the allowance risk, and revoke allowances after use. Do not run the legacy shell scripts or the bootstrap curl-to-bash recommendation.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (4)

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/bootstrap.sh:19
Finding

Unverified Remote Installer Piped Directly to Bash

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/approve.sh:64
Finding

Wallet Private Key Exposed Through Process Command-Line Arguments

Content
View full analysis
/dev/null) ``` ```bash # Step 1: ERC20 approve Permit2 log "Step 1: Approving Permit2 to spend $SYM..." TX1=$(cast send "$TOKEN" "approve(address,uint256)" \ "${PERMIT2[$CHAIN]}" "$(cast max-uint)" \ --private-key "$PRIVATE_KEY" --rpc-url "$RPC_URL" --json 2>/dev/null) || true HASH1=$(echo "$TX1" | jq -r '.transactionHash // "failed"' 2>/dev/null || echo "failed") log " TX: $HASH1" # Step 2: Permit2 approve Universal Router log "Step 2: Granting Universal Router allowance on Permit2..." # FIX M-05: Standardize Permit2 expiry (use max uint48 for long-lived approvals) MAX_UINT160="1461501637330902918203684832716283019655932542975" EXPIRY="281474976710655" # type(uint48).max TX2=$(cast send "${PERMIT2[$CHAIN]}" \ "approve(address,address,uint160,uint48)" \ "$TOKEN" "${UNIVERSAL_ROUTER[$CHAIN]}" \ "$MAX_UINT160" "$EXPIRY" \ --private-key "$PRIVATE_KEY" --rpc-url "$RPC_URL" --json 2>/dev/null) || true ``` Equivalent exposure occurs in `scripts/swap.sh`, including the final transaction: ```bash TX_RESULT=$(cast send "${UNIVERSAL_ROUTER[$CHAIN]}" \ "execute(bytes,bytes[],uint256)" \ "$COMMANDS" "[$V4_INPUT]" "$DEADLINE" \ --value "$ETH_VALUE" \ --private-key "$PRIVATE_KEY" \ --rpc-url "$RPC_URL" \ ...[truncated 1878 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/approve.sh:21
Finding

Unlimited Base Token Allowances Granted to Inconsistent Contract Addresses

Content
View full analysis
/dev/null) || true MAX_UINT160="1461501637330902918203684832716283019655932542975" EXPIRY="281474976710655" # type(uint48).max TX2=$(cast send "${PERMIT2[$CHAIN]}" \ "approve(address,address,uint160,uint48)" \ "$TOKEN" "${UNIVERSAL_ROUTER[$CHAIN]}" \ "$MAX_UINT160" "$EXPIRY" \ --private-key "$PRIVATE_KEY" --rpc-url "$RPC_URL" --json 2>/dev/null) || true ``` These addresses conflict with the project’s canonical Base configuration in `src/lib/addresses.ts:27-31`: ```ts base: { chainId: 8453, poolManager: "0x498581fF718922c3f8e6A244956aF099B2652b2b", universalRouter: "0x6ff5693b99212da76ad316178a184ab56d299b43", permit2: "0x000000000022D473030F116dDEE9F6B43aC78BA3", ``` ### Technical Analysis The bundled legacy scripts authorize Base contracts that differ from the addresses declared in `SKILL.md`, `package.json`, and `src/lib/addresses.ts`. The first approval is effectively unlimited ERC-20 spending authority, while the second uses the maximum `uint160` allowance and maximum `uint48` expiration. The legacy scripts do not verify the RPC chain ID or confirm that the configured spende ...[truncated 1834 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/approve.sh:86
Finding

Approval Script Falsely Reports Success After Transaction Failures

Content
View full analysis
/dev/null) || true HASH1=$(echo "$TX1" | jq -r '.transactionHash // "failed"' 2>/dev/null || echo "failed") log " TX: $HASH1" # Step 2: Permit2 approve Universal Router log "Step 2: Granting Universal Router allowance on Permit2..." # FIX M-05: Standardize Permit2 expiry (use max uint48 for long-lived approvals) MAX_UINT160="1461501637330902918203684832716283019655932542975" EXPIRY="281474976710655" # type(uint48).max TX2=$(cast send "${PERMIT2[$CHAIN]}" \ "approve(address,address,uint160,uint48)" \ "$TOKEN" "${UNIVERSAL_ROUTER[$CHAIN]}" \ "$MAX_UINT160" "$EXPIRY" \ --private-key "$PRIVATE_KEY" --rpc-url "$RPC_URL" --json 2>/dev/null) || true HASH2=$(echo "$TX2" | jq -r '.transactionHash // "failed"' 2>/dev/null || echo "failed") log " TX: $HASH2" if [[ "$JSON_OUTPUT" == "true" ]]; then echo "{\"success\":true,\"token\":\"$TOKEN\",\"symbol\":\"$SYM\",\"erc20ApproveTx\":\"$HASH1\",\"permit2ApproveTx\":\"$HASH2\"}" ``` ### Technical Analysis Both `cast send` failures are suppressed with `|| true`. The script converts absent transaction hashes to the literal value `"failed"` but unconditionally emits `"success":true` in JSON mode. The script also does not verify transaction receipt status before claiming success. A transaction hash alone indicates submission, not successful execution. Because Skill entry points are commonly consumed by agents and automation, the structured `success` field is a security-relevant trust boundary. Partial failure is especially dangerous in the two-step approval flow ...[truncated 1170 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (90)

Known Vulnerable Dependency: vitest==3.2.4 — 2 advisory(ies): CVE-2026-47429 (When Vitest UI server is listening, arbitrary file can be read and executed); CVE-2026-84373 (Vitest: Path Traversal / Arbitrary File Read via @vitest/mocker Redirect Mock)

Critical
Category
Supply Chain
Confidence
95% confidence
Finding

vitest 3.2.4 is a real vulnerable dev dependency with arbitrary file read and possible code execution exposure when the UI server or mocker features are used. Although this is not production runtime code, the skill's blockchain context raises the stakes because developer or CI compromise could expose private keys, permit data, or deployment credentials.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: vitest==3.2.4 — 2 advisory(ies): CVE-2026-47429 (When Vitest UI server is listening, arbitrary file can be read and executed); CVE-2026-84373 (Vitest: Path Traversal / Arbitrary File Read via @vitest/mocker Redirect Mock)

Critical
Category
Supply Chain
Confidence
97% confidence
Finding

vitest 3.2.4 is reported with critical advisories involving arbitrary file read and possible execution in affected configurations. Even though this is a dev/test dependency, test tooling often runs in CI and developer environments with repository secrets, making compromise of local files, tokens, or build infrastructure materially dangerous.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description overstates the functionality present in this code chunk. The script clearly implements swap execution plus token/Permit2 approvals, and it does include pool discovery by calling an external helper and selecting the highest-liquidity pool. However, several declared capabilities are absent or materially different: (1) chain support is limited to base and ethereum only, with no Base Sepolia entries; (2) quoting is not done through the on-chain V4Quoter, but instead through a local formula using sqrtPriceX96, which is a different capability and less accurate than a router/quoter-based quote; and (3) the script does not expose general pool-state reading functionality as described. The primary purpose is still related to Uniswap V4 swaps, but the declared description is broader and partially inaccurate for this supplied code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The description substantially overstates the skill’s behavior. The code only supports read operations for Uniswap V4 pool discovery/state inspection on Base and Ethereum. It does not perform swaps, approvals, transaction signing, or quoting, and it lacks any private-key handling. It also does not support Base Sepolia despite the description claiming it. While parts of the description about reading pool info and finding pools are partially aligned, the primary declared functionality includes several major undeclared-in-code capabilities, making this a material description/behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description says this skill performs on-chain Uniswap V4 operations and pool queries across multiple networks. However, the supplied code chunk contains only generic CLI helper functions and security checks around argument parsing. It does not interact with Ethereum/Base, wallets, RPC providers, smart contracts, pool state, Permit2, or swap routing. This is not merely a supporting implementation detail unless accompanied by substantial additional code; based on this chunk alone, the actual behavior is materially different from the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description describes a blockchain trading and pool-inspection skill, but the provided code chunk only contains tests for command-line argument parsing behavior. The code’s actual purpose is validating CLI parsing and private-key flag rejection, which is unrelated to Uniswap V4 operations. This is a materially different primary purpose, so the description does not accurately represent the supplied code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The supplied code chunk does not implement Uniswap V4 swapping, pool inspection, quoting, pool selection, Permit2 setup, or swap execution logic. Instead, its primary purpose is security testing: ensuring the PRIVATE_KEY environment variable is not leaked in CLI output. That is materially different from the declared end-user functionality. While this test could be a supporting part of a larger Uniswap-related project, the chunk itself is unrelated to the declared operational capabilities and therefore is a description-behavior mismatch for this specific code segment.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description describes a full-featured Uniswap V4 integration for on-chain reads and writes. The actual code chunk is only a test runner configuration file for Vitest. Its primary purpose is unrelated to blockchain operations and it does not implement any of the declared capabilities. Therefore, the description does not accurately represent the supplied code chunk.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
4. **Execute swap?** → `src/swap.ts` (write, ~300-350K gas, needs `PRIVATE_KEY`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
4. **Execute swap?** → `src/swap.ts` (write, ~300-350K gas, needs `PRIVATE_KEY`)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
4. **Execute swap?** → `src/swap.ts` (write, ~300-350K gas, needs `PRIVATE_KEY`)

Known Vulnerable Dependency: brace-expansion==1.1.12 — 4 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-14257 (brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro) +1 more

High
Category
Supply Chain
Confidence
93% confidence
Finding

brace-expansion 1.1.12 is present only as a transitive development dependency under eslint-related tooling, and the cited issues are denial-of-service conditions triggered by attacker-controlled glob/brace patterns. In this skill's runtime context, package-lock.json itself does not expose that parsing surface to untrusted users, so this is a real vulnerable package but with limited practical impact on the deployed skill.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: minimatch==3.1.2 — 3 advisory(ies): CVE-2026-27904 (minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regu); CVE-2026-26996 (minimatch has a ReDoS via repeated wildcards with non-matching literal in patter); CVE-2026-27903 (minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adja)

High
Category
Supply Chain
Confidence
94% confidence
Finding

minimatch 3.1.2 is a real vulnerable transitive dependency with ReDoS risk when matching crafted glob patterns. Here it appears in development/tooling paths rather than swap execution logic, so exploitation would generally require an attacker to influence developer-side glob inputs or CI tasks.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: brace-expansion==2.0.2 — 4 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-14257 (brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro) +1 more

High
Category
Supply Chain
Confidence
92% confidence
Finding

brace-expansion 2.0.2 is a genuine vulnerable package with DoS-style expansion issues on crafted patterns. In this project it is part of development dependency resolution, not token swap logic, so the practical exploitability against end users is low unless untrusted input reaches build/test tooling.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: flatted==3.3.3 — 2 advisory(ies): CVE-2026-32141 (flatted vulnerable to unbounded recursion DoS in parse() revive phase); CVE-2026-33228 (Prototype Pollution via parse() in NodeJS flatted)

High
Category
Supply Chain
Confidence
90% confidence
Finding

flatted 3.3.3 has real DoS/prototype-pollution advisories, but in this lockfile it is only a transitive development dependency under caching/tooling. There is no indication the production Uniswap skill parses attacker-controlled flatted payloads, so the vulnerable package exists but is not high-risk in context.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: js-yaml==4.1.1 — 4 advisory(ies): CVE-2026-84375 (js-yaml: maxTotalMergeKeys does not limit CPU use for empty merge sources); CVE-2026-59869 (js-yaml: YAML merge-key chains can force quadratic CPU consumption); GHSA-5p4m-2wfm-xmqj (JS-YAML: Quadratic CPU consumption in !!omap resolution (3.x and 4.x) — CVE-2026) +1 more

High
Category
Supply Chain
Confidence
91% confidence
Finding

js-yaml 4.1.1 is a real dependency with multiple resource-consumption issues when parsing crafted YAML. Here it is transitively used by eslint configuration tooling rather than by the token swap or quoting functionality, which substantially lowers the operational impact.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: minimatch==9.0.5 — 3 advisory(ies): CVE-2026-27904 (minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regu); CVE-2026-26996 (minimatch has a ReDoS via repeated wildcards with non-matching literal in patter); CVE-2026-27903 (minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adja)

High
Category
Supply Chain
Confidence
88% confidence
Finding

minimatch 9.0.5 is flagged for ReDoS on malicious glob patterns, and it is a real vulnerable package if the advisory is accurate. In this repository it appears in development/test tooling, so the main risk is denial of service in local automation or CI jobs that accept attacker-influenced glob input.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: nanoid==3.3.11 — 3 advisory(ies): CVE-2026-67214 (nanoid: non-secure generators can loop indefinitely with negative size); CVE-2026-67213 (nanoid: custom generators can loop indefinitely when size is zero); CVE-2026-73086 (nanoid: Integer Overflow or Wraparound)

High
Category
Supply Chain
Confidence
80% confidence
Finding

nanoid 3.3.11 is a real vulnerable package under the cited advisories, but it is present only through dev tooling such as postcss/vite. The issues are primarily reliability and potential DoS conditions, not direct compromise of swap execution or private-key handling in this skill.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: picomatch==4.0.3 — 2 advisory(ies): CVE-2026-33672 (Picomatch: Method Injection in POSIX Character Classes causes incorrect Glob Mat); CVE-2026-33671 (Picomatch has a ReDoS vulnerability via extglob quantifiers)

High
Category
Supply Chain
Confidence
89% confidence
Finding

picomatch 4.0.3 is a genuine vulnerable glob-matching dependency with possible ReDoS/matching flaws on crafted patterns. In this project it is only in the dev/build pipeline, so the danger is mostly limited to developer or CI environments rather than runtime agent operations.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: postcss==8.5.6 — 4 advisory(ies): CVE-2026-45623 (PostCSS: Arbitrary file read and information disclosure via attacker-controlled ); CVE-2026-69153 (PostCSS: incomplete fix of GHSA-6g55-p6wh-862q — attacker-controlled sourceMappi); CVE-2026-41305 (PostCSS has XSS via Unescaped </style> in its CSS Stringify Output) +1 more

High
Category
Supply Chain
Confidence
87% confidence
Finding

postcss 8.5.6 is a real vulnerable dependency with advisories involving file read and output-encoding issues, but it is transitively brought in by vite and used for front-end/build tooling. That makes it far less dangerous for this server-side Uniswap skill unless developers run exposed dev tooling or process hostile CSS inputs.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: rollup==4.57.1 — 1 advisory(ies): CVE-2026-27606 (Rollup 4 has Arbitrary File Write via Path Traversal)

High
Category
Supply Chain
Confidence
90% confidence
Finding

rollup 4.57.1 is a real vulnerable dev dependency with an arbitrary file write/path traversal advisory. While not part of normal production swap execution, build systems are higher-value targets because compromise of developer or CI environments could tamper with artifacts or leak secrets.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: vite==7.3.1 — 5 advisory(ies): CVE-2026-39365 (Vite Vulnerable to Path Traversal in Optimized Deps `.map` Handling); CVE-2026-53571 (vite: `server.fs.deny` bypass on Windows alternate paths); CVE-2026-39363 (Vite Vulnerable to Arbitrary File Read via Vite Dev Server WebSocket) +2 more

High
Category
Supply Chain
Confidence
92% confidence
Finding

vite 7.3.1 is a real vulnerable dev dependency with multiple file-read and path traversal issues centered on the dev server. In the context of a wallet-capable blockchain skill, compromise of a developer workstation or CI environment is more concerning because secrets, RPC credentials, or signing material may be nearby even if vite is not shipped to production.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ws==8.17.1 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
90% confidence
Finding

ws 8.17.1 is a real runtime dependency through ethers, with advisories for memory disclosure and memory exhaustion. Because this skill interacts with blockchain providers and may use WebSocket connections for on-chain data, a vulnerable ws library is more relevant than purely dev-only findings and could affect availability or potentially leak process memory in specific scenarios.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
96% confidence
Finding

The script recommends installing Foundry by piping a remote curl response directly into bash, which executes network-fetched code without verification, pinning, or integrity checks. If the remote host, TLS trust chain, DNS resolution, or delivery path is compromised, a user following the printed instruction could run attacker-controlled code on their system.

Content

Scanner excerpt · scripts/bootstrap.sh (reported line 21)May include surrounding context.

sh
# Foundry (cast)
export PATH="$HOME/.foundry/bin:$PATH"
check "cast" "curl -L https://foundry.paradigm.xyz | bash && foundryup"

# Python 3
check "python3" "apt install python3  (or brew install python3)"

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script performs token approvals, Permit2 approvals, and a swap immediately with no confirmation or dry-run step. In an agent-skill context, this is especially dangerous because automated or malformed inputs can trigger irreversible on-chain transactions, including broad approvals that may outlive the swap and increase downstream fund-loss risk.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.dynamic_code_execution, suspicious.env_credential_access (+1 more)

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/security-scan.mjs:3

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
tests/unit/no-secret-leak.test.ts:23

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/security-scan.mjs:3

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
tests/fork/swap.test.ts:19

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
tests/mainnet/smoke.test.ts:19

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
tests/unit/no-secret-leak.test.ts:27