Skip to content

Insight API is cross-origin readable in both runtimes and DELETE-enabled in Node runtime #293

@shaun0927

Description

@shaun0927

Observation

ctx_insight is documented as a local analytics UI, and the README frames context-mode as privacy-first / nothing leaves your machine.

While re-validating recent Insight changes against main@72eacf5 (2026-04-16) and v1.0.89, I found that the Insight API still advertises permissive cross-origin access:

  • GET API responses include Access-Control-Allow-Origin: *
  • in the Node runtime, API responses also include Access-Control-Allow-Methods: GET, DELETE, OPTIONS
  • the Node runtime accepts OPTIONS preflight requests for DELETE
  • a different localhost origin can read session event data, and in Node mode it can also trigger destructive DELETEs against indexed content

I’m not claiming a remote-network exploit here. This is a same-machine / different-origin trust-boundary issue for the local dashboard.

Repro steps

I reproduced this in a local fork against the latest upstream main using fixture SQLite DBs and two Insight runtimes.

Node runtime (verified read + DELETE)

  1. Start Insight with fixture DBs:
    • PORT=4748
    • INSIGHT_SESSION_DIR=/tmp/context-mode-cors-repro/sessions
    • INSIGHT_CONTENT_DIR=/tmp/context-mode-cors-repro/content
  2. Send a cross-origin-style GET:
curl -i http://127.0.0.1:4748/api/sessions/abcd1234/events/sess-1 \
  -H 'Origin: http://127.0.0.1:8081'
  1. Send a preflight for DELETE:
curl -i -X OPTIONS http://127.0.0.1:4748/api/content/feedface/source/7 \
  -H 'Origin: http://127.0.0.1:8081' \
  -H 'Access-Control-Request-Method: DELETE'
  1. Send the DELETE itself:
curl -i -X DELETE http://127.0.0.1:4748/api/content/feedface/source/7 \
  -H 'Origin: http://127.0.0.1:8081'

Bun runtime (verified read)

  1. Start Insight with the same fixture DBs on PORT=4747
  2. Send the same GET request with Origin: http://127.0.0.1:8081
  3. Sensitive session data is returned with Access-Control-Allow-Origin: *

In Bun mode, DELETE preflight currently falls through to the HTML response instead of returning a permissive preflight, so the destructive path appears blocked there by broken preflight handling. The read exposure is still present.

Expected

The local dashboard should remain same-origin by default.

A different localhost origin should not be able to:

  • read session event / resume data from the Insight API
  • preflight and issue destructive API calls

Actual

  • both runtimes allow cross-origin reads of sensitive session data
  • the Node runtime also permits cross-origin DELETE preflight + DELETE execution

Relevant code

Current behavior appears to come from insight/server.mjs:

  • apiSessionEvents / apiDeleteSource
  • route handling for /api/sessions/.../events/... and DELETE /api/content/...
  • permissive headers in both Bun and Node server branches

Environment

  • Repo: mksglu/context-mode
  • Latest upstream main tested: 72eacf5
  • Latest release also checked: v1.0.89
  • Local validation on macOS
  • Verified with both Bun and Node runtimes

Suggested direction

I think this is worth discussing as an issue first, because there are multiple valid fixes:

  • remove permissive CORS headers entirely for Insight API routes
  • keep the dashboard same-origin only by default
  • optionally add an explicit future opt-in sharing/token model if cross-origin access is ever needed

If you'd like, I can open a small follow-up PR with regression coverage and the narrowest possible fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions