Skip to content

fix(core/socketio): accept http://tauri.localhost origin (#2331 follow-up)#2482

Merged
M3gA-Mind merged 2 commits into
tinyhumansai:mainfrom
oxoxDev:fix/tauri-localhost-origin-allowlist
May 22, 2026
Merged

fix(core/socketio): accept http://tauri.localhost origin (#2331 follow-up)#2482
M3gA-Mind merged 2 commits into
tinyhumansai:mainfrom
oxoxDev:fix/tauri-localhost-origin-allowlist

Conversation

@oxoxDev
Copy link
Copy Markdown
Contributor

@oxoxDev oxoxDev commented May 22, 2026

Summary

  • Adds http://tauri.localhost to the Socket.IO handshake origin allowlist so the Windows CEF app shell can connect when the realtime gate from feat: tighten runtime policy + transport guards #2331 is active.
  • Folds the literal scheme/host short-circuit into the existing URL-parse host_str match so all three Tauri webview document-origin shapes (tauri://, http://, https:// + tauri.localhost) go through one check.
  • Extends the unit coverage with the new shape plus a matching exact-host decoy.

Problem

#2331 added an origin allowlist on the Socket.IO connect path. The literal-string short-circuit only matched tauri://localhost (macOS/iOS native scheme) and https://tauri.localhost (Linux / older Windows builds). On current Windows the CEF shell stamps http://tauri.localhost as the document origin, which fell through to the loopback host check and failed because tauri.localhost was not in the host set.

The end-user symptom: with a remote core configured, normal RPC kept working (those calls go through the Tauri IPC relay and never carry a browser Origin), but every Socket.IO connect was rejected with [socketio] rejecting connect: bad origin "http://tauri.localhost".

Solution

Replace the literal-string short-circuit with a single URL-parse → host_str → exact-match table covering all four trusted hosts (localhost, 127.0.0.1, ::1, tauri.localhost). Any scheme (http, https, tauri, ws, wss) is acceptable because the parser still rejects scheme-only payloads like javascript:alert(1) (no host) and the exact-host check still rejects starts_with decoys like http://tauri.localhost.attacker.example. The behaviour for every previously-allowed origin is preserved; only the previously-rejected http://tauri.localhost flips to allowed.

Module rustdoc now lists the four supported shell origins as a table so future readers see why the allowlist looks the way it does.

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy
  • Diff coverage ≥ 80% — changed lines covered by the extended origin_allowlist_* unit tests in src/core/socketio.rs (7 tests, all pass via cargo test --lib core::socketio::tests).
  • N/A: Coverage matrix update — no new feature row; this is a regression fix for an existing entry.
  • All affected feature IDs from the matrix are listed in the PR description under ## Related
  • No new external network dependencies introduced (mock backend used per Testing Strategy)
  • N/A: Manual smoke checklist — no release-cut surface change; smoke matrix unchanged.
  • N/A: Linked issue closed via Closes #NNN — no GH issue tracks this; flagged in feat: tighten runtime policy + transport guards #2331 follow-up.

Impact

  • Platform: Windows desktop unblocked. macOS/Linux unchanged (their origin literals still resolve to the same allowed shapes).
  • Security: same posture as feat: tighten runtime policy + transport guards #2331. tauri.localhost is a reserved Tauri-internal host (not publicly resolvable), so adding it to the host allowlist does not expand the cross-origin attack surface — only the same bundled webview the previous literals already covered now flows through the host-match arm.
  • Compatibility: pure broadening of accepted origins; no client-side change required.

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: fix/tauri-localhost-origin-allowlist
  • Commit SHA: 135b44c

Validation Run

  • pnpm --filter openhuman-app format:check — N/A: no frontend change
  • pnpm typecheck — N/A: no frontend change
  • Focused tests: cargo test --lib core::socketio::tests → 7 passed
  • Rust fmt/check (if changed): cargo fmt --check clean; cargo check --manifest-path Cargo.toml clean
  • Tauri fmt/check (if changed): N/A: no Tauri-shell change

Validation Blocked

  • command: N/A
  • error: N/A
  • impact: N/A

Behavior Changes

  • Intended behavior change: Socket.IO handshake now accepts http://tauri.localhost in addition to tauri://localhost + https://tauri.localhost.
  • User-visible effect: Windows app shell can connect to the realtime socket again when running against a separately-started core.

Parity Contract

  • Legacy behavior preserved: every previously-accepted origin still passes; every previously-rejected origin (cross-site, host-prefix decoys, unparseable strings, null, empty) still rejects.
  • Guard/fallback/dispatch parity checks: covered by the origin_allowlist_rejects_* tests in src/core/socketio.rs.

Summary by CodeRabbit

  • Bug Fixes

    • Strengthened Socket.IO origin validation using strict URL parsing and exact host matching; added explicit acceptance for tauri.localhost and loopback variants while rejecting empty, "null", unparseable, or decoy origins.
  • Tests

    • Expanded coverage for origin validation, including tauri.localhost, loopback without port, and host-decoy regressions.
  • Documentation

    • Added German translation entries for subconscious flows and MCP server UI/configuration.

Review Change Stack

…i#2331 follow-up)

Windows CEF stamps `http://tauri.localhost` as the document origin on
the shipped app shell — the prior allowlist literal block only matched
`tauri://localhost` (macOS native scheme) and `https://tauri.localhost`
(Linux / older Windows), so the socket handshake was rejected on
Windows with a remote core configured. Normal RPC over the Tauri IPC
relay sidestepped this gate, which is why only the realtime socket
path broke.

Fold all four loopback shapes (`localhost`, `127.0.0.1`, `::1`,
`tauri.localhost`) into the URL-parse `host_str` match so every Tauri
webview scheme (`http://`, `https://`, `tauri://`) flows through the
same exact-host check. The `starts_with`-decoy rejections still apply
(`http://tauri.localhost.attacker.example` etc.).

Extends the unit coverage with the new shape and a matching
exact-host decoy.
@oxoxDev oxoxDev requested a review from a team May 22, 2026 07:18
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: de3d3b2a-7392-4546-9d7a-cd5e919dfefc

📥 Commits

Reviewing files that changed from the base of the PR and between 135b44c and 9e79d2f.

📒 Files selected for processing (2)
  • app/src/lib/i18n/chunks/de-3.ts
  • app/src/lib/i18n/chunks/de-5.ts
✅ Files skipped from review due to trivial changes (1)
  • app/src/lib/i18n/chunks/de-3.ts

📝 Walkthrough

Walkthrough

The origin_is_allowed function now parses the Origin header as a URL and performs exact host matching against an allowlist that includes tauri.localhost and loopback addresses. Module docs and unit tests were updated and extended. Separate German translation entries were added for subconscious UI and MCP-Server strings.

Changes

Socket.IO origin allowlist validation

Layer / File(s) Summary
Origin allowlist logic and documentation
src/core/socketio.rs
origin_is_allowed parses Origin as a URL and performs exact host matching against an expanded allowlist (tauri.localhost, loopback addresses including IPv6 forms). Module documentation clarifies platform-dependent Origin shapes and exact host matching requirements.
Origin validation test coverage
src/core/socketio.rs
Unit tests validate tauri.localhost acceptance across schemes, loopback origins without explicit ports, and rejection of host-prefix decoys (tauri.localhost.attacker.example).

German translations (i18n)

Layer / File(s) Summary
subconscious translations
app/src/lib/i18n/chunks/de-3.ts
Added subconscious.providerUnavailableTitle and subconscious.providerSettings German entries.
MCP-Server translations
app/src/lib/i18n/chunks/de-5.ts
Added multiple German translation keys for MCP-Server developer menu and MCP server UI (client selection, copy feedback, binary/config errors, client names, aria labels).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

rust-core, bug

Suggested reviewers

  • senamakel

Poem

🐰 A safer handshake, no tricks at the door,
Exact host matching—decoys nevermore!
tauri.localhost joins the trust-worthy crew,
With tests that ensure nothing slips through.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding http://tauri.localhost to the Socket.IO origin allowlist, with a clear reference to the follow-up issue.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure. bug labels May 22, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 22, 2026
…yhumansai#2378

`Add German locale support (tinyhumansai#2378)` did not include keys added by the
parallel `feat(settings): add MCP server configuration panel` and
`fix(subconscious): pause when provider unavailable` work, so the
post-merge i18n coverage check has been red on `main` since the German
locale landed. Coverage gate trips on every PR that touches `app/` —
including unrelated changes like this one — until the locale catches
up with the English source-of-truth.

Adds the 20 missing German strings to `de-3.ts` (subconscious) and
`de-5.ts` (settings.mcpServer + settings.developerMenu.mcpServer).
Translations follow the convention already in `de-5.ts` for the
sibling `settings.mascot.*` keys (full German for UI strings,
proper-noun product names left unchanged).

Drive-by: this fix is included on the runtime-policy follow-up PR
instead of opening a third PR because the i18n coverage gate blocks
the merge of the actual fix in `src/core/socketio.rs`. Same posture
as tinyhumansai#2331's `--no-verify` allowance for unrelated pre-existing
breakage on `main`.
Copy link
Copy Markdown
Contributor

@sanil-23 sanil-23 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving.

The Socket.IO origin fix is solid: folding the tauri://localhost / https://tauri.localhost literals into the single url::Url::parse → host_str exact-match table is cleaner and correctly handles the Windows CEF http://tauri.localhost shape. The native tauri://localhost path still parses to host_str() == "localhost" so nothing regresses, and the exact-host match keeps the suffix/decoy rejections intact (http://tauri.localhost.attacker.example, *.evil). Good test coverage on the new accept shape and the new decoys, and the rustdoc table documenting the per-platform origin shapes is a nice touch.

Non-blocking nit: the German i18n backfill in commit 9e79d2f (de-3.ts / de-5.ts, subconscious + mcpServer keys missing from #2378) is unrelated to the socketio fix and would ideally have been its own PR — and the AI-metadata's "no frontend change" line is inaccurate since two frontend files changed (CI ran typecheck/i18n anyway and they pass, so no harm). Not holding the PR on it.

@M3gA-Mind M3gA-Mind merged commit 62727e1 into tinyhumansai:main May 22, 2026
29 checks passed
CodeGhost21 pushed a commit to CodeGhost21/openhuman that referenced this pull request May 22, 2026
senamakel pushed a commit to aqilaziz/openhuman that referenced this pull request May 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug rust-core Core Rust runtime in src/: CLI, core_server, shared infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants