BUG-HUNT: [security] Template rendering resource exhaustion vulnerability allows denial of service #7172

Open
opened 2026-04-10 08:28:52 +00:00 by HAL9000 · 1 comment
Owner

Background and Context

The YAML template rendering system in src/cleveragents/actor/yaml_template_engine.py has multiple resource exhaustion vulnerabilities that can be exploited for denial-of-service attacks. While the SandboxedEnvironment prevents code execution, it does not prevent resource exhaustion through complex templates or pathological input.

The affected methods are _render_and_parse(), _preprocess_for_rendering(), _postprocess_rendered_yaml(), and _fix_common_yaml_issues() (approximately lines 80–250).

Current Behavior

Vulnerability 1 — Unbounded Template Complexity: _render_and_parse() imposes no resource limits on template rendering. Templates of arbitrary complexity are accepted and rendered without timeout or memory bounds:

def _render_and_parse(self, yaml_content: str, context: dict[str, Any]) -> dict[str, Any]:
    template = self.env.from_string(processed_content)  # Unlimited complexity
    rendered = template.render(**full_context)           # No timeout

Vulnerability 2 — Quadratic String Processing: _fix_common_yaml_issues() performs O(n) operations per line (.count(":"), .split()) inside a loop over all lines, creating O(n²) worst-case behaviour on pathological input:

def _fix_common_yaml_issues(self, content: str) -> str:
    lines = content.split("\n")
    for line in lines:
        if line.count(":") > 1:          # O(n) per line
            tokens = remaining.split()   # O(n) per line — nested O(n²) total

Vulnerability 3 — No Input Size Limits: _preprocess_for_rendering() iterates over all lines of the input without any limit on line count or line length:

def _preprocess_for_rendering(self, content: str) -> str:
    lines = content.split("\n")   # No limit on line count
    for line in lines:            # Unbounded iteration

Attack Vectors:

  1. Memory exhaustion via template expression: name: "{{ range(10000000) | list | length }}"
  2. CPU exhaustion via nested loops:
    description: |
      {% for i in range(100000) %}
        {% for j in range(100000) %}Item {{i}}-{{j}}{% endfor %}
      {% endfor %}
    
  3. Pathological input: extremely long lines (megabytes per line), deep nesting requiring complex regex processing, or many lines triggering quadratic fixup operations.

No Defensive Measures Present:

  • No timeout on template rendering
  • No memory limits on template operations
  • No input size validation (max lines, max line length)
  • No complexity limits on Jinja2 expressions

Expected Behavior

The YAMLTemplateEngine must enforce resource limits at all processing stages:

  • Input size limits (configurable max lines and max line length) enforced before processing begins
  • Template rendering bounded by a configurable timeout (default: 30 s)
  • Jinja2 environment configured with loop iteration limits and expression complexity guards
  • Circuit breaker to prevent repeated DoS attempts from the same source

Metadata

  • Branch: bugfix/m3.5.0-security-yaml-template-resource-exhaustion-dos
  • Commit Message: fix(actor): add resource limits and input size guards to YAMLTemplateEngine to prevent DoS
  • Milestone: v3.5.0
  • Parent Epic: #5502

Subtasks

  • Add input size limits (max lines, max line length) to _preprocess_for_rendering()
  • Add configurable timeout (default 30 s) to _render_and_parse() template rendering
  • Add memory usage monitoring during template processing in _render_and_parse()
  • Configure Jinja2 SandboxedEnvironment with loop iteration limits and expression complexity guards
  • Fix quadratic string processing in _fix_common_yaml_issues() to prevent O(n²) worst-case behaviour
  • Add input validation guards to _postprocess_rendered_yaml()
  • Implement circuit breaker for repeated rendering failures
  • Write BDD scenarios covering all three attack vector categories (memory, CPU, pathological input)
  • Remove @tdd_expected_fail tag from TDD scenarios once fix is verified

Definition of Done

  • Input size limits enforced in _preprocess_for_rendering() before any processing occurs
  • Template rendering in _render_and_parse() has a configurable timeout; TemplateRenderTimeoutError raised on breach
  • Memory usage is bounded during template operations; TemplateMemoryLimitError raised on breach
  • Jinja2 SandboxedEnvironment configured with loop depth and iteration count limits
  • _fix_common_yaml_issues() processes input in O(n) time regardless of colon density
  • Circuit breaker prevents repeated DoS attempts
  • All three attack vectors (memory exhaustion, CPU exhaustion, pathological input) are covered by BDD scenarios tagged @tdd_issue and @tdd_issue_<N>
  • All nox stages pass
  • Coverage >= 97%

Automated by CleverAgents Bot
Supervisor: Bug Hunting | Agent: new-issue-creator

