Back to skill

Security audit

Lista Lending

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent for Lista lending, but it has a serious command-injection flaw in transaction execution and underprotected wallet-session metadata.

Review before installing. Only use trusted RPC endpoints, avoid enabling debug logs with wallet topics, and do not run state-changing lending operations until the executor is changed to avoid shell interpretation, such as using execFileSync or spawnSync with argument arrays.

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

T09 · Insecure Skill Coding Practices

Error
Location
src/executor.ts:21
Finding
Shell Command Injection in Wallet Transaction Execution<![CDATA[ ## Vulnerability Details **File Location**: `src/executor.ts:21-42` **Vulnerability Type**: OS command injection through unsafe shell command construction **Risk Level**: High ### Vulnerable Code ```ts const { topic, chain = "eip155:56" } = options; const { params } = step; const args = [ "call", "--topic", topic, "--chain", chain, "--to", params.to, "--data", params.data, ]; if (params.value && params.value > 0n) { args.push("--value", params.value.toString()); } try { const cmd = `node "${WALLET_CONNECT_CLI}" ${args.map((a) => `"${a}"`).join(" ")}`; const result = execSync(cmd, { encoding: "utf-8", timeout: 5 * 60 * 1000, env: { ...process.env, WALLETCONNECT_PROJECT_ID: process.env.WALLETCONNECT_PROJECT_ID, }, }); ``` ### Technical Analysis The executor builds a single command string and passes it to `execSync()`. String-based `execSync()` execution invokes a command shell. Arguments are surrounded with double quotes, but embedded quotation marks, command substitutions, and other shell metacharacters are not escaped. The WalletConnect topic can originate from the `--wallet-topic` command-line option or persisted wallet-session data. It is checked only for presence and is not constrained to an expected topic format. SDK-provided transaction fields are also interpolated into the same command string. Double-quote wrapping does not provide a safe process boundary. A malicious value containing a closing quote and shell syntax can escape the intended argument and cause the shell to interpret additional commands. ### Attack Path 1. An attacker causes a crafted WalletConnect topic to enter the application through `--wallet-topic`, persisted lending context, or wallet-session data. 2. The user or Agent invokes a state-changing lending operation such as deposit, withdraw, supply, borrow, or repay. 3. The operation reaches `executeStep()` with the attacker-controlled topic. 4. `executeStep()` i ...[truncated 1262 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Eliminate shell interpretation entirely. Execute Node directly with an argument array and explicitly disable shell processing: ```ts import { execFileSync } from "node:child_process"; const result = execFileSync( process.execPath, [WALLET_CONNECT_CLI, ...args], { encoding: "utf-8", timeout: 5 * 60 * 1000, shell: false, env: { ...process.env, WALLETCONNECT_PROJECT_ID: process.env.WALLETCONNECT_PROJECT_ID, }, } ); ``` Alternatively, use `spawnSync()` with the executable and arguments supplied separately. Apply defense-in-depth validation before process creation: - Require WalletConnect topics to match the exact format and length accepted by the wallet integration. - Restrict `chain` to the supported chain allowlist. - Validate `params.to` as an EVM address. - Validate `params.data` as bounded hexadecimal calldata. - Validate transaction values as non-negative integers within expected limits. - Resolve and verify the wallet CLI path before execution. - Add regression tests containing quotes, command substitutions, spaces, semicolons, and newline characters to verify that all values remain literal arguments. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/context.ts:173
Finding
Plaintext Persistence and Debug Logging of WalletConnect Session Topics<![CDATA[ ## Vulnerability Details **File Location**: `src/context.ts:173-177` and `src/cli/debug-log.ts:109-137` **Vulnerability Type**: Insecure storage and logging of authentication-sensitive session metadata **Risk Level**: Medium ### Vulnerable Code The complete context-writing function persists the context, including `walletTopic`, without setting an explicit restrictive file mode: ```ts export function saveContext(context: LendingContext): void { ensureConfigDir(); context.schemaVersion = CONTEXT_SCHEMA_VERSION; context.lastUpdated = new Date().toISOString(); writeFileSync(CONTEXT_FILE, JSON.stringify(context, null, 2)); } ``` The topic is placed into that context during target selection: ```ts export function setSelectedVault( vault: SelectedVault, userAddress: string, walletTopic: string, position?: UserPosition ): void { const context = loadContext(); context.selectedVault = vault; context.selectedMarket = null; context.userAddress = userAddress; context.walletTopic = walletTopic; context.userPosition = position || null; saveContext(context); } ``` Debug logging records the full command-line argument list and propagates the same log destination to the wallet child process: ```ts export function setupDebugLogFile(skill: string, cliLogFile?: string): string | null { const requested = cliLogFile || process.env.SKILL_DEBUG_LOG_FILE || process.env.DEBUG_LOG_FILE; if (!requested) return null; const filePath = resolve(requested); try { mkdirSync(dirname(filePath), { recursive: true }); } catch { // Ignore and continue. } // Propagate to child processes (lista-lending -> lista-wallet-connect). process.env.SKILL_DEBUG_LOG_FILE = filePath; const flushStdout = patchWriteStream("stdout", process.stdout, filePath, skill); const flushStderr = patchWriteStream("stderr", process.stderr, filePath, skill); const flushAll = (): void => { flushStdout(); flushStderr(); }; process.on("befo ...[truncated 2814 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Avoid persisting WalletConnect topics in the lending context when they can be resolved from the dedicated wallet-session manager at execution time. - If persistence is required, create `~/.agent-wallet` with mode `0o700` and sensitive files with mode `0o600`. - Verify and correct permissions on existing files before reading or rewriting them. - Use atomic writes through a mode-restricted temporary file followed by a rename. - Redact `--wallet-topic` and its following value before storing `process.argv`. - Apply recursive redaction to structured output fields named `topic`, `authorization`, `token`, `secret`, and similar sensitive keys. - Consider redacting transaction calldata and RPC credentials embedded in configured URLs. - Restrict debug logs to a dedicated owner-only directory instead of accepting unrestricted destinations by default. - Do not propagate unredacted debug configuration to child processes unless explicitly required. - Define log retention and secure-deletion behavior for files containing wallet or transaction metadata. ]]>
Vulnerability Patterns
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (105)

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding
The actual risk here is not description mismatch but that the skill persists custom RPC URLs in a local config file and allows them to influence blockchain interactions. In a financial skill, unsafe or malicious RPC endpoints can mislead reads, censor transactions, or degrade trust in simulations and transaction preparation, increasing user risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The actual risk here is not description mismatch but that the skill persists custom RPC URLs in a local config file and allows them to influence blockchain interactions. In a financial skill, unsafe or malicious RPC endpoints can mislead reads, censor transactions, or degrade trust in simulations and transaction preparation, increasing user risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The actual risk here is not description mismatch but that the skill persists custom RPC URLs in a local config file and allows them to influence blockchain interactions. In a financial skill, unsafe or malicious RPC endpoints can mislead reads, censor transactions, or degrade trust in simulations and transaction preparation, increasing user risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The actual risk here is not description mismatch but that the skill persists custom RPC URLs in a local config file and allows them to influence blockchain interactions. In a financial skill, unsafe or malicious RPC endpoints can mislead reads, censor transactions, or degrade trust in simulations and transaction preparation, increasing user risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The actual risk here is not description mismatch but that the skill persists custom RPC URLs in a local config file and allows them to influence blockchain interactions. In a financial skill, unsafe or malicious RPC endpoints can mislead reads, censor transactions, or degrade trust in simulations and transaction preparation, increasing user risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The actual risk here is not description mismatch but that the skill persists custom RPC URLs in a local config file and allows them to influence blockchain interactions. In a financial skill, unsafe or malicious RPC endpoints can mislead reads, censor transactions, or degrade trust in simulations and transaction preparation, increasing user risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The actual risk here is not description mismatch but that the skill persists custom RPC URLs in a local config file and allows them to influence blockchain interactions. In a financial skill, unsafe or malicious RPC endpoints can mislead reads, censor transactions, or degrade trust in simulations and transaction preparation, increasing user risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The actual risk here is not description mismatch but that the skill persists custom RPC URLs in a local config file and allows them to influence blockchain interactions. In a financial skill, unsafe or malicious RPC endpoints can mislead reads, censor transactions, or degrade trust in simulations and transaction preparation, increasing user risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The actual risk here is not description mismatch but that the skill persists custom RPC URLs in a local config file and allows them to influence blockchain interactions. In a financial skill, unsafe or malicious RPC endpoints can mislead reads, censor transactions, or degrade trust in simulations and transaction preparation, increasing user risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The actual risk here is not description mismatch but that the skill persists custom RPC URLs in a local config file and allows them to influence blockchain interactions. In a financial skill, unsafe or malicious RPC endpoints can mislead reads, censor transactions, or degrade trust in simulations and transaction preparation, increasing user risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The actual risk here is not description mismatch but that the skill persists custom RPC URLs in a local config file and allows them to influence blockchain interactions. In a financial skill, unsafe or malicious RPC endpoints can mislead reads, censor transactions, or degrade trust in simulations and transaction preparation, increasing user risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The actual risk here is not description mismatch but that the skill persists custom RPC URLs in a local config file and allows them to influence blockchain interactions. In a financial skill, unsafe or malicious RPC endpoints can mislead reads, censor transactions, or degrade trust in simulations and transaction preparation, increasing user risk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The actual risk here is not description mismatch but that the skill persists custom RPC URLs in a local config file and allows them to influence blockchain interactions. In a financial skill, unsafe or malicious RPC endpoints can mislead reads, censor transactions, or degrade trust in simulations and transaction preparation, increasing user risk.

Ae1

High
Category
analysis-evasion
Content
> **Agent quick check:** `node dist/cli/cli.bundle.mjs version`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
> **Agent quick check:** `node dist/cli/cli.bundle.mjs version`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
> **Agent quick check:** `node dist/cli/cli.bundle.mjs version`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
> **Agent quick check:** `node dist/cli/cli.bundle.mjs version`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
> **Agent quick check:** `node dist/cli/cli.bundle.mjs version`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
> **Agent quick check:** `node dist/cli/cli.bundle.mjs version`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
> **Agent quick check:** `node dist/cli/cli.bundle.mjs version`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
> **Agent quick check:** `node dist/cli/cli.bundle.mjs version`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
> **Agent quick check:** `node dist/cli/cli.bundle.mjs version`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
> **Agent quick check:** `node dist/cli/cli.bundle.mjs version`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
> **Agent quick check:** `node dist/cli/cli.bundle.mjs version`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
> **Agent quick check:** `node dist/cli/cli.bundle.mjs version`
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
dist/cli/cli.bundle.mjs:776

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
dist/executor.js:27

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/executor.ts:42