v0.14.2

feder-cr/AIHawkv0.14.2Sep 8, 2026by feder-cr

AI Summary

This release addresses a security vulnerability by fixing the rendering of model-generated text to prevent HTML injection and exfiltration. The answer pane now uses a custom renderer that converts markdown syntax into safe semantic elements while strictly forbidding the creation of images, links, or scripts.

Key Highlights

  • Fixes rendering of model text to prevent HTML injection/exfiltration.
  • Implements a custom renderer that converts markdown-like asterisks into semantic HTML elements (strong, em, code, pre).
  • Verifies safety through tests ensuring no assignment to the `innerHTML` property or `insertAdjacentHTML` methods are used.

New Features

  • Custom renderer for the answer pane that safely handles markdown syntax (bold, italic, code) while stripping out dangerous elements (images, links, scripts).

Full Release Notes

The model answered `The main heading says **"Example Domain"**` and the page drew the asterisks.

Everything in this page is built with `textContent`, and that is not the oversight to correct: it is the reason the pane is safe. The text arriving in it was written by a model that had just read arbitrary web pages, so its content is chosen by whoever wrote the last page it visited. Putting that through the HTML parser is the documented road to exfiltration by injected image, and no amount of sanitising makes that road shorter than building the nodes by hand.

## What it does

The marks become elements and everything between them stays text: bold, italic, inline code, fenced blocks. An unclosed fence is still shown as code, because the alternative is prose that changes shape when the closing fence arrives.

Deliberately absent: **images**, which are the exfiltration vector itself, and **links**, which this pane has no reason to make clickable when the browser it drives is sitting right next to it.

## Verified, not asserted

Against the real model in a browser: the answer comes back with two rendered bold spans and no literal asterisks.

Fed a hostile string by hand, the renderer produced `strong`, `em`, `code` and `pre`, and **zero** `img`, `a` or `script` elements, with the script tag surviving as literal characters because it never stops being a text node.

The test asserts the invariant rather than the output: no assignment to the HTML property, no `insertAdjacentHTML`, no `document.write`, and no `img` or `a` constructed anywhere. It checks the assignment and not the word, because both the page and the test discuss that property in prose precisely because neither may use it - a check tripped by the sentence explaining the rule is the defect this project writes down most often.

## Test plan

- [x] `pytest -q`: 361 passed, 3 xfailed unchanged
- [x] the renderer driven by hand against a hostile string: 0 img, 0 a, 0 script, the tag stays text
- [x] end to end with the real model: 2 bold spans rendered, 0 literal asterisks
- [x] version, english and content gates clean