## Background and Context The YAML template rendering system in `src/cleveragents/actor/yaml_template_engine.py` has multiple resource exhaustion vulnerabilities that can be exploited for denial-of-service attacks. While the `SandboxedEnvironment` prevents code execution, it does not prevent resource exhaustion through complex templates or pathological input. The affected methods are `_render_and_parse()`, `_preprocess_for_rendering()`, `_postprocess_rendered_yaml()`, and `_fix_common_yaml_issues()` (approximately lines 80–250). ## Current Behavior **Vulnerability 1 — Unbounded Template Complexity**: `_render_and_parse()` imposes no resource limits on template rendering. Templates of arbitrary complexity are accepted and rendered without timeout or memory bounds: ```python def _render_and_parse(self, yaml_content: str, context: dict[str, Any]) -> dict[str, Any]: template = self.env.from_string(processed_content) # Unlimited complexity rendered = template.render(**full_context) # No timeout ``` **Vulnerability 2 — Quadratic String Processing**: `_fix_common_yaml_issues()` performs O(n) operations per line (`.count(":")`, `.split()`) inside a loop over all lines, creating O(n²) worst-case behaviour on pathological input: ```python def _fix_common_yaml_issues(self, content: str) -> str: lines = content.split("\n") for line in lines: if line.count(":") > 1: # O(n) per line tokens = remaining.split() # O(n) per line — nested O(n²) total ``` **Vulnerability 3 — No Input Size Limits**: `_preprocess_for_rendering()` iterates over all lines of the input without any limit on line count or line length: ```python def _preprocess_for_rendering(self, content: str) -> str: lines = content.split("\n") # No limit on line count for line in lines: # Unbounded iteration ``` **Attack Vectors**: 1. Memory exhaustion via template expression: `name: "{{ range(10000000) | list | length }}"` 2. CPU exhaustion via nested loops: ```yaml description: | {% for i in range(100000) %} {% for j in range(100000) %}Item {{i}}-{{j}}{% endfor %} {% endfor %} ``` 3. Pathological input: extremely long lines (megabytes per line), deep nesting requiring complex regex processing, or many lines triggering quadratic fixup operations. **No Defensive Measures Present**: - No timeout on template rendering - No memory limits on template operations - No input size validation (max lines, max line length) - No complexity limits on Jinja2 expressions ## Expected Behavior The `YAMLTemplateEngine` must enforce resource limits at all processing stages: - Input size limits (configurable max lines and max line length) enforced before processing begins - Template rendering bounded by a configurable timeout (default: 30 s) - Jinja2 environment configured with loop iteration limits and expression complexity guards - Circuit breaker to prevent repeated DoS attempts from the same source ## Metadata - **Branch**: `bugfix/m3.5.0-security-yaml-template-resource-exhaustion-dos` - **Commit Message**: `fix(actor): add resource limits and input size guards to YAMLTemplateEngine to prevent DoS` - **Milestone**: v3.5.0 - **Parent Epic**: #5502 ## Subtasks - [ ] Add input size limits (max lines, max line length) to `_preprocess_for_rendering()` - [ ] Add configurable timeout (default 30 s) to `_render_and_parse()` template rendering - [ ] Add memory usage monitoring during template processing in `_render_and_parse()` - [ ] Configure Jinja2 `SandboxedEnvironment` with loop iteration limits and expression complexity guards - [ ] Fix quadratic string processing in `_fix_common_yaml_issues()` to prevent O(n²) worst-case behaviour - [ ] Add input validation guards to `_postprocess_rendered_yaml()` - [ ] Implement circuit breaker for repeated rendering failures - [ ] Write BDD scenarios covering all three attack vector categories (memory, CPU, pathological input) - [ ] Remove `@tdd_expected_fail` tag from TDD scenarios once fix is verified ## Definition of Done - [ ] Input size limits enforced in `_preprocess_for_rendering()` before any processing occurs - [ ] Template rendering in `_render_and_parse()` has a configurable timeout; `TemplateRenderTimeoutError` raised on breach - [ ] Memory usage is bounded during template operations; `TemplateMemoryLimitError` raised on breach - [ ] Jinja2 `SandboxedEnvironment` configured with loop depth and iteration count limits - [ ] `_fix_common_yaml_issues()` processes input in O(n) time regardless of colon density - [ ] Circuit breaker prevents repeated DoS attempts - [ ] All three attack vectors (memory exhaustion, CPU exhaustion, pathological input) are covered by BDD scenarios tagged `@tdd_issue` and `@tdd_issue_<N>` - [ ] All nox stages pass - [ ] Coverage >= 97% --- **Automated by CleverAgents Bot** Supervisor: Bug Hunting | Agent: new-issue-creator
HAL9000 added this to the v3.5.0 milestone 2026-04-10 08:29:10 +00:00
Author
Owner

Verified — Critical security bug: template rendering resource exhaustion DoS vulnerability. MoSCoW: Must-have. Priority: Critical.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Verified** — Critical security bug: template rendering resource exhaustion DoS vulnerability. MoSCoW: Must-have. Priority: Critical. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
cleveragents/cleveragents-core#7172
No description provided.