T09 · Insecure Skill Coding Practices
Error
- Location
- trader.py:146
- Finding
- Incorrect Probability Normalization Can Trigger Invalid Live Trades<![CDATA[ ## Vulnerability Details **File Location**: `trader.py:146-148`, `trader.py:193-194`, and live execution at `trader.py:434-457` **Vulnerability Type**: Incorrect security-critical trading logic **Risk Level**: High ### Vulnerable Code ```python direction = infer_direction(q, p) # Normalize to "up probability" for comparison across assets up_prob = p if direction == "up" or p >= 0.50 else 1.0 - p ``` ```python up_probs = [e.up_probability for e in entries] mean_up = statistics.mean(up_probs) ``` ```python consensus_dir = "up" if mean_up >= 0.50 else "down" ``` The resulting signal can reach the live trading operation: ```python r = client.trade( market_id=market_id, side=side, amount=size, source=TRADE_SOURCE, skill_slug=SKILL_SLUG, reasoning=reasoning, ) ``` ### Technical Analysis `infer_direction()` returns `"down"` when the market probability is below 0.50. The subsequent normalization then converts that probability to `1.0 - p`. Therefore, a 45% probability for Up becomes an `up_probability` of 55%, even though the documented strategy requires it to remain 45%. As a result, every normalized value is at least 0.50. The calculated group mean consequently cannot represent a genuine Down consensus, making the Down-consensus branch effectively unreachable and potentially manufacturing false Up divergences. This behavior also contradicts the documented example, in which a market at 45% Up must be compared directly with other assets at 54%–58% Up. ### Attack Path 1. The skill discovers an eligible market whose YES probability is below 50%. 2. `infer_direction()` labels the market as Down. 3. The normalization logic changes its Up probability from `p` to `1-p`. 4. The inflated value contributes to an artificial Up consensus. 5. `find_divergences()` generates a potentially incorrect trade opportunity. 6. If the probability and context gates pass, an operator running the skill with `--live` causes `client.trade()` to submit ...[truncated 687 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Determine which market outcome token represents “Up” using structured outcome metadata rather than deriving outcome identity from the current probability. - Preserve the actual probability of the Up outcome. If YES represents Up, use `up_prob = p`; if NO represents Up, use `up_prob = 1.0 - p`. - Reject markets when outcome ordering cannot be verified reliably. - Add unit tests covering: - Mixed values such as 58%, 56%, 54%, and 45%. - Groups in which every asset favors Down. - Markets with reversed outcome ordering. - Values exactly at 50%. - Both YES and NO trade generation. - Add a live-mode preflight check that logs the verified outcome mapping and calculated consensus before an order is submitted. ]]>
