T09 · Insecure Skill Coding Practices
Error
- Location
- skill.py:145
- Finding
- Untrusted AI Output Controls Unattended Value-Bearing Blockchain Transactions<![CDATA[ ## Vulnerability Details **File Location**: `skill.py:145-173`, `skill.py:211-235`, `skill.py:289-299`; `skill.md:159-165` **Vulnerability Type**: Unvalidated AI output used in an automatically signed blockchain transaction **Risk Level**: High ### Complete Code Snippets The skill incorporates untrusted social-media content directly into the model prompt and accepts the model response after JSON syntax parsing: ```python def analyze_with_claude(tweets, recent_predictions): recent_qs = [p['question'] for p in recent_predictions] recent_str = json.dumps(recent_qs) if recent_predictions else "None" prompt = f"""From these X posts: {json.dumps(tweets, default=str)} Avoid these recent questions: {recent_str} Pick a NEW debatable hot topic and create a yes/no prediction market proposal in valid JSON: {{ "question": "Will [event] happen by [date]?", "duration_days": 1-14, "resolution_criteria": "How to resolve (sources)", "score": 8.0-10.0, "reasoning": "Why hot", "sources": ["link1", "link2"], "category": "One of: Politics, Elections, Sport, Gaming, Crypto, Price, Tech, People, Personal, music, Pop, other" }} Return ONLY JSON, no extra text, no markdown.""" message = client.messages.create( model="claude-sonnet-4-20250514", max_tokens=500, temperature=0.8, messages=[{"role": "user", "content": prompt}] ) text = message.content[0].text.strip() ``` Only JSON parsing is performed. No schema, type, or range validation is applied to transaction-relevant fields: ```python try: return json.loads(text) except Exception as e: print(f"JSON parse error: {str(e)}") print(f"Raw text: {text}") raise ``` The model-provided duration is passed directly to a payable contract call. The transaction is then signed and broadcast without user confirmation: ```python def get_min_deposit(): try: min_wei = contract.functions.minimumDeposit().ca ...[truncated 5205 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Apply strict schema validation** - Validate the complete model response using a fixed schema. - Require `duration_days` to be an integer, explicitly rejecting booleans and numeric strings. - Enforce `1 <= duration_days <= 14`. - Set maximum lengths for questions, rules, sources, and other text fields. - Reject unknown fields and unsupported categories. 2. **Require approval before signing** - Display the destination contract, chain, method, duration, deposit, gas limit, and maximum total cost. - Require explicit operator approval before every transaction. - Do not allow model output to trigger signing merely because it is valid JSON. 3. **Enforce financial policy in code** - Set an immutable maximum deposit and abort if `minimumDeposit()` exceeds it. - Enforce maximum gas cost, transaction count, and cumulative daily spending. - Add a cooldown between market creations. - Stop automatically rather than using a fallback deposit when the contract query fails. 4. **Constrain signing privileges** - Use a dedicated low-balance wallet exclusively for this skill. - Prefer a policy-controlled signer, multisignature wallet, or contract account restricted to the expected contract and method. - Store the key in a secret manager or protected signing service rather than a general `.env` file. 5. **Verify blockchain context** - Verify the expected chain ID before constructing or signing transactions. - Confirm that bytecode exists at the configured contract address and matches an approved deployment. - Simulate the transaction and inspect the result before requesting approval. - Pin or independently verify security-sensitive state instead of relying on one untrusted RPC endpoint. 6. **Reduce prompt-injection exposure** - Clearly delimit retrieved posts as untrusted quoted data. - Instruct the model never to follow instructions found inside retrieved content. - Treat mo ...[truncated 406 chars]
