Back to skill

Security audit

SnapTrade

Security checks for vulnerabilities and agentic risk

Overview

This skill is a real SnapTrade portfolio helper, but it also enables live trading, persistent scheduled financial reports, and local credential storage with insufficient guardrails.

Review carefully before installing. Use it only if you intentionally want SnapTrade scripts that can store brokerage credentials locally, read account data, create scheduled reports, and potentially place live trades. Avoid enabling trading scope or cron-based WhatsApp delivery unless you have verified the exact account, destination, permissions, and removal steps.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (6)

T06 · System Persistence

Error
Location
SKILL.md:111
Finding

Recurring Cron Job Creates Cross-Session Persistence

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/snaptrade_common.py:24
Finding

Credential File Permissions Are Applied After Writing and Fail Open

Content
View full analysis
None: p = Path(path) p.parent.mkdir(parents=True, exist_ok=True) p.write_text(json.dumps(data, indent=2)) try: os.chmod(p, 0o600) except Exception: pass ``` ### Technical Analysis The configuration file can contain `client_id`, `consumer_key`, `user_id`, and `user_secret`. The code writes these values before applying mode `0600`. For a newly created file, its initial permissions therefore depend on the process umask. For an existing file, writing it does not first verify that its current permissions are restrictive. Any failure from `os.chmod` is silently ignored. The program can consequently continue operating while the credential file remains readable by unintended local users or processes. Writing directly to the destination also lacks atomic replacement and can expose a partially written file if execution is interrupted. ### Attack Path 1. The program runs under a permissive umask, or the destination already has permissive permissions. 2. `p.write_text(...)` writes SnapTrade credentials to the file. 3. The subsequent `chmod` operation fails because of ownership, filesystem, or permission conditions. 4. The exception is suppressed without alerting the user. 5. Another local user or compromised process reads the exposed SnapTrade credentials. 6. The credentials are used to access the associated SnapTrade user and connected brokerage data, subject to the permissions granted to that integration. ### Impact Assessment Successful exploitation can disclose the SnapTrade consumer key and user secret. These credentials may permit unauthorized access to portfolio information and other API operations available to the configured integration. The immediat ...[truncated 186 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/snaptrade_reconnect.py:37
Finding

Reconnect Workflow Selects Unintended Connections and Requests Trading Scope

Content
View full analysis
1: wanted = sys.argv[1].lower() for d in connections: if d["name"] and wanted in d["name"].lower(): target = d break if target is None: # fallback to first disabled, else first connection target = disabled[0] if disabled else connections[0] resp = client.authentication.login_snap_trade_user( user_id=cfg["user_id"], user_secret=cfg["user_secret"], reconnect=target["id"], connection_type="trade", connection_portal_version="v4", immediate_redirect=False, show_close_button=True, ) ``` ### Technical Analysis The reconnect command searches all connections rather than limiting selection to disabled connections. It uses substring matching and accepts the first match. If no requested match is found, it silently falls back to the first disabled connection or, if none are disabled, the first active connection. The generated portal also requests `connection_type="trade"`, even though portfolio reporting only requires read access and the initial connection workflow uses read scope. This violates least privilege and can lead the user to authorize trading capability while intending only to restore portfolio connectivity. ### Attack Path 1. The script is invoked without a brokerage name, with an ambiguous substring, or with a name that does not match. 2. The selection logic silently chooses the first disabled or active connection. 3. The script generates a portal URL for that potentially unintended connection. 4. The portal requests trading scope rather than read-only scope. 5. The user ope ...[truncated 634 chars]
Remediation
View remediation

other

Warning
Location
scripts/snaptrade_accounts.py:12
Finding

Brokerage Account Numbers Are Disclosed Through Standard Output

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/snaptrade_order.py:9
Finding

Trade Orders Are Submitted Without Adequate Numeric Validation or Confirmation

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/snaptrade_total.py:203
Finding

