Back to skill

Security audit

Portfolio Trader

Security checks for vulnerabilities and agentic risk

Overview

This SnapTrade skill is mostly coherent for portfolio reporting, but it also enables live brokerage trades and stores financial credentials without enough safety controls or upfront disclosure.

Install only if you intentionally want this skill to access brokerage data and you understand it contains live-trading capability. Before use, remove or disable the order scripts unless trading is required, require explicit confirmation and checked-order previews for any trade, protect the SnapTrade config file, and avoid forwarding financial reports through WhatsApp unless you accept that privacy exposure.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/snaptrade_order.py:9
Finding

Direct Force-Order Execution Without Pre-Trade Validation or Confirmation

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/snaptrade_common.py:24
Finding

Credential File Is Written Before Restrictive Permissions Are Enforced

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 contains the SnapTrade `consumer_key` and, after registration, the user's `user_secret`. The file is written before mode `0600` is applied. Consequently, the permissions present during creation depend on the process umask. If the file already exists, writing it preserves its existing permission mode until the subsequent `chmod`. The permission change is wrapped in a broad exception handler that silently ignores all failures. If `chmod` fails because of ownership, filesystem behavior, or another environmental condition, execution continues with no warning even when the secret file remains accessible to other local users or processes. The implementation also follows a path supplied through `SNAPTRADE_CONFIG` without checking whether the target is a symbolic link or whether its parent directory is securely owned. ### Attack Path 1. The process runs with a permissive umask, an insecure pre-existing configuration file, or an attacker-influenced `SNAPTRADE_CONFIG` path. 2. `snaptrade_portal.py` registers a user and adds `user_secret` to the configuration. 3. `save_config` writes the credentials before restrictive permissions are established. 4. The `chmod` operation fails or leaves a window during which the file is more broadly readable. 5. A local user or process reads the SnapTrade client credentials and user secret. 6. The exposed credentials are used to access linked account data or invoke trading operations permitted to that SnapTrade user. ## ...[truncated 483 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/snaptrade_accounts.py:12
Finding

Brokerage Account Numbers Are Exposed Through Standard Output

Content
View full analysis
Remediation
View remediation
4 else "****" ``` 3. Do not include account numbers in synchronization diagnostics. Use a non-sensitive internal account ID or a masked label. 4. Keep the total-report output schema limited to the documented minimum: ```python result = { "total_value": round(total_value, 2), "currency": currency, } ``` 5. Send diagnostic information to a protected logging sink or standard error rather than including it in machine-readable output intended for forwarding. 6. Add an explicit command-line option before exposing even masked account metadata, and clearly warn that the output is sensitive. 7. Ensure scheduled jobs and messaging integrations apply output allowlisting rather than forwarding arbitrary script output. 8. Review and restrict retention and access controls for existing logs or messages that may already contain full account numbers. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill description does not clearly disclose order-monitoring functionality tied to brokerage order execution. While monitoring is less severe than placing orders, hidden execution-related behavior can still mislead users and orchestration systems about the sensitivity of the skill's access and operational scope.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill description does not clearly disclose order-monitoring functionality tied to brokerage order execution. While monitoring is less severe than placing orders, hidden execution-related behavior can still mislead users and orchestration systems about the sensitivity of the skill's access and operational scope.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

Within a skill presented as portfolio reporting/connectivity, the documented workflow includes direct buy/sell order placement. In financial contexts this materially increases risk because the capability can cause immediate asset movement and losses if invoked under assumptions appropriate only for reporting tasks.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The order-placement instructions default to market orders and do not prominently warn that these are real trades with immediate financial consequences. In a brokerage context, lack of an explicit risk warning and confirmation step can lead to accidental executions, slippage, and unintended losses.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This script places live buy/sell orders via client.trading.place_force_order, which materially exceeds the skill’s declared scope of brokerage connectivity, account registration, and portfolio reporting. A skill presented as read-oriented portfolio tooling but containing trade execution logic creates a dangerous capability mismatch that could enable unauthorized or unexpected transactions if invoked by an agent or user who reasonably assumes the skill is non-trading.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill documents shell execution, file reads/writes, and secret handling but does not declare any explicit tool scope or permissions boundary. In an agent setting, this weakens least-privilege controls and makes it easier for the skill to access sensitive files or execute commands beyond what is necessary for portfolio reporting.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The overview frames the skill as generating a daily total-value report, yet nearby instructions introduce real trade execution. This can cause dangerous trust confusion, especially for agents selecting skills by overview text, leading to use of a transaction-capable skill where a read-only reporting skill was expected.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill recommends automated daily WhatsApp reporting of portfolio value without warning that financial account data will be transmitted through a third-party messaging channel. This creates privacy and confidentiality risk, especially if messages are sent to the wrong recipient, stored insecurely, or exposed on a device.

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 132)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.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · references/api-reference.md (reported line 8)May include surrounding context.

md
This page is the landing reference for API endpoints. Use it to navigate to specific endpoint docs.

## Example: API Status
- GET https://api.snaptrade.com/api/v1/
- Checks API operational status + timestamp

If you need detailed endpoint schemas, use the official reference for the specific endpoint path.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The code writes configuration data to disk and sets restrictive permissions, which strongly suggests the file may contain sensitive credentials such as the consumer key referenced elsewhere in the file. There is no confirmation prompt, user-facing log/print, or explanatory comment/docstring warning that secrets will be persisted to a local file.

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
94% confidence
Finding

The code stores the SnapTrade user secret directly into persistent configuration via cfg["user_secret"] followed by save_config(cfg). If that config is stored in plaintext or in a broadly accessible location, compromise of the file would expose a credential that can be reused to authenticate SnapTrade user operations, increasing the blast radius of local file disclosure or accidental config sharing.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The function reads client_id and consumer_key from configuration and uses them to initialize an API client, which is credential handling. The file contains no docstring, comment, or user-facing notice explaining that credentials are being loaded and used for API access.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.