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>
4.6 KiB
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, anddeckare now allowlist-sanitized (nh3) at create time:<script>,on*handlers,<style>, andjavascript:/data:URLs are stripped, while formatting/ tables/links/images (incl. relative/assets/<id>) survive. Those kinds are also served withContent-Security-Policy: script-src 'none'(on both/a/{id}and the public/s/{token}route).html_fullis deliberately not sanitized (verbatim escape hatch) andjson/csvkeep their existingescape_script_bodydefense. - #015 (Med) — deeply nested JSON → 500. Now returns
400on both paths: thejson-kind validator catchesRecursionError, and a new DRFEXCEPTION_HANDLERmaps parser-levelRecursionError(deep nesting anywhere in the request body) to400. - #016 (Low-Med) — ragged CSV rows.
wrap_csv_viewernow normalizes every row to the max width (long rows widen the columns with auto-namedColumn 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/srcwithjavascript:,data:,vbscript:, whitespace/newline/ encoding tricks (java\tscript:,javascript:),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
/assetsimages, 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.