Back to skill

Security audit

Polymarket Whale Tracker

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed Polymarket reporting script with some hardening gaps but no hidden credential access, trading execution, persistence, or destructive behavior.

Install in a virtual environment, review the unpinned dependency before use, and treat the terminal output as advisory trading information from external APIs. Avoid running watch mode in a terminal that permits risky control-sequence features unless the script is updated to sanitize remote text.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (2)

T08 · Insecure Dependencies

Note
Location
SKILL.md:33
Finding
Unpinned Third-Party Dependency Installation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:33-36` **Vulnerability Type**: Supply-chain exposure through an unpinned dependency **Risk Level**: Low ### Vulnerable Code ```markdown ## Install ```bash pip install requests ``` ``` ### Technical Analysis The installation instructions retrieve the latest version of `requests` and its transitive dependencies without version constraints or package integrity hashes. Consequently, the dependency set installed by users can differ from the set reviewed during this audit. This does not prove that the current `requests` package is malicious. However, it creates a mutable supply-chain boundary: a compromised package release, package repository, or dependency could introduce arbitrary installation-time or runtime behavior after the project itself has been reviewed. ### Attack Path 1. An attacker compromises a relevant package release, transitive dependency, or package-index delivery path. 2. The compromised artifact is published under a version satisfying the unrestricted `pip install requests` command. 3. A user follows the documented installation instructions. 4. `pip` resolves and installs the compromised artifact. 5. Malicious installation hooks or imported runtime code execute with the privileges of the user running the installation or tracker. ### Impact Assessment Successful exploitation could execute arbitrary code under the installing user's account. The resulting scope would depend on that account's privileges and could include access to user-readable files, environment variables, network resources, and credentials available to the Python process. No direct privilege escalation beyond the invoking user's permissions is established by the audited project. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create a reviewed dependency lock file that pins `requests` and all transitive dependencies to exact versions. 2. Record cryptographic hashes for every approved distribution. 3. Install dependencies with hash verification, for example: ```bash python3 -m pip install --require-hashes -r requirements.txt ``` 4. Generate and retain a dependency inventory or software bill of materials. 5. Use automated vulnerability monitoring and controlled dependency-update reviews. 6. Install dependencies in an isolated virtual environment under a non-privileged account. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
whale_tracker.py:103
Finding
Terminal Control-Sequence Injection Through Unsanitized API Data<![CDATA[ ## Vulnerability Details **File Location**: `whale_tracker.py:103-113`, `whale_tracker.py:137-144`, and `whale_tracker.py:155-165` **Vulnerability Type**: Improper neutralization of terminal control sequences **Risk Level**: Medium ### Vulnerable Code Position and market values received from remote APIs are printed directly: ```python def display_positions(name, address, positions): if not positions: print(f" No open positions found.") return print(f"\n {'Outcome':<8} {'Size':>10} {'Avg Price':>10} {'Curr Price':>10} {'PnL':>10} Market") print(f" {'-------':<8} {'----':>10} {'---------':>10} {'----------':>10} {'---':>10} ------") for p in sorted(positions, key=lambda x: abs(float(x.get("size", 0) or 0)), reverse=True)[:15]: try: outcome = p.get("outcome", "?")[:6] size = float(p.get("size") or p.get("currentValue") or 0) avg_price = float(p.get("avgPrice") or p.get("averagePrice") or 0) curr_price = float(p.get("curPrice") or p.get("currentPrice") or p.get("price") or 0) pnl = (curr_price - avg_price) * size if avg_price and curr_price else 0 market = p.get("title") or p.get("market") or p.get("conditionId", "")[:50] if not market or len(market) < 10: market = get_market_info(str(p.get("conditionId", ""))) print(f" {outcome:<8} {size:>10.2f} {avg_price:>10.3f} {curr_price:>10.3f} {pnl:>+10.2f} {str(market)[:55]}") ``` Recent-trade data is also printed without sanitization: ```python if trades: print(f"\n Recent trades:") for t in trades[:5]: side = t.get("side", "?") size = float(t.get("size") or 0) price = float(t.get("price") or 0) market = t.get("title") or t.get("market", "")[:50] ts = t.get("timestamp") or t.get("createdAt", "")[:16] ...[truncated 2993 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pass every remotely sourced string through a centralized terminal-safe rendering function before printing. 2. Remove ANSI CSI sequences, OSC sequences, C0/C1 control characters, carriage returns, newlines, and other non-printing characters. 3. Apply length limits only after sanitization. 4. Consider replacing unsafe characters with escaped representations so that suspicious data remains visible to users. 5. Use a terminal-rendering library with explicit escaping support where practical. 6. Apply the protection consistently to leaderboard names, addresses, market titles, outcomes, trade sides, timestamps, condition IDs, and exception messages. A basic defensive helper could begin with: ```python import re import unicodedata ANSI_ESCAPE = re.compile( r"(?:\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])" r"|\x9B[0-?]*[ -/]*[@-~])" ) OSC_ESCAPE = re.compile(r"\x1B\].*?(?:\x07|\x1B\\)", re.DOTALL) def terminal_safe(value, max_length=100): text = str(value) text = OSC_ESCAPE.sub("", text) text = ANSI_ESCAPE.sub("", text) text = "".join( ch for ch in text if ch in "\t" or not unicodedata.category(ch).startswith("C") ) return text[:max_length] ``` The implementation should then sanitize each API-derived value before interpolation into terminal output. The helper should be tested against CSI, OSC, embedded newlines, carriage returns, backspaces, and truncated escape-sequence payloads. ]]>
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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 (1)

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill advertises and relies on network access ('fetches the top 20 traders', installs and uses requests) but does not declare any explicit tool scope or permissions in the manifest. This creates an authorization and transparency gap: an agent or reviewer cannot easily determine or constrain what external access the skill needs, increasing the risk of unintended outbound requests, data exfiltration, or use in environments that assume least privilege.

Static analysis

No suspicious patterns detected.