Dorian 39c7ac1924 feat: rootless podman, session hardening, boot stability, sidebar fix
Rootless podman migration (TASK-11):
- Remove sudo from all podman calls in PodmanClient + 8 backend files
- Remove sudo from all podman/docker calls in deploy script
- Restore full systemd security hardening: NoNewPrivileges,
  RestrictAddressFamilies, MemoryDenyWriteExecute, RestrictRealtime,
  RestrictNamespaces, RestrictSUIDSGID, SystemCallFilter, ProtectSystem=strict
- Enable loginctl linger for rootless container persistence
- Remove Ollama from auto-deploy (marketplace-only)

Session & auth hardening:
- Increase MAX_CONCURRENT_SESSIONS 20→50 (prevents eviction storms)
- Debounced 401 redirect in rpc-client.ts (prevents redirect storms)

Boot stability:
- optimize-debian.sh: adds chrony, swap, removes policy-rc.d
- deploy script: pre-restart chrony + swap setup
- ISO build: chrony package, swap file creation
- BootScreen: no longer clears localStorage (prevents splash replay)
- RootRedirect: sole owner of localStorage clearing on server ready

UI fixes:
- Sidebar opacity default changed from 0→visible (fixes missing sidebar
  after page-persistence login without entrance animation)
- Console.log/error wrapped in import.meta.env.DEV guards
- Remove unused route import from RootRedirect

Beta tracking:
- CLAUDE.md: beta freeze protocol added
- MASTER_PLAN.md: TASK-11, TASK-17, phase structure
- BETA-PROGRESS.md: initial tracking doc
- Tagged v1.2.0-alpha.1 as pre-rootless baseline

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 13:53:27 +00:00

2.7 KiB

XSS Analysis Complete

Written to loop/pentest/analysis/xss.md. Here's the summary:

4 Findings

ID Type Location Confidence
XSS-001 DOM-based iframe src injection AppSession.vue:399-418?path= query param concatenated to iframe src without validation Medium
XSS-002 DOM-based javascript: URI redirect Login.vue:220,384-386?redirect= flows to window.location.href in catch handler Medium
XSS-003 Cross-origin message injection appLauncher.ts:192-284 — NIP-07 postMessage handler has zero origin validation, responses sent with '*' High
XSS-004 Weak CSP (amplification) nginx-archipelago.conf:20script-src 'self' 'unsafe-inline' disables CSP as XSS defense High

Most Critical: XSS-003

The NIP-07 handler is the highest-risk finding. Any iframe (including the external HTTPS apps like botfights.net, nostrudel.ninja, etc.) can silently extract the user's Nostr public key without origin validation. The contextBroker.ts handler does this correctly — the appLauncher.ts handler does not, and sends responses with wildcard '*' origin.

No Reflected or Stored XSS Found

The codebase is clean on traditional XSS:

  • All v-html (2 instances) sanitized with DOMPurify
  • Stored messages sanitized with HTML entity encoding before storage
  • All dynamic content rendered via Vue {{ }} auto-escaping
  • Backend returns only JSON (serde_json), never raw HTML
  • Error messages sanitized by sanitize_error_message() before returning
{
  "category": "xss",
  "findings": [
    {
      "id": "XSS-001",
      "type": "dom_based_xss_iframe_src_injection",
      "endpoint": "/app/:appId",
      "parameter": "path (query)",
      "confidence": "medium",
      "payload_suggestion": "/app/indeedhub?path=%23<img+onerror=alert(1)+src=x>"
    },
    {
      "id": "XSS-002",
      "type": "dom_based_xss_javascript_uri_redirect",
      "endpoint": "/login",
      "parameter": "redirect (query)",
      "confidence": "medium",
      "payload_suggestion": "/login?redirect=javascript:alert(document.cookie)"
    },
    {
      "id": "XSS-003",
      "type": "dom_based_cross_origin_message_injection",
      "endpoint": "postMessage handler (NIP-07)",
      "parameter": "event.data (nostr-request)",
      "confidence": "high",
      "payload_suggestion": "window.parent.postMessage({type:'nostr-request',id:'1',method:'getPublicKey'},'*')"
    },
    {
      "id": "XSS-004",
      "type": "weak_csp_unsafe_inline",
      "endpoint": "all pages (nginx)",
      "parameter": "n/a",
      "confidence": "high",
      "payload_suggestion": "n/a - amplification factor, not direct XSS"
    }
  ]
}