Back to skill

Security audit

tradr

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly matches its trading purpose, but it combines real-money automated trading with unsafe default persistence, weak input boundaries, and overbroad credential/config exposure.

Review this before installing on a funded wallet. Prefer a user service or dedicated unprivileged account, avoid sudo/system-wide setup, validate and authenticate all signal sources, keep the dashboard local and authenticated, do not expose full config.json, disable or fix Telegram broadcasts, and test with tiny limits or dry-run behavior before allowing automated Bankr trades.

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

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/setup.sh:64
Finding

Root-Persistent Service Executes User-Controlled Skill Code

Content
View full analysis
"$UNIT_DIR/$SERVICE_NAME.service" systemctl --user daemon-reload systemctl --user enable "$SERVICE_NAME" else UNIT_DIR="/etc/systemd/system" UNIT_FILE="$UNIT_DIR/$SERVICE_NAME.service" if [ -w "$UNIT_DIR" ] || [ "$(id -u)" -eq 0 ]; then echo "$UNIT" > "$UNIT_FILE" systemctl daemon-reload systemctl enable "$SERVICE_NAME" ``` ### Technical Analysis The system-wide unit does not specify `User=` or `Group=`, so systemd runs it as root. Its `ExecStart` points directly to `exit-manager.py` inside the original Skill directory, which is commonly located beneath the invoking user's home directory and may remain writable by that user. The installer therefore crosses two unnecessary privilege boundaries: 1. It establishes cross-session persistence by enabling a system service. 2. It causes code from a potentially user-writable directory to execute as root. The daemon only requires outbound network access and access to user-owned trading state. Root privileges are not necessary for its declared position-monitoring function. Although persistence is disclosed in the documentation, the unsafe privilege model creates a local privilege-escalation path. ### Attack Path 1. A victim runs `sudo ./scripts/setup.sh`. 2. The installer creates and enables `/etc/systemd/system/tradr-exit-manager.s ...[truncated 778 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/exit-manager.py:596
Finding

Predictable Root Lock File in /tmp Permits Symlink-Based File Truncation

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/tradr-enter.py:274
Finding

Unvalidated Trading Inputs Are Forwarded While Bankr Transaction Safeguards Are Bypassed

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
dashboard/index.html:249
Finding

Stored Cross-Site Scripting in Dashboard Rendering

Content
View full analysis
!p.closed); const closed = allPos.filter(([_,p]) => p.closed); const config = _data.config; root.innerHTML = renderExitManagerBar() + renderPositions(open) + renderStats(closed, open) + renderClosedPositions(closed) + renderTradeHistory() + renderConfig(config) + '
Last updated: '+fmtDateTime(new Date().toISOString())+' EST
'; } ``` ```javascript return `
$${p.token || '?'} ${chainBadge(p.chain)} ${modeBadge(p.mode)}
${fmtMult(mult)}
...
Held: ${fmtAgo(p.buy_ts)} ... ${p.score != null ? 'Score: '+p.score+'' : ''}
`; ``` ```javascript ${p.note ? '
'+p.note+'
' : ''} ``` ```javascript return ` ${fmtDateTime(t.ts||t.timestamp)} $${t.token||'?'} ${act.toUpperCase()} $${parseFloat(t.amount||t.amount_usd||0).toFixed(2)} ${t.score||'—'} ${mode ? modeBadge(mode) : '—'} ${t.status||'—'} ${txLink(t.tx, chain)} `; ``` ### Technical Analysis The dashboard builds HTML strings from position, trade, and configuration records and assigns the result to `innerH ...[truncated 1471 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/notify-telegram.sh:14
Finding

Telegram Hook Sources a Generic Secrets File and Unexpectedly Broadcasts Buy Activity

