T09 · Insecure Skill Coding Practices
Warning
- Location
- skill.md:65
- Finding
- Unbounded Proof-of-Work Loop Allows Resource Exhaustion## Vulnerability Details **File Location**: `skill.md`, lines 65–79 **Vulnerability Type**: Unbounded computation using remotely supplied challenge parameters **Risk Level**: Medium ### Vulnerable Code ```markdown Find a `nonce` where `SHA256(data + nonce)` starts with the `prefix` (currently `000000` — 6 hex zeros). ⚠️ **Do NOT impose an iteration cap.** This takes 30–90 seconds on average. Run the loop until you find a valid nonce. ```python import hashlib def solve_pow(data, prefix): nonce = 0 while True: attempt = f"{data}{nonce}" hash_result = hashlib.sha256(attempt.encode()).hexdigest() if hash_result.startswith(prefix): return nonce nonce += 1 ``` ``` ### Technical Analysis The challenge endpoint remotely supplies both `data` and `prefix`, but the documented solver neither validates these values nor limits execution time or iteration count. The explicit instruction not to impose a cap compounds the problem. Proof-of-work cost grows exponentially with prefix difficulty. An excessively long hexadecimal prefix can make completion impractical, while a malformed or impossible prefix—for example, characters that cannot occur in a hexadecimal SHA-256 digest or a prefix longer than the 64-character digest—causes the loop never to terminate. Because the loop performs continuous SHA-256 calculations, a malicious or compromised API response can turn normal registration into sustained CPU resource exhaustion. ### Attack Path 1. An attacker compromises the challenge service or otherwise causes it to return attacker-controlled challenge parameters. 2. The response contains a malformed, impossible, or excessively difficult `prefix`. 3. The agent follows the skill's instruction to run the solver without an iteration cap. 4. The termination condition is never reached or requires impractical computation. 5. The process continuously consumes CPU until an ...[truncated 500 chars]
- Remediation
- ## Remediation Suggestions - Validate that `prefix` contains only lowercase hexadecimal characters. - Reject prefixes longer than the SHA-256 hexadecimal digest length of 64 characters. - Enforce a conservative maximum proof-of-work difficulty based on an explicitly trusted local policy rather than accepting arbitrary server-provided difficulty. - Apply both a maximum iteration count and a wall-clock deadline. - Support cancellation and periodically yield control so autonomous agents remain responsive. - Reject malformed or unexpectedly difficult challenges and request a new challenge rather than continuing indefinitely. - Run proof-of-work in an isolated worker with CPU and memory limits. - Replace the instruction not to impose a cap with fail-closed guidance, for example: ```python import hashlib import re import time def solve_pow(data, prefix, max_iterations=20_000_000, timeout_seconds=120): if not isinstance(data, str): raise ValueError("Invalid challenge data") if not isinstance(prefix, str) or not re.fullmatch(r"[0-9a-f]{1,6}", prefix): raise ValueError("Invalid or unsupported proof-of-work prefix") deadline = time.monotonic() + timeout_seconds for nonce in range(max_iterations): if time.monotonic() >= deadline: raise TimeoutError("Proof-of-work deadline exceeded") digest = hashlib.sha256(f"{data}{nonce}".encode()).hexdigest() if digest.startswith(prefix): return nonce raise RuntimeError("Proof-of-work iteration limit exceeded") ```
