Skip to content

fix(view): sanitize HTML rendering#1361

Open
FromSi wants to merge 2 commits into
floatpane:masterfrom
FromSi:fix/html-sanitization-rebased
Open

fix(view): sanitize HTML rendering#1361
FromSi wants to merge 2 commits into
floatpane:masterfrom
FromSi:fix/html-sanitization-rebased

Conversation

@FromSi
Copy link
Copy Markdown
Member

@FromSi FromSi commented May 25, 2026

What?

HTML email rendering now sanitizes untrusted content before converting it to terminal text.

Available after sanitization:

  • safe text/layout tags such as paragraphs, lists, tables, headings, blockquotes, and inline formatting
  • safe links using http, https, mailto, and tel
  • image sources using http, https, safe cid, and valid data:image payloads

Not available after sanitization:

  • javascript:, vbscript:, file:, relative, and protocol-relative links
  • data: or cid: links in <a href>
  • scripts, styles, event handlers like onclick, and unsafe attributes
  • OSC 8 clickable image fallbacks for cid: and data:image sources

Demo of the fix:
image

Why?

Closes #653

HTML emails could include unsafe links or attributes such as javascript: URLs and on* event handlers. In terminals with OSC 8 hyperlink support, these could become risky clickable terminal links.

This hardens HTML rendering for untrusted email content and addresses.

Demo of the issue:
image

@FromSi FromSi requested a review from a team as a code owner May 25, 2026 12:54
@floatpanebot floatpanebot added bug Something isn't working dependencies Dependency updates area/tui Terminal UI / view layer size/L Diff: 201–800 lines and removed bug Something isn't working labels May 25, 2026
@floatpanebot
Copy link
Copy Markdown
Member

Benchmark report — no significant change

Metrics worse: 0 · better: 0 (threshold: ±3%).

benchstat output
goos: linux
goarch: amd64
pkg: github.com/floatpane/matcha/backend
cpu: AMD EPYC 7763 64-Core Processor                
                           │    old.txt    │               new.txt               │
                           │    sec/op     │    sec/op      vs base              │
ParseSearchQuery_Simple-4    2.977µ ± 253%   2.565µ ± 231%       ~ (p=0.818 n=6)
ParseSearchQuery_Complex-4   5.383µ ±  92%   8.897µ ±  46%       ~ (p=0.310 n=6)
TokenizeSearchQuery-4        4.021µ ±  51%   3.325µ ±  47%       ~ (p=0.180 n=6)
geomean                      4.009µ          4.233µ         +5.59%

                           │  old.txt   │              new.txt               │
                           │    B/op    │    B/op     vs base                │
ParseSearchQuery_Simple-4    26.00 ± 0%   26.00 ± 0%       ~ (p=1.000 n=6) ¹
ParseSearchQuery_Complex-4   762.0 ± 0%   762.0 ± 0%       ~ (p=1.000 n=6) ¹
TokenizeSearchQuery-4        176.0 ± 0%   176.0 ± 0%       ~ (p=1.000 n=6) ¹
geomean                      151.6        151.6       +0.00%
¹ all samples are equal

                           │  old.txt   │              new.txt               │
                           │ allocs/op  │ allocs/op   vs base                │
ParseSearchQuery_Simple-4    2.000 ± 0%   2.000 ± 0%       ~ (p=1.000 n=6) ¹
ParseSearchQuery_Complex-4   23.00 ± 0%   23.00 ± 0%       ~ (p=1.000 n=6) ¹
TokenizeSearchQuery-4        9.000 ± 0%   9.000 ± 0%       ~ (p=1.000 n=6) ¹
geomean                      7.453        7.453       +0.00%
¹ all samples are equal

pkg: github.com/floatpane/matcha/tui
                    │   old.txt    │              new.txt               │
                    │    sec/op    │    sec/op     vs base              │
LogPanelView-4        171.0µ ±  6%   165.8µ ± 23%       ~ (p=0.699 n=6)
SearchOverlayView-4   187.7µ ± 12%   187.9µ ± 15%       ~ (p=1.000 n=6)
InboxConstruction-4   940.0µ ± 27%   918.0µ ± 30%       ~ (p=1.000 n=6)
geomean               311.3µ         305.8µ        -1.78%

                    │    old.txt     │               new.txt                │
                    │      B/op      │     B/op       vs base               │
LogPanelView-4        21.79Ki ± 105%   44.67Ki ± 51%        ~ (p=0.405 n=6)
SearchOverlayView-4   44.67Ki ±  26%   56.14Ki ± 41%        ~ (p=0.498 n=6)
InboxConstruction-4   874.0Ki ±   0%   874.3Ki ±  0%   +0.04% (p=0.002 n=6)
geomean               94.75Ki          129.9Ki        +37.12%

                    │   old.txt   │              new.txt              │
                    │  allocs/op  │  allocs/op   vs base              │
LogPanelView-4         712.0 ± 0%    714.0 ± 0%       ~ (p=0.567 n=6)
SearchOverlayView-4    925.0 ± 0%    926.0 ± 0%       ~ (p=1.000 n=6)
InboxConstruction-4   3.476k ± 0%   3.478k ± 0%  +0.07% (p=0.002 n=6)
geomean               1.318k        1.320k       +0.15%

auto-generated by benchmarks.yml

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/tui Terminal UI / view layer dependencies Dependency updates size/L Diff: 201–800 lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: HTML email rendering XSS vulnerability

2 participants