Back to skill

Security audit

Kraken CLI

Security checks for vulnerabilities and agentic risk

Overview

This Kraken trading skill is not clearly malicious, but it combines financial account access with under-scoped networking, file, and configuration behavior that users should review carefully.

Install only if you are comfortable auditing and controlling the environment yourself. Use least-privileged Kraken API keys, avoid withdrawal/trading permissions unless needed, do not use untrusted OPENCLAW_KRAKEN_CONFIG files, do not override API or websocket hosts outside Kraken, and treat --message-file as capable of transmitting local file contents.

Vulnerability Patterns
  • 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
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
lib/kraken_validate.sh:3
Finding

Authenticated API requests can be redirected to arbitrary configured hosts

Content
View full analysis

Vulnerability Details

File Location: lib/kraken_validate.sh:3-12, lib/kraken_http.sh:22-32,43-50, and lib/kraken_futures.sh:94-120,135-142
Vulnerability Type: Insufficient destination validation for credential-bearing requests
Risk Level: High

Vulnerable Code

lib/kraken_validate.sh:3-12:

bash
kraken_validate_runtime() {
  case "$KRAKEN_API_BASE_URL" in
    https://*)
      ;;
    http://*)
      [ "$KRAKEN_ALLOW_INSECURE_BASE_URL" = "true" ] || kraken_fail "refusing insecure base URL without KRAKEN_ALLOW_INSECURE_BASE_URL=true"
      ;;
    *)
      kraken_fail "invalid base URL: $KRAKEN_API_BASE_URL"
      ;;
  esac

lib/kraken_http.sh:22-32,43-50:

bash
local nonce="" request_body="$payload" request_url="${KRAKEN_API_BASE_URL}/${KRAKEN_API_VERSION}${path}" signature=""
local -a args
args=(-sS --connect-timeout "$KRAKEN_TIMEOUT_SECS" --max-time "$KRAKEN_TIMEOUT_SECS" -A "$KRAKEN_USER_AGENT" -X "$method")

if [ "$signed" = "true" ]; then
  nonce="$(kraken_generate_nonce)"
  request_body="$(kraken_join_query "$(kraken_query_kv nonce "$nonce")" "$payload" "$(kraken_query_kv otp "${KRAKEN_OTP:-}")")"
  signature="$(kraken_sign_payload "$path" "$request_body" "$nonce")"
  args+=(-H "API-Key: $KRAKEN_API_KEY" -H "API-Sign: $signature" -H "Content-Type: application/x-www-form-urlencoded" --data "$request_body")
elif [ -n "$payload" ]; then
  request_url="${request_url}?${payload}"
fi

kraken_log info "dispatching ${method} ${request_url}"
set +x
if [ "${KRAKEN_OUTPUT_MODE:-raw}" = "raw" ] && [ -z "${KRAKEN_JQ_FILTER:-}" ]; then
  "$KRAKEN_HTTP_BIN" "${args[@]}" "$request_url"
  return
fi

response="$("$KRAKEN_HTTP_BIN" "${args[@]}" "$request_url")"

lib/kraken_futures.sh:94-120,135-142:

