T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/copy_trader.py:42
- Finding
- Unnecessary transmission of a deterministic private-key-derived identifier<![CDATA[ ## Vulnerability Details **File Location**: `scripts/copy_trader.py:42-53`, `scripts/copy_trader.py:96-106`, and `scripts/copy_trader.py:117-125` **Vulnerability Type**: Improper handling and external disclosure of secret-derived data **Risk Level**: Medium ### Vulnerable Code ```python self.private_key = os.environ.get("POLYMARKET_KEY", "") self.our_wallet = self._derive_wallet() if self.private_key else None ``` ```python def _derive_wallet(self): """Derive wallet address from private key (simplified)""" try: # In production, use proper eth library # This is a placeholder - real implementation needs web3 return "0x" + hashlib.sha256(self.private_key.encode()).hexdigest()[:40] except: return None ``` The resulting identifier is included in requests to external services: ```python req = urllib.request.Request( "https://polygon-rpc.com", data=json.dumps(payload).encode(), headers={"Content-Type": "application/json"} ) with urllib.request.urlopen(req, timeout=10) as resp: result = json.loads(resp.read().decode()) ``` ```python def get_our_positions(self): """Get our current positions""" if not self.our_wallet: return {} url = f"https://data-api.polymarket.com/positions?user={self.our_wallet}" positions = self._fetch_json(url) or [] return {p.get("asset_id"): p for p in positions} ``` ### Technical Analysis The Skill reads `POLYMARKET_KEY`, hashes the private key with SHA-256, truncates the result to 40 hexadecimal characters, and treats that value as an Ethereum wallet address. This is not a valid Ethereum address-derivation procedure. The resulting deterministic, secret-derived identifier is subsequently transmitted to: - `https://polygon-rpc.com` as part of an `eth_call` request for a USDC balance. - `https://data-api.polymarket.com` as the `user` parameter of a positions request. The raw private key is not directly transmitted, and recovering a properly ...[truncated 2253 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove all access to `POLYMARKET_KEY` until transaction signing is actually implemented. 2. Accept a separate public wallet address, such as `POLYMARKET_WALLET`, for balance and position queries. 3. Validate supplied public addresses for proper Ethereum syntax and checksum before including them in network requests. 4. If signing is later implemented, derive the public address with an audited Ethereum library rather than manually hashing the private key. 5. Keep all signing operations local and never include private keys or unnecessary secret-derived values in API requests, URLs, logs, errors, or persistent state. 6. Separate read-only monitoring from transaction execution so the default monitoring mode never requires wallet credentials. 7. Document every external endpoint and the exact public data transmitted to it. 8. Add tests confirming that read-only and dry-run modes do not access `POLYMARKET_KEY`. 9. Update `SKILL.md` to state accurately that live trading and automatic redemption are not currently implemented. ]]>