Balances in Different Currencies Are Added Without Conversion

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documented ability to watch and track brokerage orders is omitted from the stated purpose. In a financial context, undisclosed order-status polling expands the operational scope from passive reporting into active trade workflow support, which can expose sensitive trading activity and enable actions the user did not reasonably expect.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The documented ability to watch and track brokerage orders is omitted from the stated purpose. In a financial context, undisclosed order-status polling expands the operational scope from passive reporting into active trade workflow support, which can expose sensitive trading activity and enable actions the user did not reasonably expect.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill presents itself as generating portfolio reports, yet the primary workflow also includes placing buy/sell orders. This mismatch is particularly dangerous in an investment context because a user may grant or trigger the skill expecting read-only reporting while the skill supports irreversible market activity.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documented ability to place securities orders is not justified by the stated purpose of connectivity and portfolio summaries. Unnecessary high-risk capability increases blast radius: if the skill is selected for benign account-linking or reporting tasks, it still exposes trade execution paths that could be misused or accidentally invoked.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documentation describes live buy/sell orders with a default market order and no explicit warning about financial loss, slippage, or irreversibility. Defaulting to market orders in particular can produce unintended execution prices, making accidental or misunderstood use especially harmful.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This script enables live order placement and post-trade monitoring, which materially exceeds the skill's declared scope of brokerage connectivity and portfolio reporting. Scope expansion into trading is dangerous because an agent or user expecting read-oriented account access could instead trigger irreversible financial transactions.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code directly calls a force-order trading API to buy or sell securities, but the stated skill purpose only covers account connectivity, portal links, registration, and portfolio summaries. In this context, live trading capability is unjustified and increases the risk of unauthorized or unexpected financial actions through the agent.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Order submission occurs immediately from command-line inputs with no confirmation prompt, no human-in-the-loop warning, and no secondary validation for a destructive financial action. A mistaken symbol, units value, account selection, or automated invocation could therefore result in real trades and direct monetary loss.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill declares no explicit tool scope or permissions even though its documented workflows require shell execution, local file reads/writes, and access to secrets. In a financial-account skill, missing scope boundaries materially increases the chance the agent can use broader capabilities than intended, including handling credentials and executing trading-related scripts without clear confinement.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The workflow instructs sending portfolio values via WhatsApp without warning that sensitive financial data is being transmitted through a third-party messaging platform. Even if only total value is sent, this can expose private financial information to external services, compromised devices, or misdirected recipients.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
- Request signing is handled by the SDK via `request_after_hook` using `consumer_key`.
- The total is computed by summing each account’s `account.balance.total` from holdings; this avoids errors when accounts are added or removed.
- If multiple currencies are present, the script uses the first currency encountered.
- Keep secrets in the local config file with `chmod 600` permissions.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This function writes credential-bearing configuration data to disk silently, which increases the chance that API secrets are persisted without the operator fully realizing it. In a brokerage-integration skill handling SnapTrade client credentials, undisclosed local secret storage raises the risk of credential exposure through backups, shared workspaces, misconfigured permissions, or later file disclosure.

Content

No source excerpt is available for this finding.

Tainted flow: 'data' from pathlib.Path.read_text (line 20, file read) → pathlib.Path.write_text (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/snaptrade_common.py (reported line 27)May include surrounding context.

python
def save_config(data: Dict[str, Any], path: str = DEFAULT_CONFIG_PATH) -> None:
    p = Path(path)
    p.parent.mkdir(parents=True, exist_ok=True)
    p.write_text(json.dumps(data, indent=2))
    try:
        os.chmod(p, 0o600)
    except Exception:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The code persists user_secret directly into the local config via save_config(cfg) without any indication of encryption, access control hardening, or user disclosure. Because this secret is later used to authenticate SnapTrade user actions, storing it in plaintext or weakly protected config increases the risk of credential theft from disk, logs, backups, or multi-user environments.

Content

No source excerpt is available for this finding.