bash
kraken_futures_http_request() {
  local method="$1"
  local path="$2"
  local payload="${3:-}"
  local signed="$4"
  local nonce=""
 
...[truncated 3058 chars]
Remediation
View remediation

Remediation Suggestions

  • Parse URLs using a robust URL parser instead of shell prefix matching.
  • Allowlist exact approved origins, such as the intended Kraken API hostnames, with HTTPS and the expected port.
  • Reject user-information components, fragments, unexpected ports, malformed hosts, and hostnames that merely contain a trusted name as a suffix or prefix.
  • Apply equivalent validation to KRAKEN_FUTURES_API_BASE_URL before any request is prepared.
  • Do not attach private authentication headers when the destination differs from an approved Kraken origin.
  • If custom endpoints are required for local testing, place them behind a clearly named test-only option and prohibit real credentials while that option is active.
  • Add tests proving that attacker-controlled HTTPS hosts, deceptive hostname suffixes, user-information URLs, and unapproved ports are rejected for authenticated requests.

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/ws_client.mjs:10
Finding

Generic WebSocket client can transmit arbitrary readable files to arbitrary servers

Content
View full analysis

Vulnerability Details

File Location: scripts/ws_client.mjs:10-33,43-52,62-66
Vulnerability Type: Unrestricted local file read combined with unrestricted outbound transmission
Risk Level: High

Vulnerable Code

javascript
const args = process.argv.slice(2);
let url = "";
let timeoutMs = 10000;
let maxMessages = 1;
const messages = [];

for (let i = 0; i < args.length; i += 1) {
  const arg = args[i];
  switch (arg) {
    case "--url":
      url = args[++i] ?? "";
      break;
    case "--timeout-ms":
      timeoutMs = Number(args[++i] ?? "10000");
      break;
    case "--max-messages":
      maxMessages = Number(args[++i] ?? "1");
      break;
    case "--message-json":
      messages.push(args[++i] ?? "");
      break;
    case "--message-file":
      messages.push(readFileSync(args[++i] ?? "", "utf8"));
      break;
    default:
      fail(`unknown arg: ${arg}`);
  }
}

if (!url) {
  fail("missing --url");
}

const ws = new WebSocket(url);

ws.addEventListener("open", () => {
  for (const message of messages) {
    ws.send(message);
  }
});

Technical Analysis

The --url argument accepts any destination supported by the WebSocket runtime, while --message-file synchronously reads any file accessible to the process. The entire file content is placed into an outbound message and sent automatically when the connection opens.

There is no Kraken hostname allowlist, approved-directory restriction, file-size limit, content validation, or confirmation step for file transmission. This creates a direct local-file exfiltration primitive when an agent invocation can be influenced by untrusted instructions.

Attack Path

  1. An attacker causes a user or agent to invoke the WebSocket client with an attacker-controlled wss:// URL.
  2. The invocation supplies --message-file with the path of a sensitive file readable by the current process.

...[truncated 765 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove the generic arbitrary-URL mode from the Kraken-specific skill.
  • Allowlist exact Kraken WebSocket origins and require secure wss:// transport.
  • Remove arbitrary --message-file support or restrict it to a dedicated, operator-approved directory.
  • Resolve the real path and reject symbolic links, traversal outside the approved directory, non-regular files, and files exceeding a conservative size limit.
  • Prefer receiving explicitly supplied message content through standard input rather than reading arbitrary filesystem paths.
  • Require explicit user confirmation whenever local file contents will be transmitted.
  • Validate outbound messages against the expected Kraken JSON schema and reject non-JSON or unexpected authentication fields where feasible.
  • Add tests confirming that non-Kraken hosts and sensitive paths outside the approved directory are rejected.

T09 · Insecure Skill Coding Practices

Warning
Location
lib/kraken_config.sh:3
Finding

Configuration loading executes arbitrary shell code

Content
View full analysis

Vulnerability Details

File Location: lib/kraken_config.sh:3-11
Vulnerability Type: Arbitrary code execution through unsafe configuration sourcing
Risk Level: Medium

Vulnerable Code

bash
kraken_load_config() {
  local root_dir="$1"
  local version_file="$root_dir/VERSION"

  if [ -n "${OPENCLAW_KRAKEN_CONFIG:-}" ]; then
    [ -f "$OPENCLAW_KRAKEN_CONFIG" ] || kraken_fail "config file not found: $OPENCLAW_KRAKEN_CONFIG"
    # shellcheck disable=SC1090
    source "$OPENCLAW_KRAKEN_CONFIG"
  fi

Technical Analysis

Bash source does not parse a passive environment file; it executes the referenced file as shell code in the current process. A file containing command substitutions, function definitions, redirections, external commands, or variable overrides therefore executes with the same privileges and environment as the CLI.

Merely checking that the path references an existing regular file does not establish its trustworthiness, ownership, permissions, or syntax. A malicious configuration can also modify transport-related variables such as KRAKEN_HTTP_BIN, redirect API base URLs, or access credentials already present in the environment.

Attack Path

  1. An attacker creates, replaces, or modifies a file that can be selected through OPENCLAW_KRAKEN_CONFIG.
  2. The attacker places arbitrary shell commands in that file, for example commands that copy environment variables or launch another executable.
  3. The user or agent starts the CLI with OPENCLAW_KRAKEN_CONFIG referencing that file.
  4. kraken_load_config invokes source before completing runtime validation.
  5. The attacker's commands execute in the CLI process with the user's permissions and access to its environment.
  6. The commands may steal secrets, modify files, alter the selected HTTP executable, or redirect later authenticated requests.

Impact Assessment

Successful exploitation provides arbitrary command e ...[truncated 292 chars]

Remediation
View remediation

Remediation Suggestions

  • Replace source with a non-executing parser for a strict configuration format such as JSON or a restricted KEY=VALUE file.
  • Maintain an explicit allowlist of supported configuration keys.
  • Reject shell metacharacters, command substitutions, function declarations, multiline assignments, and unknown keys.
  • Validate each value before assignment, particularly URLs, executable paths, booleans, timeouts, and registry paths.
  • Open configuration files safely and verify that they are regular files with trusted ownership and non-group/non-world-writable permissions.
  • Do not permit configuration files to override executable paths unless that capability is explicitly required and separately authorized.
  • If shell sourcing must be retained for compatibility, clearly document that the file is executable code and only accept files from a trusted, permission-controlled directory; this reduces but does not eliminate the inherent risk.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is about a Kraken trading/API skill. The supplied code chunk does not query any Kraken API, use secrets, inspect account state, place trades, manage funding, or process websocket payloads. Its sole purpose is project release tooling: validating a version string, updating a local VERSION file, and printing publish/tag commands. This is a materially different primary purpose and accesses different resources than declared, so it is a clear mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description describes a full-featured Kraken trading/account CLI. The supplied code chunk is only a small support script that outputs a constant nonce value, likely for testing. It does not implement or expose any of the declared Kraken API, account, trading, funding, websocket, or secret-management functionality. This is a materially different primary purpose for the provided code chunk, so it should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill exposes shell-backed capabilities but does not declare an explicit tool scope such as permissions or allowed-tools. In an agent environment, undeclared shell access weakens containment and reviewability, increasing the chance that the skill can invoke broader command execution than operators expect.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The function reads the sensitive environment variable KRAKEN_API_SECRET and transforms it for signing, but the file contains no comment, docstring, logging, or prompt disclosing that credential material is being accessed. For code files, credential access should be accompanied by some visible explanation unless already clearly disclosed elsewhere in skill documentation, which is not present in this file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This function sends authenticated futures API requests, including account-scoped operations, without any user-visible confirmation or warning at the transport layer. In a trading skill context, this increases the chance of accidental disclosure of sensitive account data or unintended execution of private actions when higher-level safeguards are missing or bypassed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

In simulation mode, the function returns a JSON object containing the full request URL and, for signed requests, the full request body. Because signed private Kraken requests include sensitive parameters such as nonce and optional OTP, this can expose confidential account-related data to terminal output, logs, or downstream tooling without any warning or redaction. In the context of a trading skill that uses managed secrets and private account actions, this increases the chance of accidental leakage during testing or dry runs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The script reads KRAKEN_FUTURES_API_KEY and KRAKEN_FUTURES_API_SECRET from the environment and derives signing material from the secret, but there is no nearby comment or user-facing notice explaining this sensitive credential access. For safety-sensitive code, users should be informed when API credentials are required and used.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.