security: critical batch 1 — RCE/XSS/CORS/webhook hardening
Backend:
- auth/deps: fix refresh-lock clock race (cleanup now monotonic like the cache)
- core/registry: add missing structlog logger (NameError on fallback path)
- config: GNAUTH_WEBHOOK_SECRET, NAVI_ALLOWED_ORIGINS (+list property)
- webhooks: HMAC-SHA256 signature verification (503 unconfigured in auth mode,
  unsigned+warning in no-auth mode, 403 bad/stale signature, 400 bad JSON)
- main: CORS from NAVI_ALLOWED_ORIGINS in auth mode (fail-fast on empty),
  eval router behind require_admin, /debug only registered in no-auth mode
- auth routes: mobile-done sid validation (32 hex) + CSP header + safe JS
  escaping (reflected XSS); Secure cookie flag via helper (https base URL)
- websocket: anonymous WS rejected in auth mode (closes legacy-session RCE);
  socket registered only after access checks; stop_session auth gate
- messages: REST agent start now takes session lock + busy flag (409 on
  active run), contextvars reset in finally

Webclient:
- useMarkdown: DOMPurify.sanitize on all rendered markdown (stored XSS),
  image-URL scheme whitelist, delegated error listener (no inline onerror)
- html.html artifact viewer: sandbox without allow-same-origin (opaque origin)
- tests: DOMPurify runs under jsdom (happy-dom Node.prototype.nodeName getter
  breaks DOMPurify); useWebSocket tests get localStorage stub + ui-kit alias

Tests: pytest 1049 passed, 1 skipped; vitest 61 passed
1 parent 38c1a45 commit cc64ed8d7e5829d2a5f9432c4e672286f4fed305
@Eugene Sukhodolskiy Eugene Sukhodolskiy authored 23 hours ago
Showing 24 changed files
View
.env.example
View
docs/auth.md
View
navi/api/routes/auth.py
View
navi/api/routes/messages.py
View
navi/api/routes/webhooks.py
View
navi/api/websocket.py
View
navi/auth/deps.py
View
navi/config.py
View
navi/core/registry.py
View
navi/main.py
View
tests/integration/conftest.py
View
tests/integration/test_api_routes.py
View
tests/integration/test_websocket.py
View
tests/unit/api/test_auth_mobile_done.py 0 → 100644
View
tests/unit/api/test_webhooks.py 0 → 100644
View
tests/unit/api/test_websocket.py
View
tests/unit/auth/test_deps.py
View
webclient/package-lock.json
View
webclient/package.json
View
webclient/public/content-viewers/html.html
View
webclient/src/composables/useMarkdown.js
View
webclient/tests/unit/composables/useMarkdown.test.js 0 → 100644
View
webclient/tests/unit/composables/useWebSocket.test.js
View
webclient/vitest.config.js