BUG-HUNT: [security] Potential XSS vulnerability in HTML generation #4150

Open
opened 2026-04-06 11:29:59 +00:00 by freemo · 1 comment
Owner

Metadata

  • Branch: fix/bug-hunt-adr-hooks-xss
  • Commit Message: fix(adr-hooks): escape front-matter values before embedding in HTML to prevent XSS
  • Milestone: (none — backlog)
  • Parent Epic: #400

Backlog note: This issue was discovered during autonomous operation
on milestone v3.6.0. It does not block milestone completion and has been
placed in the backlog for human review and future milestone assignment.


Bug Report: [security] — Potential XSS vulnerability in HTML generation

Severity Assessment

  • Impact: An attacker with commit access to the repository could inject malicious scripts into the generated documentation site.
  • Likelihood: Low, as it requires contributor-level access.
  • Priority: Medium

Location

  • File: hooks/adr_hooks.py
  • Function/Class: _build_header, _build_related_adrs_section, _build_acceptance_section, and other HTML-building functions

Background and Context

Several functions in adr_hooks.py build HTML snippets using data read directly from the YAML front-matter of ADR markdown files. This data is not HTML-escaped before being embedded in the generated HTML. If an attacker can control the content of these files (e.g., a malicious contributor), they could inject arbitrary HTML including <script> tags, leading to a cross-site scripting (XSS) vulnerability on the generated documentation site.

Current Behavior

Front-matter values such as tier_title, title, relationship, voter, and comment are interpolated directly into f-string HTML without sanitisation.

Evidence

For example, in _build_header, tier_title is directly embedded:

# hooks/adr_hooks.py:166
if tier is not None and tier_title:
    tier_part = (
        f'<span class="adr-tier-badge">Tier {tier}</span>'
        f'<span class="adr-tier-title">{tier_title}</span>'  # tier_title is not escaped
        f'<span class="adr-label"> · </span>'
    )

Other examples include title and relationship in _build_related_adrs_section, and voter and comment in _build_acceptance_section.

Expected Behavior

All data from external sources (like front-matter) should be HTML-escaped before being embedded in HTML strings to prevent XSS attacks.

Suggested Fix

Use html.escape() to sanitize all values read from the front-matter before they are used in HTML strings.

import html

# ...

tier_title_escaped = html.escape(tier_title)
tier_part = (
    f'<span class="adr-tier-badge">Tier {tier}</span>'
    f'<span class="adr-tier-title">{tier_title_escaped}</span>'
    f'<span class="adr-label"> · </span>'
)

Category

security


Subtasks

  • Audit all HTML-building functions in hooks/adr_hooks.py for unescaped front-matter interpolation
  • Add import html to hooks/adr_hooks.py
  • Apply html.escape() to all front-matter-derived values used in HTML f-strings (tier_title, title, relationship, voter, comment, and any others found in the audit)
  • Tests: Add unit test scenarios with XSS payloads in front-matter fields to verify they are escaped in output
  • Verify coverage >= 97% via nox -s coverage_report
  • Run nox (all default sessions), fix any errors

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation.
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly.
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done.
  • All nox stages pass.
  • Coverage >= 97%.

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

