Tests / Test failed: 4, passed: 744
Replace hand-written f-string + html.escape() rendering in the Host Agent
local console with a module-level Jinja2 Environment configured with
select_autoescape(["html","xml"]). XSS safety now holds by mechanism
rather than per-call discipline — every operator-controlled field
(device name, connection_info, task summary, etc.) is escaped by the
engine uniformly.
Eight templates under host_agent/web/templates/ replace the former
_chrome(), _CSS, escape(), and per-page _xxx_body() helpers: base.html
(header/nav/CSS + {% block body %}), login, dashboard (with the polling
<script> preserved byte-identically inside {% raw %}), devices, account,
history, tasks_list, and task_detail. The task-list and task-detail
templates — added by the just-landed task-execution-progress-visibility
change — were also migrated here rather than left in f-string form,
since this change removes the shared helpers they depended on.
URLs, auth/session/CSRF semantics, redirects, and /api/status JSON are
unchanged. 15 new template tests cover render-smoke, XSS probing, script
byte-identity, and no-autoescape-bypass guards. Tasks 8.1-8.6 (manual
browser verification) remain.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
23 lines
979 B
HTML
23 lines
979 B
HTML
{% extends "base.html" %}
|
|
{% block body %}
|
|
<h1>Task {{ task.get("id") or "" }}</h1>
|
|
<table>
|
|
<thead><tr><th>Field</th><th>Value</th></tr></thead>
|
|
<tbody>{% for row in task_rows %}<tr><td>{{ row[0] }}</td><td>{{ row[1] }}</td></tr>{% endfor %}</tbody>
|
|
</table>
|
|
<h2>Timeline</h2>
|
|
{% if not timeline_steps %}
|
|
<p>No timeline records.</p>
|
|
{% else %}
|
|
{% for step in timeline_steps %}
|
|
<div style="border:1px solid #ccc;background:#fff;padding:0.75rem;margin-bottom:0.75rem;">
|
|
<p><strong>Step {{ step.index }}</strong> — {{ step.timestamp }}</p>
|
|
<p>Prompt: {{ step.prompt }}</p>
|
|
<p>Tool call: <code>{{ step.tool_call_text }}</code></p>
|
|
<p>Result: <code>{{ step.result_text }}</code></p>
|
|
{% if step.screenshot_src %}<img src="{{ step.screenshot_src }}" alt="screenshot" style="max-width:100%;border:1px solid #ccc;margin-top:0.5rem;">{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% endblock %}
|