T09 · Insecure Skill Coding Practices
- Location
scripts/cli_qr_refiner.py:26- Finding
Unbounded Image Allocation Enables Local Resource Exhaustion
- Content
View full analysis
Vulnerability Details
File Location:
scripts/cli_qr_refiner.py, lines 26–38 and 70–74
Vulnerability Type: Uncontrolled resource consumption
Risk Level: MediumVulnerable Code
python with open(input_path, 'r', encoding='utf-8') as f: lines = [line.rstrip('\n') for line in f if line.strip()] if not lines: print(f"[QR-Renderer] Error: empty input file '{input_path}'") sys.exit(1) height = len(lines) width = max(len(line) for line in lines) # Each char cell: width = scale, height = scale * 2 # (half blocks ▀ ▄ are half-height, so we double the scale for proper rendering) cell_w = scale cell_h = scale * 2 img = Image.new('RGB', (width * cell_w, height * cell_h), color='white')python if __name__ == '__main__': if len(sys.argv) < 3: print("Usage: python3 cli_qr_refiner.py <input_txt> <output_png> [scale]") sys.exit(1) input_file = sys.argv[1] output_file = sys.argv[2] scale = int(sys.argv[3]) if len(sys.argv) > 3 else 10 render_qr(input_file, output_file, scale)Technical Analysis
The renderer does not impose limits on input-file size, row count, line width, scale, or total output dimensions. It first loads all nonblank input lines into memory and then allocates an RGB image whose dimensions are calculated from attacker-influenced values:
- Image width:
maximum_line_length × scale - Image height:
line_count × scale × 2 - Approximate raw RGB storage:
image_width × image_height × 3bytes, excluding Pillow and Python overhead
An unusually large input matrix, an excessive positive scale, or both can therefore trigger excessive memory and CPU consumption. A non-positive scale can also produce an unhandled Pillow exception rather than a controlled validation error.
Exploitation requires the attacker to influence the QR text processed by the Skill or the optional scale argument. No r ...[truncated 1378 chars]
- Image width:
- Remediation
View remediation
Remediation Suggestions
- Validate that
scaleis an integer within a conservative positive range, such as1through50. - Reject input files exceeding a defined byte-size limit before reading them fully.
- Read incrementally and enforce explicit maximum row-count and column-count limits.
- Calculate output dimensions before image creation and reject zero, negative, or excessive dimensions.
- Enforce a maximum total-pixel budget, using checked calculations before calling
Image.new(). - Catch
ValueError,OSError, Pillow decompression/allocation errors, andMemoryError, then return a controlled nonzero exit status without exposing a traceback. - Where available, run the renderer with operating-system memory, CPU, and execution-time limits.
- Document the accepted input and scale limits in
SKILL.md.
- Validate that
