github nesquena/hermes-webui v0.50.265

latest release: v0.50.266
2 hours ago

Release v0.50.265 — opt-in WebUI extension hooks

Single contributor PR + 4 Opus pre-release follow-ups.

What ships

feat

  • #1445 Opt-in WebUI extension hooks@ryansombraio — adds a deliberately-small, self-hosted extension surface for administrators who want to inject local CSS/JS into the WebUI shell without forking the core repo. Disabled by default; activates only when HERMES_WEBUI_EXTENSION_DIR points to an existing directory. Three env vars (HERMES_WEBUI_EXTENSION_DIR, HERMES_WEBUI_EXTENSION_SCRIPT_URLS, HERMES_WEBUI_EXTENSION_STYLESHEET_URLS) expose the surface. New /extensions/... route is auth-gated (NOT in PUBLIC_PATHS, unlike /static/...). URL validation rejects external schemes, protocol-relative URLs, fragments, traversal (raw + percent-encoded + double-encoded + quadruple-encoded after Opus follow-up), control characters, quotes, and angle brackets. Filesystem serving sandboxes paths via Path.resolve() + relative_to(), rejects dotfiles, dot-directories, encoded backslashes, and symlink escapes. CSP unchanged — extensions live at same origin. 7 regression tests in tests/test_extension_hooks.py. Documentation in docs/EXTENSIONS.md covers extension authoring + trust model.

Opus pre-release advisor follow-ups

  • _fully_unquote_path iteration cap raised from 3 to 10 — quadruple-encoded .. now correctly collapses to literal .. and is rejected by the validator (defense in depth; not previously exploitable but a contract violation).
  • Trust-model callout at top of docs/EXTENSIONS.md — moved the strongest warning ("extensions execute with full WebUI session authority") from middle of doc to a blockquote callout right after the lead paragraph. Adds explicit "do not point at user-writable directory" guidance.
  • URL list cap (32 entries) + reject-URL logging — caps configured URL lists to avoid pathological rendering. Logs one-shot WARNING per process for each rejected URL so misconfigurations are visible.
  • MIME map expansion — adds ttf (font/ttf), otf (font/otf), wasm (application/wasm) so modern fonts and WebAssembly modules serve correctly (Chrome refuses .wasm as text/plain).

Stage-only test harness

  • Test-only fix: tests/test_extension_hooks.py::test_extension_route_remains_behind_webui_auth SimpleNamespace needed query="" (auth.py accesses parsed.query since v0.50.258).
  • 5 regression tests in tests/test_pr1445_opus_followups.py pin all Opus follow-up invariants.

Verification

  • Full pytest: 3705 passed, 2 skipped, 3 xpassed, 0 failed in 86s on the stage branch.
  • Browser sanity: 20 + 11 API checks green.
  • Opus pre-release advisor: SHIP verdict on the merged stage diff. Two pre-merge nits + three nice-to-haves all applied in stage.
  • Security audit (deep check, see brief): path validation correct, encoded traversal blocked at all encoding depths, dotfile/symlink rejection works, extension route auth-gated (verified via server.py:76), CSP unchanged.

Constituent merges (no-ff, attribution preserved)

4ee9368 Opus pre-release follow-ups for PR #1445
73cb3c1 stage-265: test fix + CHANGELOG for v0.50.265
3de70c5 Merge PR #1445: feat: add opt-in WebUI extension hooks
9de61a0 feat: add opt-in webui extension hooks

Stage rebased cleanly on fb66ba5 (current master, post-v0.50.264). Original PR was 12 releases behind master at fork point; rebased clean with no conflicts.

Stats

  • Files: 6 (api/extensions.py, api/routes.py, README.md, docs/EXTENSIONS.md, tests/test_extension_hooks.py, tests/test_pr1445_opus_followups.py, CHANGELOG.md)
  • Diff: ~860 LOC added (624 from contributor + ~236 from Opus follow-ups + tests)
  • Tests added: 12 (7 from #1445 + 5 from Opus follow-ups)

Closes

Author credit

--no-ff merge preserves original authorship and timestamp for @ryansombraio. CHANGELOG explicitly credits the contributor.

Don't miss a new hermes-webui release

NewReleases is sending notifications on new releases.