T09 · Insecure Skill Coding Practices
Error
- Location
- kalshi_divergence.py:149
- Finding
- Insufficient Market Identity Validation Can Trigger Trades on Unrelated Markets<![CDATA[ ## Vulnerability Details **File Location**: `kalshi_divergence.py:149-183`, with the trade sink at `kalshi_divergence.py:220-272` **Vulnerability Type**: Weak market matching and validation **Risk Level**: High ### Complete Code Snippet ```python def find_polymarket_match(client: SimmerClient, kalshi_market: dict, keywords: list) -> dict | None: """Find best matching Polymarket market for a Kalshi market.""" kalshi_desc = extract_kalshi_description(kalshi_market).lower() # Try each keyword to search Polymarket for kw in keywords: try: markets = client.find_markets(query=kw) except Exception: markets = [] if not markets: continue # Score matches best_match = None best_score = 0 for pm in markets: q = (pm.question or "").lower() score = 0 # Check for overlapping terms kalshi_tokens = set(kalshi_desc.split()) pm_tokens = set(q.split()) overlap = len(kalshi_tokens & pm_tokens) score += overlap * 2 # Bonus for price-level matches (e.g., "$100,000", "above 5000") import re kalshi_nums = set(re.findall(r'\d+[,.]?\d*', kalshi_desc)) pm_nums = set(re.findall(r'\d+[,.]?\d*', q)) if kalshi_nums & pm_nums: score += 10 # Bonus for keyword in question if kw.lower() in q: score += 5 if score > best_score: best_score = score best_match = pm if best_match and best_score >= 5: return best_match return None ``` The selected market is subsequently used as the target of a live trade: ```python if live: try: result = client.trade( market_id=sig["market_id"], side=sig["side"], amount=TRADE_SIZE_USD, source=TRADE_SOURCE, ...[truncated 2663 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace heuristic keyword matching with an explicit, reviewed mapping between equivalent Kalshi and Polymarket contracts where possible. 2. Before accepting a match, normalize and compare: - Asset or event identity - Threshold value and currency or unit - Comparison direction - Start and resolution timestamps - Outcome definitions - Resolution source 3. Require multiple independent match conditions. A keyword alone must never satisfy the acceptance threshold. 4. Reject matches when multiple candidates have similar scores or required contract metadata is absent. 5. Introduce a minimum confidence threshold based on structured fields rather than token overlap. 6. Persist approved market pairs and require manual confirmation before the first live trade on any new pair. 7. Add unit tests covering similarly worded but non-equivalent markets, reversed outcomes, different dates, and different numeric units. 8. Apply per-market and aggregate exposure limits to reduce losses if matching validation fails. ]]>
