fix stored XSS in investigation/report templates

`{{ json_data|safe }}` injected the output of `json.dumps(summary)` raw
into a <script> block. Python's json.dumps does not escape </script>,
so any attacker-controlled string in the summary (the query itself
when entity_type is company/person, scraped WHOIS, breach names, etc.)
could close the script tag and execute arbitrary JS in viewers'
browsers.

Use Jinja2's `tojson` filter, which produces HTML-safe JSON (escapes
<, >, &, ' to \uXXXX). Drop the server-side json.dumps argument and
the unused `json` import in report_generator.
This commit is contained in:
authentik Default Admin 2026-05-09 00:55:13 +00:00
parent 3365e0b23e
commit dd3a3db95d
3 changed files with 4 additions and 5 deletions

View file

@ -1,6 +1,5 @@
"""Report generator — Creates exportable HTML investigation reports."""
import os
import json
import logging
from jinja2 import Environment, FileSystemLoader
from eirescope.core.entity import Investigation
@ -30,7 +29,7 @@ class ReportGenerator:
"""Generate a standalone HTML report."""
summary = summarize_investigation(investigation)
template = self.env.get_template("report.html")
return template.render(inv=summary, json_data=json.dumps(summary))
return template.render(inv=summary)
def save_html(self, investigation: Investigation, output_path: str) -> str:
"""Generate and save HTML report to file."""

View file

@ -162,7 +162,7 @@ class EireScopeHandler(BaseHTTPRequestHandler):
summary = summarize_investigation(investigation)
template = jinja_env.get_template("investigation.html")
html = template.render(inv=summary, json_data=json.dumps(summary))
html = template.render(inv=summary)
self._html_response(html)
def _handle_api_investigation(self, inv_id: str):
@ -200,7 +200,7 @@ class EireScopeHandler(BaseHTTPRequestHandler):
else:
template = jinja_env.get_template("report.html")
html = template.render(inv=summary, json_data=json.dumps(summary))
html = template.render(inv=summary)
self._html_response(html, headers={
"Content-Disposition": f'attachment; filename="eirescope-report-{inv_id[:8]}.html"'
})

View file

@ -168,7 +168,7 @@
{% block scripts %}
<script>
const investigationData = {{ json_data|safe }};
const investigationData = {{ inv|tojson }};
</script>
<script src="/static/js/app.js"></script>
<script src="/static/js/graph.js"></script>