Skip to content

Commit 7c60c69

Browse files
jeremyederclaude
andauthored
fix: Prevent XSS in HTML reports (fixes #54) (#62)
Eliminated double JSON encoding that could allow XSS attacks. Security improvements: - Pass dicts to template instead of pre-serialized JSON - Use Jinja2's tojson filter for proper JavaScript escaping - Remove unnecessary JSON.parse() calls - Prevent malicious data from breaking JavaScript context CVSS Score: 7.1 (High) → Resolved Attack Vector: Malicious repository metadata in HTML reports Mitigation: Single-encoding with Jinja2's safe tojson filter Technical Details: - Changed assessment_json → assessment_dict (dict, not string) - Changed available_themes_json → available_themes_dict - Updated template to use tojson without JSON.parse() - Jinja2 autoescape + tojson provides comprehensive protection Co-authored-by: Claude <noreply@anthropic.com>
1 parent 2bf052d commit 7c60c69

File tree

2 files changed

+10
-8
lines changed

2 files changed

+10
-8
lines changed

src/agentready/reporters/html.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"""HTML reporter for generating interactive assessment reports."""
22

3-
import json
43
from pathlib import Path
54

65
from jinja2 import Environment, PackageLoader, select_autoescape
@@ -68,13 +67,15 @@ def generate(self, assessment: Assessment, output_path: Path) -> Path:
6867
"duration_seconds": assessment.duration_seconds,
6968
"config": assessment.config,
7069
"metadata": assessment.metadata,
71-
# Embed assessment JSON for JavaScript
72-
"assessment_json": json.dumps(assessment.to_dict()),
70+
# Security: Pass dict directly, Jinja2's tojson filter handles escaping
71+
# Prevents XSS by avoiding double JSON encoding
72+
"assessment_dict": assessment.to_dict(),
7373
# Theme data
7474
"theme": theme,
7575
"theme_name": theme.name,
7676
"available_themes": available_themes,
77-
"available_themes_json": json.dumps(available_themes),
77+
# Security: Pass dict, not pre-serialized JSON
78+
"available_themes_dict": available_themes,
7879
}
7980

8081
# Render template

src/agentready/templates/report.html.j2

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -713,11 +713,12 @@
713713
</div>
714714

715715
<script>
716-
// Embedded assessment data (properly escaped to prevent XSS)
717-
const ASSESSMENT = JSON.parse({{ assessment_json|tojson }});
716+
// Security: Using Jinja2's tojson filter for proper XSS prevention
717+
// tojson creates JavaScript objects directly, no JSON.parse() needed
718+
const ASSESSMENT = {{ assessment_dict|tojson }};
718719
719-
// Embedded theme data
720-
const THEMES = JSON.parse({{ available_themes_json|tojson }});
720+
// Embedded theme data (properly escaped)
721+
const THEMES = {{ available_themes_dict|tojson }};
721722
const DEFAULT_THEME = {{ theme_name|tojson }};
722723
723724
// Theme management with localStorage persistence

0 commit comments

Comments
 (0)