daybook/issues/018-handover-to-llm-test-round-3.md
peter 54f8e8ea3b Add round-3 handover doc for the LLM test project
Covers the #014-#016 fixes (sanitization+CSP, nested-JSON 400, ragged-CSV
normalization) and flags the sanitizer as the top round-4 adversarial
target (mutation XSS, attribute/scheme bypasses, CSP presence). Notes #017
is a design issue, not a bug to re-report, and the aesthetic/UI changes
have no API surface.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-03 13:47:46 +01:00

93 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 018 — Handover to AGENT_DAYBOOK__LLM_TEST (round 3)
**Status:** For information — a handback covering everything fixed/changed
since the round-2 handoff (#013).
Round-2 testing (against #013's suggestions) filed #014, #015, #016 — all
now fixed. This round-3 handoff summarizes those fixes and points at where
the fresh adversarial surface is, plus one new design issue (#017) that is
**not** a bug and shouldn't be re-reported.
All changes are on `main` (pushed to Forgejo) and live on the local dev
instance (`http://127.0.0.1:8001`) via autoreload — no restart needed.
Test as always with the `test` / `testpwd` account and clean up after
yourself.
## Fixes since #013 (issues you filed)
- **#014 (High) — stored XSS.** `markdown`, `html_fragment`, and `deck` are
now allowlist-sanitized (nh3) at create time: `<script>`, `on*` handlers,
`<style>`, and `javascript:`/`data:` URLs are stripped, while formatting/
tables/links/images (incl. relative `/assets/<id>`) survive. Those kinds
are also served with `Content-Security-Policy: script-src 'none'` (on both
`/a/{id}` and the public `/s/{token}` route). `html_full` is deliberately
**not** sanitized (verbatim escape hatch) and `json`/`csv` keep their
existing `escape_script_body` defense.
- **#015 (Med) — deeply nested JSON → 500.** Now returns `400` on both
paths: the `json`-kind validator catches `RecursionError`, and a new DRF
`EXCEPTION_HANDLER` maps parser-level `RecursionError` (deep nesting
anywhere in the request body) to `400`.
- **#016 (Low-Med) — ragged CSV rows.** `wrap_csv_viewer` now normalizes
every row to the max width (long rows widen the columns with auto-named
`Column N`; short rows pad with `""`), so no cell is dropped.
## Other changes (context, mostly not API-surface)
- Document artifact backgrounds unified to one off-white (`#faf9f6`) across
markdown/html_fragment/json/csv (report/tasks/base themes). Deck stays
dark; html_full/pdf unchanged. Only relevant to you as: the rendered HTML
background value changed — no behavioral/API change.
- UI-only work (dark mode toggle, top-bar logo, sidebar width behavior,
greyscale chrome). No API surface.
- **#017 filed — customizable theme variants.** A *design issue* (feature
request), not a bug. Don't re-report theme/color inflexibility as a bug;
it's tracked.
## Suggested Round-4 Probes
Prioritized by where the new surface is riskiest.
### The sanitizer (#014) — now the top adversarial target
The XSS fix is an allowlist sanitizer; the classic follow-up is trying to
get past it. Worth hard probing on `markdown`, `html_fragment`, `deck`:
- **Mutation/parser-confusion XSS**: malformed nesting, stray `<`/`>`,
comments (`<!-- -->`), CDATA, `<svg>`/`<math>` foreign-content vectors,
`<noscript>`/`<template>`, deprecated/odd tags — anything that might
re-parse into script after nh3 serializes.
- **Attribute vectors**: `on*` variants, `style=` (should be stripped),
`href`/`src` with `javascript:`, `data:`, `vbscript:`, whitespace/newline/
encoding tricks (`java\tscript:`, `&#106;avascript:`), `srcset`, `formaction`.
- **Allowlisted-tag abuse**: does anything survive on the *permitted* tags
(a/img/etc.) that shouldn't — e.g. `<a href>` protocol bypasses, `<img
src>` with odd schemes?
- **CSP presence**: confirm `script-src 'none'` is actually on the response
for markdown/deck/html_fragment (both `/a/` and `/s/`), and absent for
html_full and json/csv. Confirm markdown/deck/html_fragment pages contain
no executable inline script at all after sanitization.
- **html_full is out of scope** — it's verbatim by design; a `<script>`
surviving there is not a bug (documented). Don't file it.
- Verify the sanitizer didn't over-strip: tables, code highlighting, links,
relative `/assets` images, headings/lists still render.
### #015 recursion — other sites
- Deeply nested `metadata` / `tag_colors` (string-parsed JSON), deeply
nested arrays vs objects, right-at-the-limit depths. Confirm 400 not 500.
### #016 CSV — other raggedness
- Header shorter than data rows, entirely empty first row, mixed quoting
with ragged widths, a row that's all empty cells. Confirm no data lost and
the auto-named columns behave.
### Regression sweep
- Re-run the #002–#012 repros briefly to confirm none regressed (esp. the
#010 quota race and #006 eviction, which have thin/no automated coverage).
As always: use `test`/`testpwd`, clean up, check `artifacts/views.py` before
calling a surprise a bug (some behavior is documented/by-design), and file
anything real as a new numbered issue (next is #019), linking back if it's
a variant of a closed one.