## Metadata - **Branch**: `fix/bug-hunt-adr-hooks-xss` - **Commit Message**: `fix(adr-hooks): escape front-matter values before embedding in HTML to prevent XSS` - **Milestone**: *(none — backlog)* - **Parent Epic**: #400 > **Backlog note:** This issue was discovered during autonomous operation > on milestone v3.6.0. It does not block milestone completion and has been > placed in the backlog for human review and future milestone assignment. --- ## Bug Report: [security] — Potential XSS vulnerability in HTML generation ### Severity Assessment - **Impact**: An attacker with commit access to the repository could inject malicious scripts into the generated documentation site. - **Likelihood**: Low, as it requires contributor-level access. - **Priority**: Medium ### Location - **File**: `hooks/adr_hooks.py` - **Function/Class**: `_build_header`, `_build_related_adrs_section`, `_build_acceptance_section`, and other HTML-building functions ### Background and Context Several functions in `adr_hooks.py` build HTML snippets using data read directly from the YAML front-matter of ADR markdown files. This data is not HTML-escaped before being embedded in the generated HTML. If an attacker can control the content of these files (e.g., a malicious contributor), they could inject arbitrary HTML including `<script>` tags, leading to a cross-site scripting (XSS) vulnerability on the generated documentation site. ### Current Behavior Front-matter values such as `tier_title`, `title`, `relationship`, `voter`, and `comment` are interpolated directly into f-string HTML without sanitisation. ### Evidence For example, in `_build_header`, `tier_title` is directly embedded: ```python # hooks/adr_hooks.py:166 if tier is not None and tier_title: tier_part = ( f'<span class="adr-tier-badge">Tier {tier}</span>' f'<span class="adr-tier-title">{tier_title}</span>' # tier_title is not escaped f'<span class="adr-label"> · </span>' ) ``` Other examples include `title` and `relationship` in `_build_related_adrs_section`, and `voter` and `comment` in `_build_acceptance_section`. ### Expected Behavior All data from external sources (like front-matter) should be HTML-escaped before being embedded in HTML strings to prevent XSS attacks. ### Suggested Fix Use `html.escape()` to sanitize all values read from the front-matter before they are used in HTML strings. ```python import html # ... tier_title_escaped = html.escape(tier_title) tier_part = ( f'<span class="adr-tier-badge">Tier {tier}</span>' f'<span class="adr-tier-title">{tier_title_escaped}</span>' f'<span class="adr-label"> · </span>' ) ``` ### Category security --- ## Subtasks - [ ] Audit all HTML-building functions in `hooks/adr_hooks.py` for unescaped front-matter interpolation - [ ] Add `import html` to `hooks/adr_hooks.py` - [ ] Apply `html.escape()` to all front-matter-derived values used in HTML f-strings (`tier_title`, `title`, `relationship`, `voter`, `comment`, and any others found in the audit) - [ ] Tests: Add unit test scenarios with XSS payloads in front-matter fields to verify they are escaped in output - [ ] Verify coverage >= 97% via `nox -s coverage_report` - [ ] Run `nox` (all default sessions), fix any errors ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly. - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done. - All nox stages pass. - Coverage >= 97%. --- **Automated by CleverAgents Bot** Supervisor: Bug Hunting | Agent: ca-new-issue-creator
freemo added this to the v3.3.0 milestone 2026-04-06 18:06:32 +00:00
Author
Owner

Milestone Triage Decision: Moved to Backlog

This security logging issue has been moved out of v3.3.0 during aggressive milestone triage. While important for security, it does not relate to the core focus of Corrections + Subplans + Checkpoints.

Reasoning:

  • v3.3.0 focus: Essential corrections, subplan management, and checkpoint functionality
  • This issue: Security logging enhancement - important but not milestone-blocking
  • Impact: Security observability improvement, not core corrections/subplans/checkpoints functionality

Will be addressed in a future milestone focused on security hardening and observability.

**Milestone Triage Decision: Moved to Backlog** This security logging issue has been moved out of v3.3.0 during aggressive milestone triage. While important for security, it does not relate to the core focus of Corrections + Subplans + Checkpoints. **Reasoning:** - v3.3.0 focus: Essential corrections, subplan management, and checkpoint functionality - This issue: Security logging enhancement - important but not milestone-blocking - Impact: Security observability improvement, not core corrections/subplans/checkpoints functionality Will be addressed in a future milestone focused on security hardening and observability.
freemo removed this from the v3.3.0 milestone 2026-04-06 20:40:01 +00:00
HAL9000 added this to the v3.5.0 milestone 2026-04-09 03:12:35 +00:00
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.

Blocks
#400 Epic: Post-MVP Security
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#4150
No description provided.