T09 · Insecure Skill Coding Practices
Warning
- Location
- dnd.py:33
- Finding
- Unbounded Dice Parameters Allow Resource Exhaustion## Vulnerability Details **File Location**: `dnd.py`, lines 33-45 **Vulnerability Type**: Uncontrolled resource consumption **Risk Level**: Medium **Vulnerable Code:** ```python # Parse XdY+Z or XdY-Z or XdY import re match = re.match(r'(\d+)d(\d+)([+-]\d+)?', dice_str.lower()) if not match: print(f"Invalid dice format: {dice_str}. Use format like '2d6', '1d20+5', '3d8-2'", file=sys.stderr) sys.exit(1) num_dice = int(match.group(1)) die_size = int(match.group(2)) modifier = int(match.group(3) or 0) rolls = [random.randint(1, die_size) for _ in range(num_dice)] ``` ### Technical Analysis The dice count is obtained directly from a user-controlled command-line argument without an upper bound. It is then passed to `range()` and used to determine the size of an eagerly allocated list. Consequently, an attacker can request an extremely large number of dice. The application will repeatedly invoke `random.randint()` and retain every generated value in memory. The resulting CPU and memory consumption can stall the process, trigger swapping, or cause termination by the operating system's out-of-memory mechanism. The dice size is also not bounded, and the expression is parsed with `re.match()` rather than requiring the entire input to conform to the expected format. These validation weaknesses should be addressed as part of the same hardening effort. ### Attack Path 1. An attacker supplies an excessively large dice expression through a prompt or direct command, such as: ```bash python3 dnd.py roll 999999999d6 ``` 2. The regular expression accepts the expression. 3. `num_dice` is set to the attacker-controlled value. 4. The list comprehension attempts to generate and retain hundreds of millions of random integers. 5. The process consumes excessive CPU and memory, potentially making the Agent or host unavailable. ### Impact Assessment Successful exploitation can cause denial of servic ...[truncated 266 chars]
- Remediation
- ## Remediation Suggestions - Parse the complete expression using `re.fullmatch()` instead of `re.match()`. - Enforce conservative maximum values for the number of dice, die size, and modifier before performing any computation. - Reject zero or negative-equivalent values and return a controlled validation error. - Avoid allocating large roll lists when only a total is needed, or impose a strict output-size limit. - Add automated tests for malformed, zero-sized, and oversized inputs. Example hardening: ```python match = re.fullmatch(r'(\d+)d(\d+)([+-]\d+)?', dice_str.lower()) if not match: raise ValueError("Invalid dice expression") num_dice = int(match.group(1)) die_size = int(match.group(2)) modifier = int(match.group(3) or 0) if not 1 <= num_dice <= 1000: raise ValueError("Dice count must be between 1 and 1000") if not 2 <= die_size <= 10000: raise ValueError("Die size must be between 2 and 10000") if abs(modifier) > 1_000_000: raise ValueError("Modifier is too large") ```
