Back to skill

Security audit

Storyclaw Alpaca Trading

Security checks for vulnerabilities and agentic risk

Overview

This Alpaca trading skill is mostly about its stated purpose, but it includes under-documented scripts that can place real trades automatically and handles brokerage credentials too broadly.

Review carefully before installing. Use paper-trading credentials only unless you have audited and modified the scripts to require explicit confirmation, live-mode opt-in, endpoint allowlisting, credential-path validation, and clear risk limits. Do not run the undocumented aggressive or momentum strategy scripts with live credentials.

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

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/config-loader.js:11
Finding

Credential file path traversal through an unvalidated user identifier

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/trading.js:31
Finding

Alpaca API credentials can be transmitted to arbitrary configured hosts

Content
View full analysis
{ const urlObj = new URL(url); const options = { hostname: urlObj.hostname, port: urlObj.port || 443, path: urlObj.pathname + urlObj.search, method, headers: { "APCA-API-KEY-ID": API_KEY, "APCA-API-SECRET-KEY": API_SECRET, "Content-Type": "application/json", }, }; const req = https.request(options, (res) => { let body = ""; res.on("data", (chunk) => (body += chunk)); res.on("end", () => { try { const json = JSON.parse(body); if (res.statusCode >= 400) { reject(new Error(`API Error [${res.statusCode}]: ${json.message || body}`)); } else { resolve(json); } } catch (e) { resolve(body); } }); }); req.on("error", reject); if (data) req.write(JSON.stringify(data)); req.end(); }); } ``` The same request pattern is independently implemented in `scripts/momentum-strategy.js`: ```javascript const BASE_URL = config.baseUrl || "https://paper-api.alpaca.markets"; const DATA_URL = config.dataUrl || "https://data.alpaca.markets"; function request(method, url, data = null) { return new Promise((resolve, reject) => { const urlObj = new URL(url); const options = { hostname: urlObj.hostname, port: urlObj.port || 443, path: urlObj.pathname + ur ...[truncated 1989 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/trading.js:420
Finding

Automated strategies submit market orders without enforcing explicit confirmation

Content
View full analysis
p.symbol === displaySym || p.symbol === symbol); if (rsi < 30 && !hasPosition) { console.log("✅ RSI < 30 and no position → BUY signal"); return await this.buy(symbol, qty); } else if (rsi > 70 && hasPosition) { console.log("✅ RSI > 70 and has position → SELL signal"); return await this["sell-all"](symbol); } else { console.log("⏸ No action: RSI in neutral zone or position mismatch"); return null; } }, ``` The momentum strategy automatically performs stop-loss and portfolio-rotation trades: ```javascript async function checkStopLoss(positions) { console.log("🛡️ 检查止损...\n"); for (const position of positions) { const lossPercent = position.unrealizedPLPercent; if (lossPercent <= -STOP_LOSS * 100) { console.log(`🚨 ${position.symbol} 触发止损!亏损 ${lossPercent.toFixed(2)}%`); console.log(` 卖出 ${position.qty} 股,止损价 $${position.currentPrice.toFixed(2)}\n`); await request("POST", `${BASE_URL}/v2/orders`, { symbol: position.symbol, qty: position.qty, side: "sell", type: "market", time_in_force: "day", }); console.log(`✅ ${position.symbol} 止损订单已提交\n`); } } } ``` ```javascript async function main() { try { console.log(" ...[truncated 2592 chars]
Remediation
View remediation
``` 4. Revalidate prices, balances, positions, and plan expiry immediately before execution. Reject confirmation if any material plan input changed. 5. Require an additional explicit `--live` opt-in when the destination is the live Alpaca API. Display a prominent distinction between paper and live environments. 6. Add configurable limits for maximum order value, daily turnover, position concentration, cumulative loss, and number of orders. 7. Prevent unattended execution unless the user has separately enabled a documented automation policy with defined symbols, limits, duration, and revocation controls. 8. Document `momentum-strategy.js` and every behavior that can submit orders in `SKILL.md`. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/aggressive-strategy.js:13
Finding

Shell command construction creates a latent command-injection sink

Content
View full analysis
0) { const result = exec(`node trading.js buy ${symbol} ${shares}`); console.log(result); return { shares, price, total: shares * price }; } return null; } ``` ```javascript if (pnlPct >= targetProfit) { console.log(`🎉 Target reached! Taking profit at +${(pnlPct * 100).toFixed(2)}%`); exec(`node trading.js sell ${symbol} ${shares}`); return true; } if (pnlPct <= -stopLoss) { console.log(`🛑 Stop loss triggered at ${(pnlPct * 100).toFixed(2)}%`); exec(`node trading.js sell ${symbol} ${shares}`); return true; } ``` ### Technical Analysis The script constructs shell command strings using template interpolation and passes them to `execSync()`. Shell metacharacters contained in interpolated values would be interpreted by the operating system shell rather than treated as literal command arguments. In the currently reviewed entry points, `symbol` is supplied as the hard-coded value `NVDA`, so a direct user-controlled exploitation route is not presen ...[truncated 1550 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

A description-behavior mismatch is dangerous in a financial trading skill because users and reviewers may approve it based on a benign summary while the underlying behavior is materially different and potentially more aggressive. If the skill can execute strategies or allocations not clearly disclosed, it could cause unauthorized or unexpectedly risky trades, especially when real trading is supported.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

A description-behavior mismatch is dangerous in a financial trading skill because users and reviewers may approve it based on a benign summary while the underlying behavior is materially different and potentially more aggressive. If the skill can execute strategies or allocations not clearly disclosed, it could cause unauthorized or unexpectedly risky trades, especially when real trading is supported.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

buyMaxShares computes shares from the full available cash balance and then submits a buy order for the maximum amount, effectively enabling an all-in trade without a strong warning or confirmation step. In the context of a skill capable of real trading, this materially raises the chance of catastrophic loss from accidental invocation, stale prices, slippage, or misuse.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The strategy automatically submits sell orders when profit or stop-loss thresholds are met, with no user confirmation or safeguard before placing real trades. In a trading skill that supports real-money accounts, this can cause irreversible liquidation from parsing errors, faulty market data, or accidental execution in the wrong environment.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The RSI strategy can place live market buy and sell orders automatically with no confirmation prompt, dry-run default, or explicit warning that real funds may be used depending on configuration. In a trading skill, this is especially dangerous because a simple command invocation can trigger irreversible financial transactions and losses, amplified by support for both paper and real Alpaca endpoints.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill documents access to sensitive environment variables and operational shell commands, but does not declare an explicit tool scope such as allowed tools or permissions. In a trading skill that can place real orders, missing scope boundaries increases the chance of overbroad execution or unintended access to secrets and command execution paths.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill instructs users to store Alpaca API keys in local JSON files or environment variables without warning about secret exposure, filesystem permissions, accidental commits, or multi-user isolation risks. Because these credentials can enable real trades, leakage could directly lead to account abuse, unauthorized orders, or financial loss.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The script wraps child_process.execSync in a generic exec helper and uses shell command strings to drive trading actions. Even though current call sites use mostly fixed commands, this adds unnecessary command-execution capability to a financial automation script and includes one interpolated argument path (symbol), increasing the blast radius if inputs are ever widened or reused unsafely.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The script loads apiKey and apiSecret from config.json and uses them for outbound API requests, which is access to sensitive credentials. While the file contains technical comments and runtime logs, there is no explicit warning or disclosure to the user that credentials will be read and transmitted to a brokerage API.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The check command prints configuration status and setup guidance in Chinese, while most other output in the script is in English. This creates a fixed language experience without opt-in or documented locale justification, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The file's natural-language comments and all console output are written in Chinese, and there is no indication that the user can choose another language or locale. This can violate language/locale policy when a skill imposes a specific language without opt-in.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest describes trading, quotes, orders, positions, and an RSI strategy, but does not mention portfolio equity history or performance-curve reporting. This file adds a broader account analytics capability by querying and displaying historical account equity and profit/loss over time.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.exposed_secret_literal

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/aggressive-strategy.js:15

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/momentum-strategy.js:28

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
scripts/trading.js:29