Skip to content

Fix localhost bridge cross-origin file read and WebSocket hijack#44

Merged
Alban1911 merged 1 commit intoAlban1911:mainfrom
spookier:security/fix-localhost-hijack-spookier
Apr 27, 2026
Merged

Fix localhost bridge cross-origin file read and WebSocket hijack#44
Alban1911 merged 1 commit intoAlban1911:mainfrom
spookier:security/fix-localhost-hijack-spookier

Conversation

@spookier
Copy link
Copy Markdown
Contributor

@spookier spookier commented Apr 25, 2026

Summary

Fixes a localhost bridge security issue where arbitrary websites could interact with Rose's local HTTP/WebSocket server while Rose was running.

This patch:

  • rejects non-loopback browser Origin headers for HTTP bridge requests
  • rejects non-loopback browser Origin headers during WebSocket upgrade
  • removes wildcard CORS responses from localhost bridge endpoints
  • restricts /asset/ resolution to files inside Rose's bundled assets directory
  • rejects unsafe absolute, UNC, drive-letter, and traversal paths in bridge-controlled flows

Security impact

Before this change, a page such as https://attacker.example could read local files through:

http://127.0.0.1:50000/asset/C:/Users/<user>/...

and could also open a WebSocket to Rose's local bridge and send unauthenticated commands.

After this change, those cross-origin browser requests are rejected.

Also, you should double check if nothing got broken since I can't compile the binary on my end

Copilot AI review requested due to automatic review settings April 25, 2026 03:38
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Addresses a localhost bridge security issue by restricting which browser origins can interact with Rose’s local HTTP/WebSocket server and by hardening path handling for asset/mod related flows.

Changes:

  • Added loopback-only Origin validation helpers and used them to restrict HTTP bridge requests and WebSocket upgrades.
  • Removed wildcard CORS behavior and restricted /asset/ resolution to Rose’s bundled assets directory.
  • Hardened path validation in WebSocket message flows (UNC/absolute/traversal checks; URL-encoding for asset URLs; stricter League path validation).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
utils/core/security.py Introduces loopback-origin detection and CORS header construction helpers.
utils/core/paths.py Adds get_assets_dir() and hardens get_asset_path() to prevent escaping the assets directory.
pengu/core/websocket_server.py Blocks WebSocket upgrade requests when a non-loopback Origin is present.
pengu/core/http_handler.py Enforces loopback-only Origin access for HTTP routes and removes Access-Control-Allow-Origin: *.
pengu/communication/message_handler.py Tightens path validation for “other mod” selection, encodes asset URLs, and blocks unsafe League install paths.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +61 to +63
def _forbidden(self) -> tuple:
"""Return a generic forbidden response."""
return (403, {"Content-Type": "text/plain"}, b"Forbidden")
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

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

_forbidden() always returns a 403 without the computed cors_headers. For requests coming from an allowed loopback Origin, this results in a CORS-blocked response in the browser (the JS caller can’t read the 403/500 body/headers), even though the Origin itself is permitted. Consider threading cors_headers into _forbidden() (and the 500 handler) for the allowed-origin case, while still omitting CORS headers when the Origin is rejected.

Copilot uses AI. Check for mistakes.
Comment thread utils/core/security.py
Comment on lines +3 to +5
"""
Security helpers for Rose's localhost bridge.
"""
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

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

The PR description mentions adding regression tests for the new cross-origin / WebSocket / path validation behavior, but there don’t appear to be any test files added/updated in this change set. Either add the promised tests (or clarify where they live/how to run them), or update the PR description to avoid implying test coverage that isn’t present.

Copilot uses AI. Check for mistakes.
@Alban1911 Alban1911 merged commit 942b74e into Alban1911:main Apr 27, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants