Back to skill

Security audit

Sim Trading MVP

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed simulated-trading workflow, but users should opt in carefully because it can create persistent paper-account files and optional recurring cron jobs.

Install only if you want a simulated, not real-money, trading workflow that keeps local paper-account state. Confirm the project path, report language, market-data source, and whether cron automation should run; keep API keys out of the skill files; and avoid relying on account valuation until the missing-price handling in the helper script is fixed.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/update_account.py:16
Finding

Incomplete Price Data Is Persisted as Authoritative Account Valuation

Content
View full analysis

Vulnerability Details

File Location: scripts/update_account.py, lines 16–23 and 32–40
Vulnerability Type: Insecure handling of incomplete and unvalidated financial data
Risk Level: Medium

Complete vulnerable code snippet:

python
def calc_equity(account: dict) -> float:
    cash = float(account.get("cash", 0))
    positions = account.get("positions", [])
    market_value = 0.0
    for pos in positions:
        qty = float(pos.get("qty", 0))
        price = pos.get("currentPrice")
        if price is None:
            continue
        market_value += qty * float(price)
    return cash + market_value


def main():
    if len(sys.argv) < 2:
        print("Usage: update_account.py <account.json>", file=sys.stderr)
        sys.exit(1)

    path = Path(sys.argv[1])
    account = load_json(path)

    equity = calc_equity(account)
    initial_cash = float(account.get("initialCash", equity or 0))
    account["equity"] = round(equity, 2)
    account["totalReturnPct"] = round(((equity - initial_cash) / initial_cash) * 100, 4) if initial_cash else 0
    account["updatedAt"] = datetime.now(timezone.utc).isoformat()

    dump_json(path, account)

Technical Analysis

calc_equity() silently excludes every position whose currentPrice is absent. It then returns the partial valuation as if it were complete. main() persists that result to the authoritative equity and totalReturnPct fields without setting an incomplete-data status, preserving the prior valuation, or aborting the update.

Consequently, a nonzero holding with no current price is implicitly valued at zero. The implementation also converts quantities and prices directly to floating-point values without checking whether they are finite or nonnegative. Special values such as NaN or Infinity, if accepted by the parser and conversion path, can contaminate valuation output.

This behavior conflicts with the Skill' ...[truncated 1831 chars]

Remediation
View remediation

Remediation Suggestions

  1. Treat a missing price for any nonzero position as an incomplete valuation rather than assigning it zero value implicitly.
  2. Abort without overwriting equity or totalReturnPct, or preserve the previous values and add an explicit status such as valuationStatus: "incomplete".
  3. Return structured calculation results containing the equity value, missing-price symbols, valuation timestamp, and completeness status.
  4. Validate that cash, initialCash, quantities, and prices are numeric, finite, and consistent with the portfolio rules. Reject negative values unless explicitly supported.
  5. Write updates atomically through a temporary file followed by replacement so validation or write failures do not partially corrupt account state.
  6. Make incomplete status visible in downstream reports and force HOLD where reliable valuation is required.
  7. Add tests covering missing prices, zero-quantity positions, malformed numeric fields, NaN, infinity, negative values, and mixed complete/incomplete portfolios.

A hardened calculation should fail explicitly for a nonzero unpriced position, for example:

python
import math

def finite_nonnegative(value, field):
    number = float(value)
    if not math.isfinite(number) or number < 0:
        raise ValueError(f"{field} must be finite and nonnegative")
    return number

def calc_equity(account):
    cash = finite_nonnegative(account.get("cash", 0), "cash")
    market_value = 0.0
    missing = []

    for pos in account.get("positions", []):
        qty = finite_nonnegative(pos.get("qty", 0), "position quantity")
        price = pos.get("currentPrice")

        if qty and price is None:
            missing.append(pos.get("ticker", "unknown"))
            continue

        if price is not None:
            market_value += qty * finite_nonnegative(
                price, "position currentPrice"
            )

    if missing:
      
...[truncated 148 chars]
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
Findings (11)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
Never hardcode, publish, commit, or echo a user's market-data API key into `SKILL.md`, reference files, public repos, or ClawHub releases.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill instructs the agent to read and write persistent local files such as account state and trade logs, but it does not declare a constrained tool scope. In practice, this can let a broadly capable agent perform filesystem actions beyond the minimally necessary project files, increasing the risk of unintended data access, overwrite, or persistence abuse.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The description uses broad triggers like acting like an investor, maintaining a model portfolio, scheduling trading decisions, or sending market reviews, which can cause the skill to activate for common finance-related requests without clear user intent for this persistent workflow. Over-broad invocation is dangerous because it can unexpectedly steer the agent into file persistence, automation setup, and quasi-advisory behavior in contexts where the user only wanted general discussion.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
86% confidence
Finding

The skill is designed to make exactly one BUY/SELL/HOLD decision in multiple daily windows and optionally automate those decisions via cron, which is autonomous decision-making in an investing context. Even though it is framed as simulated trading, autonomous recurring financial decisions and state updates can materially affect user trust, future real-world decisions, and local system state without per-action human approval.

Content

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

md
3. **Three decision windows and cron behavior**
4. **Post-market report format**

Do not skip confirmation unless the user explicitly says to use the current/default version.

## 1. Style selection

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Mandating that the post-market recap be sent in Chinese without offering language choice can cause output that does not match the user's expectations or instructions. This is primarily a safety and usability issue, but in a financial workflow it can also reduce transparency and increase the chance the user misunderstands account status, actions, or risk disclosures.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The manifest describes a workflow with three decision windows per trading day, but this guide says to 'Use four jobs' and enumerates an additional postmarket_sync job. While the recap is mentioned elsewhere in the manifest, presenting it here as a fourth trading-day job creates a semantic mismatch with the claimed three-window structure.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The instructions explicitly say to "send the user the daily recap in Chinese," and the example cron command repeats that requirement. This is a language-policy issue because it imposes a specific language without documenting user preference, opt-in, or a justified region-specific constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The notes mandate that daily output be in Chinese without indicating user choice, consent, or fallback behavior. This can cause the agent to ignore the user's language preference, reduce transparency of trading-related reporting, and create a prompt-level control that may obscure important risk, performance, or compliance-relevant information for users who do not read Chinese.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The instruction "Use concise Chinese" imposes a specific language unconditionally. Under the policy criteria, forcing a language or locale without user opt-in or clear justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The guide instructs unattended cron jobs to update persistent account and log files, but it does not clearly warn about ongoing autonomous modifications, duplicate scheduling, or unintended repeated writes. In an automation context, this can cause integrity issues, confusing state drift, and accidental overwrite/duplication of trading records, especially because the skill is designed to run repeatedly without intermediate user review.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

This file adds a concrete requirement to send the recap 'in Chinese,' including in the example cron command, but that behavior is not reflected in the manifest description. The documentation therefore narrows and changes the advertised behavior in a way the top-level skill description does not disclose.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.