Skip to content

fix(browser): copilot ws_url honours x-forwarded-proto scheme#521

Merged
jaylfc merged 2 commits into
devfrom
fix/copilot-ws-scheme
Jun 2, 2026
Merged

fix(browser): copilot ws_url honours x-forwarded-proto scheme#521
jaylfc merged 2 commits into
devfrom
fix/copilot-ws-scheme

Conversation

@jaylfc
Copy link
Copy Markdown
Owner

@jaylfc jaylfc commented Jun 2, 2026

Addresses CodeRabbit's Major finding on #519.

The injected copilot websocket URL derived its scheme from request.url.scheme directly, while the CSP (from #519) uses the x-forwarded-proto-aware _request_scheme(). So behind a TLS terminator the page would inject ws:// instead of wss:// and the copilot socket would fail (mixed-content / wrong scheme).

Fix: route ws_scheme through _request_scheme(request), matching the CSP line. Adds unit tests for _request_scheme (plain http, direct https, x-forwarded-proto override, comma-list first-value, bogus-value clamp).

Only affects reverse-proxied HTTPS deploys; plain LAN http was already correct.

Summary by CodeRabbit

  • Bug Fixes

    • Ensure injected WebSocket URL uses the correct secure/insecure scheme when the app is behind a proxy, including safer handling of malformed or unexpected forwarded-protocol headers so connections use the appropriate ws/wss.
  • Tests

    • Added unit tests covering scheme selection, header precedence, comma-separated header values, and fallback behavior for invalid schemes.

The injected copilot websocket URL derived its scheme from
request.url.scheme directly, so behind a TLS terminator it would inject
ws:// instead of wss:// and the socket would fail. Route it through
_request_scheme() (x-forwarded-proto aware), matching the CSP line.
Addresses CodeRabbit on #519. Adds _request_scheme unit tests.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 21d019d6-89dd-4409-8970-0643cda16865

📥 Commits

Reviewing files that changed from the base of the PR and between 9d52f74 and e7eb84a.

📒 Files selected for processing (2)
  • tests/routes/desktop_browser/test_proxy_shell.py
  • tinyagentos/routes/desktop_browser/proxy.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/routes/desktop_browser/test_proxy_shell.py

📝 Walkthrough

Walkthrough

This PR adds tests for _request_scheme behavior covering HTTP/HTTPS resolution, x-forwarded-proto header precedence, comma-separated scheme handling, and unsupported scheme clamping. The proxy's WebSocket URL construction is updated to use _request_scheme(request) instead of the raw request URL scheme, aligning injected URLs with the effective scheme when behind HTTPS terminators.

Changes

HTTP Scheme Forwarding for WebSocket Injection

Layer / File(s) Summary
Scheme resolution implementation and WebSocket injection
tinyagentos/routes/desktop_browser/proxy.py
_request_scheme now treats malformed/unsupported x-forwarded-proto values as a signal to fall back to the request's own scheme and clamps the final result to http/https; the copilot WebSocket URL uses _request_scheme(request) for selecting ws vs wss.
Request scheme resolution tests
tests/routes/desktop_browser/test_proxy_shell.py
TestRequestScheme validates _request_scheme with assertions for plain HTTP/HTTPS, x-forwarded-proto override precedence, comma-list parsing (first entry), and fallback/clamping behavior for invalid forwarded/request schemes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • jaylfc/tinyagentos#519: Introduces the _request_scheme utility function with x-forwarded-proto handling and CSP scheme logic that this PR builds tests and practical application around.

Poem

🐰 I nibble headers in the night,
I hop to choose the proper light,
When proxies hide their TLS,
My tests make schemes confess,
WebSockets now jump safe and bright.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly describes the main fix: enabling copilot ws_url to respect x-forwarded-proto scheme headers.
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.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/copilot-ws-scheme

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/routes/desktop_browser/test_proxy_shell.py`:
- Around line 180-182: The test and implementation currently force an invalid
x-forwarded-proto to "http" which downgrades HTTPS; update the logic in
_request_scheme to use request.url.scheme as the fallback when the
X-Forwarded-Proto header is malformed (instead of hard-coding "http"), and
change the test test_bogus_forwarded_proto_clamped_to_http to assert that
_request_scheme(self._req(xff="javascript", scheme="http" or scheme="https"))
returns request.url.scheme (i.e., the original request.url.scheme), covering
both HTTPS and HTTP cases so malformed headers do not force a downgrade.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4f453d26-2669-4698-884d-2a593232a5d2

📥 Commits

Reviewing files that changed from the base of the PR and between 72f70c3 and 9d52f74.

📒 Files selected for processing (2)
  • tests/routes/desktop_browser/test_proxy_shell.py
  • tinyagentos/routes/desktop_browser/proxy.py

Comment thread tests/routes/desktop_browser/test_proxy_shell.py Outdated
@kilo-code-bot
Copy link
Copy Markdown

kilo-code-bot Bot commented Jun 2, 2026

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (2 files)
  • tests/routes/desktop_browser/test_proxy_shell.py
  • tinyagentos/routes/desktop_browser/proxy.py

Reviewed by nemotron-3-super-120b-a12b-20230311:free · 391,460 tokens

…e, not http

A junk forwarded-proto header on a genuinely HTTPS request was being
clamped to http, downgrading the injected Copilot URL to ws:// and
disabling the HTTPS CSP path. Fall back to request.url.scheme instead.
@jaylfc jaylfc changed the base branch from master to dev June 2, 2026 21:53
@jaylfc jaylfc merged commit e4bc7a1 into dev Jun 2, 2026
7 checks passed
@jaylfc jaylfc deleted the fix/copilot-ws-scheme branch June 2, 2026 22:10
@github-project-automation github-project-automation Bot moved this from Todo to Done in TinyAgentOS Roadmap Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

1 participant