Content
View full analysis
/dev/null 2>&1 || true } send_broadcast() { [ -z "$BOT2_TOKEN" ] || [ -z "$CHANNEL_ID" ] && return curl -sf -X POST "https://api.telegram.org/bot${BOT2_TOKEN}/sendMessage" \ --data-urlencode "chat_id=${CHANNEL_ID}" \ --data-urlencode "text=$1" \ --data-urlencode "parse_mode=Markdown" >/dev/null 2>&1 || true } case "$TYPE" in buy) send_dm "$TEXT" send_broadcast "$TEXT" ;; sell) send_dm "$TEXT" send_broadcast "$TEXT" ;; ``` ### Technical Analysis The hook loads secrets by shell-sourcing `.env.secrets`. Sourcing is code execution, not passive configuration parsing: command substitutions, shell functions, redirections, and arbitrary commands in the file execute with the hook's privileges. The filename is generic and may contain unrelated credentials beyond the Telegram values required by this script. If the hook is invoked by the unsafe system-wide service, this code can execute in a root context. The Telegram bot token is also embedded in the command-line URL passed to `curl`, potentially exposing it to local process inspection. The script's header states that buy notificatio ...[truncated 1472 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
dashboard/index.html:231
Finding

Dashboard API Design Exposes the Complete Trading Configuration

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
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (38)

Tainted flow: 'req' from os.environ.get (line 188, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/exit-manager.py (reported line 102)May include surrounding context.

python
for attempt in range(retries + 1):
        try:
            req = Request(url, headers=headers)
            with urlopen(req, timeout=10) as resp:
                return json.loads(resp.read())
        except HTTPError as e:
            if e.code == 429 and attempt < retries:

Tainted flow: 'req' from os.environ.get (line 188, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/exit-manager.py (reported line 153)May include surrounding context.

python
for attempt in range(retries + 1):
        try:
            req = Request(url, headers=headers)
            with urlopen(req, timeout=10) as resp:
                return json.loads(resp.read())
        except HTTPError as e:
            if e.code == 429 and attempt < retries:

Tainted flow: 'req' from os.environ.get (line 188, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · scripts/exit-manager.py (reported line 190)May include surrounding context.

python
for attempt in range(retries + 1):
        try:
            req = Request(url, headers=headers)
            with urlopen(req, timeout=10) as resp:
                return json.loads(resp.read())
        except HTTPError as e:
            if e.code == 429 and attempt < retries:

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents this skill as the core onchain trade execution engine that accepts a CA and score and handles the entire lifecycle of a trade. The provided code chunk is instead an example adapter whose primary function is to poll a signal source and invoke another script, tradr-enter.py, with those parameters. Any actual trading behavior is external to this code. The code contains only signal collection, subprocess invocation, and simple stdout handling. It does not itself perform sizing logic, exit logic, on-chain verification, or trade logging in a substantive way, and it shows no Bankr integration. This is a material description-versus-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description overstates and mischaracterizes this code chunk. The implementation is specifically an exit-management service, not a full trade lifecycle engine. It contains no buy/entry execution, no scoring input handling, and no position sizing based on a supplied CA + score. Instead, it continuously polls market data for already-open positions stored in positions.json, triggers partial/full sells via Bankr, verifies wallet balances, reconciles state, and logs/announces results. On-chain verification and trade logging do align with the description, and use of Bankr also aligns, but the primary purpose and capabilities materially differ from the declared behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description is for a trading engine handling on-chain execution, exits, verification, and logging. The supplied code does none of that. Instead, it is a Telegram notification hook that reads bot tokens/chat IDs from secret environment files and posts messages to Telegram via curl. This is a materially different primary purpose and adds undeclared external communication capabilities unrelated to on-chain trade execution itself.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The supplied code is clearly a test file (scripts/test-tradr.py) containing assertions for trading-related logic and state-machine scenarios. While it covers concepts mentioned in the description—such as sized entry rules, mode-based exits, chain detection, and transaction-hash formatting—it only validates expected behavior in isolation. There is no real trade execution, no external API/skill invocation, no blockchain access, no verification of submitted transactions, and no logging of actual trades. The primary purpose of the code chunk is unit testing, which is materially different from the declared purpose of an onchain trade execution engine.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

The description overstates the implemented behavior. This script is explicitly an entry engine ('tradr-enter.py') and even states 'No signal generation -- purely execution.' It does size resolution, mode selection, market data lookup, buy execution through Bankr, position persistence, trade logging, locking, cooldown checks, protected-token checks, and notifications. However, there is no code for selling, exit management, lifecycle progression, or actual on-chain verification of the executed trade. The Bankr dependency is consistent with the description, and trade logging is accurate, but the primary scope is narrower than declared.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
The `dashboard/index.html` file provides a real-time dashboard. It expects four API endpoints:

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
The `dashboard/index.html` file provides a real-time dashboard. It expects four API endpoints:

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
89% confidence
Finding

Copying the full process environment into a child process can expose unrelated secrets, API keys, wallet material, or infrastructure credentials to the external Bankr script and anything it invokes. In this skill's context, that is riskier because the child process performs sensitive trading actions and may be separately configurable or compromise-prone.

Content

Scanner excerpt · scripts/exit-manager.py (reported line 218)May include surrounding context.

python
def bankr_sell(prompt):
    log.info("Executing bankr: %s", prompt)
    try:
        env = os.environ.copy()
        env["BANKR_ALLOW_TRADE"] = "1"  # Bypass trade guard for mechanical pipeline
        env["BANKR_ALLOW_SELL"] = "1"   # Legacy sell override
        result = subprocess.run(

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The code intentionally overrides trade protections and enables fully automated sell execution with no user confirmation or separate runtime authorization. In an on-chain trading engine, mistakes, poisoned inputs, logic bugs, or config tampering can directly cause irreversible asset liquidation, making this especially dangerous in context.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
91% confidence
Finding

Copying the full parent environment into a child process can expose secrets such as API keys, wallet settings, credentials, or infrastructure tokens to the invoked bankr_script. In this skill’s context, the child process is a separate executable involved in financial operations, so inherited secrets materially expand the blast radius if that script is compromised or replaced.

Content

Scanner excerpt · scripts/tradr-enter.py (reported line 272)May include surrounding context.

python
def bankr_buy(bankr_script, prompt):
    log.info("Executing bankr: %s", prompt)
    try:
        env = os.environ.copy()
        env["BANKR_ALLOW_TRADE"] = "1"  # Bypass trade guard for mechanical pipeline
        result = subprocess.run(
            [bankr_script, prompt],

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises and instructs use of capabilities with material security impact—shell execution, network access, environment/config handling, and file writes—but does not declare any tool scope or permissions boundaries. In an agent ecosystem, that omission increases the chance the skill is granted broader-than-necessary access and makes dangerous behavior less visible to operators reviewing it.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill describes automated real-fund trading behavior without a prominent warning about irreversible financial loss, market manipulation risk, bad signals, slippage, and dependency compromise. In this context, users may execute real buys and sells on funded wallets, so under-warning materially increases the chance of harmful deployment and accidental loss.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The startup instructions tell the user to launch a persistent daemon with sudo but do not clearly warn that this enables continuous automated monitoring and autonomous sell execution. In a live trading skill, that omission is dangerous because users may not realize that once started, the service can act without further confirmation and continue operating after they leave the terminal.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
92% confidence
Finding

The documentation instructs users to run the exit manager with sudo via systemctl, which normalizes privileged execution for a networked, file-writing automation component. If the installed service or referenced scripts are compromised or misconfigured, running them under elevated privileges can expand the blast radius from trade errors into broader host compromise.

Content

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

md
vi config.json    # Add wallet addresses, tune scoring/modes

# 3. Start the exit manager daemon
sudo systemctl start tradr-exit-manager

# 4. Feed a trade
python3 scripts/tradr-enter.py <CA> --score <N> [--chain base] [--mode snipe]

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
92% confidence
Finding

Starting the service with sudo again promotes privileged operation without explaining least-privilege boundaries. In a skill that interfaces with external data sources, scripts, and wallet-related workflows, unnecessary root usage increases the impact of any later script injection, config tampering, or service misbehavior.

Content

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

  1. Start the exit manager:
    bash
    sudo systemctl start tradr-exit-manager
    sudo systemctl status tradr-exit-manager  # verify it's running
    

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

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

  1. Start the exit manager:

    bash
    sudo systemctl start tradr-exit-manager
    sudo systemctl status tradr-exit-manager  # verify it's running
    
  2. Connect a signal source:

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · adapters/example-adapter.py (reported line 94)May include surrounding context.

python
print(f"[ADAPTER] Feeding signal: {token or ca[:12]} | score={score} | chain={chain or 'auto'}")

    try:
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=360)
        if result.returncode == 0:
            data = json.loads(result.stdout)
            if data.get("success"):

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The file sets TZ = 'America/New_York' and formats times using 'en-US', which forces a specific locale and timezone for all users. This is a natural-language locale policy concern because the UI does not provide opt-in, configuration, or justification that the dashboard is intentionally region-specific.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The dashboard renders detailed internal trading configuration including exit modes, stop levels, take-profit thresholds, position sizing by score, concurrency limits, daily limits, and market-cap ceilings. In the context of an on-chain trade execution engine, exposing strategy and operational parameters materially increases the risk of front-running, reverse-engineering trading behavior, and targeted manipulation of the bot's positions or liquidity conditions.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/exit-manager.py (reported line 209)May include surrounding context.

python
script = os.path.expanduser(NOTIFY_SCRIPT)
        if os.path.exists(script):
            try:
                subprocess.run([script, level, notify_type, text], capture_output=True, timeout=15)
            except Exception as e:
                log.warning("Notification script failed: %s", e)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
95% confidence
Finding

This code launches an external trading script with a dynamically constructed prompt and explicitly sets BANKR_ALLOW_TRADE/BANKR_ALLOW_SELL to bypass safety guards. In the context of an autonomous on-chain trading daemon, that means any compromised position/config input or flawed exit logic can trigger irreversible sell transactions without an interactive check, greatly increasing blast radius.

Content

Scanner excerpt · scripts/exit-manager.py (reported line 221)May include surrounding context.

python
env = os.environ.copy()
        env["BANKR_ALLOW_TRADE"] = "1"  # Bypass trade guard for mechanical pipeline
        env["BANKR_ALLOW_SELL"] = "1"   # Legacy sell override
        result = subprocess.run(
            [BANKR_SH, prompt],
            capture_output=True, text=True, timeout=330,
            env=env,

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The comment states that buy notifications are sent to DM only, but the code actually sends buy events to both DM and broadcast. In a trading skill, buy alerts can reveal strategy activity, positions, or timing to a wider audience than intended, creating confidentiality and operational-risk issues if operators rely on the documented routing behavior.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.