Back to skill

Security audit

Trading DevBox

Security checks for vulnerabilities and agentic risk

Overview

This trading backtest skill is mostly purpose-aligned, but it runs generated Python through an insecure shared temporary path and calls itself a sandbox without providing real containment.

Review before installing. The skill is not trying to trade or steal data, but it executes generated Python on your machine and uses an unsafe fixed temporary path. It should be changed to use a private mktemp directory and clearer sandboxing before relying on it for repeated use.

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
SKILL.md:30
Finding

Predictable Shared Temporary Path Enables Symlink and File-Replacement Attacks

Content
View full analysis
/tmp/trading-devbox/strategy.py << 'PYEOF' import backtrader as bt import sys import json class UserStrategy(bt.Strategy): params = dict( entry_drop_pct=10, take_profit_pct=30, stop_loss_pct=5, ) def __init__(self): self.order = None self.buy_price = None def next(self): if self.order: return if not self.position: # entry: price dropped by entry_drop_pct from recent high high = max(self.data.close.get(size=20) or [self.data.close[0]]) drop = (high - self.data.close[0]) / high * 100 if drop >= self.p.entry_drop_pct: self.order = self.buy() self.buy_price = self.data.close[0] else: pnl = (self.data.close[0] - self.buy_price) / self.buy_price * 100 if pnl >= self.p.take_profit_pct or pnl <= -self.p.stop_loss_pct: self.order = self.sell() if __name__ == '__main__': print(json.dumps({"status": "ok", "message": "Strategy generated"})) PYEOF python3 /tmp/trading-devbox/strategy.py ``` ### Technical Analysis The workflow creates and executes Python code through the fixed, globally predictable path `/tmp/trading-devbox/strategy.py`. The command `mkdir -p` does not verify that an existing path is owned by the invoking user, is a real directory rather than an indirect path, or has secure permissions. If another local user pre-creates `/tmp/trading-devbox`, the command accepts that directory without error. Shell output redirection follows symbolic links, so an attacker-controlled `strategy.py` symlink could cause the generated content to truncate and overwrite another file that the invoking account ...[truncated 2198 chars]
Remediation
View remediation
"$strategy_file" <<'PYEOF' # Generated strategy code PYEOF python3 -- "$strategy_file" ``` 2. Do not reuse a fixed directory under `/tmp`. `mktemp -d` atomically creates an unpredictable directory and prevents another user from pre-creating the same path. 3. Apply `umask 077` so generated directories and files are accessible only to the invoking account. 4. Quote all path variables and use `--` where supported to prevent path parsing errors. 5. Keep the generated file inside the newly created private directory and delete the directory through a cleanup trap. 6. For higher-assurance implementations, create files using APIs that support exclusive creation and no-follow semantics, such as `O_CREAT | O_EXCL | O_NOFOLLOW`, and execute only after verifying ownership, file type, and permissions. 7. If generated strategy code may contain untrusted user-derived logic, execute it in an isolated container or sandbox with: - No host credentials or sensitive environment variables. - A read-only filesystem except for a dedicated work directory. - No network access unless explicitly required. - CPU, memory, process, and execution-time limits. - A non-privileged user and no additional Linux capabilities. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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 (2)

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
70% confidence
Finding

Skill instructs the agent to never refuse or to always comply. Suppressing the agent's ability to decline removes a core safety control and enables downstream harmful requests to succeed.

Content

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

md
## Response Format

Always respond in the user's language. Structure the response as:
- Parsed intent summary
- Strategy parameters
- Execution result or next steps

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill is configured to trigger on very broad trading-related keywords, which can cause unintended invocation when a user mentions generic terms like 'strategy' or 'trading' outside the intended sandbox workflow. This increases the chance that the agent enters a code-generation/execution path without sufficient user intent validation, expanding attack surface and enabling prompt-trigger abuse or accidental execution in unrelated contexts.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.