Skip to content

fix(browser): GET-form search through the proxy (query-clobber)#569

Merged
jaylfc merged 3 commits into
devfrom
fix/browser-proxy-get-forms
Jun 4, 2026
Merged

fix(browser): GET-form search through the proxy (query-clobber)#569
jaylfc merged 3 commits into
devfrom
fix/browser-proxy-get-forms

Conversation

@jaylfc
Copy link
Copy Markdown
Owner

@jaylfc jaylfc commented Jun 4, 2026

Problem

After the POST fix (#566), searching (e.g. Google) returned 422 — profile_id / url required. A GET form submit replaces the action URL's query string with the form's own fields (?q=…), wiping the query-encoded profile_id/url the proxy needs.

Fix

  • Rewriter now owns all <form> actions (split out of the generic href/src pass):
    • GET forms → action set to the bare proxy path, with routing carried as reserved hidden inputs (__taos_pid/__taos_url, prefixed so they can't collide with a site field named url/q) that survive the submit.
    • POST forms → keep the query-encoded proxied action (body carries fields; handled by fix(browser): proxy 405 on form POST (cookie consent, search, login) #566).
  • Proxy route resolves the routing params from query or the reserved fields, then merges the leftover form fields (q=cats) into the target URL. Only the query is touched, so the per-hop SSRF re-check sees the same host.

Tests

4 rewriter cases (GET hidden-inputs, no-method default, POST query action, no-action→current page) + 4 proxy-route cases (merge, preserve existing target query, missing-profile 400, missing-url 400). Targeted suites green.

Note

JS/SPA-driven search submits via fetch() from inside the sandboxed iframe and isn't covered by HTML-form rewriting — that's the real-Chromium escalation tier's job (#567).

Summary by CodeRabbit

  • New Features

    • Desktop proxy now routes form submissions: GET forms are proxied via a fixed proxy path with hidden routing inputs; POST forms keep proxied action info while preserving action query parameters.
    • Form fields submitted alongside routing inputs are merged into the target URL query string.
  • Bug Fixes

    • Request validation now returns HTTP 400 with JSON error details for missing required parameters.
  • Tests

    • Added and expanded tests covering form rewriting, query-parameter merging, preserved target queries, and validation/error responses.

A GET form submit replaces the action's query string with the form's own
fields, wiping the query-encoded profile_id/url and 422-ing the proxy.
Route GET forms via the bare proxy path with routing in reserved hidden
inputs (__taos_pid/__taos_url) that survive the submit; the proxy resolves
those and merges the remaining fields into the target URL (SSRF-revalidated,
host unchanged). POST forms keep the query-encoded action (body carries
fields). Rewriter now owns all <form> actions; _rewrite_attributes does
href/src only. Tests: 4 rewriter + 4 proxy-route cases.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 4, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3a79b7be-28fe-4855-9e36-f5cd31ce2d6b

📥 Commits

Reviewing files that changed from the base of the PR and between 3b75e33 and 30b09b7.

📒 Files selected for processing (3)
  • tests/routes/desktop_browser/test_proxy_post.py
  • 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 (2)
  • tests/routes/desktop_browser/test_proxy_post.py
  • tinyagentos/routes/desktop_browser/proxy.py

📝 Walkthrough

Walkthrough

This pull request routes GET-form submissions through the desktop-browser proxy by rewriting forms to include reserved hidden routing inputs (__taos_pid, __taos_url), updating the proxy to extract/merge non-reserved form fields into the target URL and validate routing inputs, and adding tests for merging, collision handling, and validation behavior.

Changes

GET-form proxy routing

Layer / File(s) Summary
Routing contracts and constants
tinyagentos/routes/desktop_browser/proxy.py, tinyagentos/routes/desktop_browser/rewriter.py
Adds urllib.parse helpers, defines proxy path and reserved hidden-input names (__taos_pid, __taos_url, __taos_tab), and introduces query-merge helper signatures.
HTML form rewriting
tinyagentos/routes/desktop_browser/rewriter.py
Adds _rewrite_forms to rewrite <form> elements: GET forms use the bare proxy path and inject hidden routing inputs (including optional profile_id); POST forms preserve proxied action encoding. Stops rewriting action in the generic attribute pass.
Proxy endpoint routing logic
tinyagentos/routes/desktop_browser/proxy.py
proxy_get now accepts optional profile_id/url, detects GET-form mode via reserved fields, merges non-reserved submitted fields into the target URL with _merge_query_params(), validates routing inputs, and forwards profile_id to rewrite_html.
Tests for rewriting, merging, and validation
tests/routes/desktop_browser/test_proxy_post.py, tests/routes/desktop_browser/test_rewriter.py, tests/routes/desktop_browser/test_proxy_shell.py
Adds TestProxyGetForm tests for field merging, query preservation, missing-parameter 400 responses, and collision handling; adds TestFormRewriting tests for GET/POST form rewrite behavior; updates parameter-validation tests to expect HTTP 400 with missing-field detail; removes the (action, form) case from attribute-rewriting parametization.

Sequence Diagram

sequenceDiagram
  participant Browser
  participant Rewriter
  participant ProxyGET
  participant TargetServer
  Browser->>Rewriter: fetches proxied page (HTML)
  Rewriter->>Browser: returns rewritten HTML with hidden __taos_* inputs for GET forms
  Browser->>ProxyGET: submits form (hidden routing inputs + user fields)
  ProxyGET->>ProxyGET: extract/validate __taos_* or query params
  ProxyGET->>ProxyGET: merge non-reserved user fields into target URL
  ProxyGET->>TargetServer: forward GET to merged target URL
  TargetServer-->>ProxyGET: respond
  ProxyGET-->>Browser: return (possibly rewritten) response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

  • jaylfc/taOS#566: Modifies desktop-browser proxy/form flow and proxy endpoint behavior; directly related at the proxy/form-forwarding level.

Poem

🐇 A rabbit hops, secret fields in tow,
Forms rewritten where the hidden inputs go,
GETs merge fields, POSTs keep their encoded art,
Routing finds its target, never falls apart,
Hooray — the proxy plays its part!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.81% 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 title 'fix(browser): GET-form search through the proxy (query-clobber)' directly references the main change: fixing GET-form submissions through the proxy by addressing query parameter handling, which is the core issue described in the PR objectives.
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/browser-proxy-get-forms

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

🧹 Nitpick comments (1)
tinyagentos/routes/desktop_browser/proxy.py (1)

73-83: ⚡ Quick win

Extract shared routing constants to avoid drift.

The reserved field names (__taos_pid, __taos_url) and proxy path are duplicated between this file and rewriter.py. If one side changes without the other, GET-form routing silently breaks.

Consider extracting to a shared module (e.g., routing_constants.py) that both files import.

🤖 Prompt for 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.

In `@tinyagentos/routes/desktop_browser/proxy.py` around lines 73 - 83, The
reserved GET-form routing constants (_FORM_PID_FIELD, _FORM_URL_FIELD,
_FORM_TAB_FIELD, and _RESERVED_QUERY_KEYS) are duplicated between proxy.py and
rewriter.py; extract these symbols into a new shared module (e.g.,
routing_constants.py) and have both files import them instead of defining them
locally so they cannot drift—create routing_constants.py exporting the four
identifiers, update tinyagentos/routes/desktop_browser/proxy.py to import those
names (remove the local definitions), and update rewriter.py to import the same
names; ensure any references (e.g., usages of _FORM_PID_FIELD, _FORM_URL_FIELD,
_FORM_TAB_FIELD, _RESERVED_QUERY_KEYS) remain unchanged.
🤖 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_post.py`:
- Around line 130-169: Add a regression test ensuring unprefixed site fields
named "url" and "profile_id" are not dropped by the proxy's reserved-key
filtering: create a test (e.g., test_preserves_site_fields_url_and_profile_id)
mirroring the existing GET tests that calls the endpoint
"/api/desktop/browser/proxy" with params including "__taos_pid"/"__taos_url"
plus additional unprefixed "url" and "profile_id" fields, use respx to mock the
upstream target and assert route.calls.last.request.url contains the forwarded
"url" and "profile_id" query values; this verifies behavior around the
_RESERVED_QUERY_KEYS handling in tinyagentos/routes/desktop_browser/proxy.py and
prevents collisions between prefixed hidden fields and real site fields.

---

Nitpick comments:
In `@tinyagentos/routes/desktop_browser/proxy.py`:
- Around line 73-83: The reserved GET-form routing constants (_FORM_PID_FIELD,
_FORM_URL_FIELD, _FORM_TAB_FIELD, and _RESERVED_QUERY_KEYS) are duplicated
between proxy.py and rewriter.py; extract these symbols into a new shared module
(e.g., routing_constants.py) and have both files import them instead of defining
them locally so they cannot drift—create routing_constants.py exporting the four
identifiers, update tinyagentos/routes/desktop_browser/proxy.py to import those
names (remove the local definitions), and update rewriter.py to import the same
names; ensure any references (e.g., usages of _FORM_PID_FIELD, _FORM_URL_FIELD,
_FORM_TAB_FIELD, _RESERVED_QUERY_KEYS) remain unchanged.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: eb1de7f1-83e8-48aa-94b4-f120da91c853

📥 Commits

Reviewing files that changed from the base of the PR and between 435ad81 and 3b75e33.

📒 Files selected for processing (4)
  • tests/routes/desktop_browser/test_proxy_post.py
  • tests/routes/desktop_browser/test_rewriter.py
  • tinyagentos/routes/desktop_browser/proxy.py
  • tinyagentos/routes/desktop_browser/rewriter.py

Comment thread tests/routes/desktop_browser/test_proxy_post.py
jaylfc added 2 commits June 4, 2026 13:03
…lide

Address CodeRabbit: when a GET form submit carries the reserved __taos_*
routing fields, treat ANY plain url/profile_id/tab_id in the query as the
site's own form data (merge into target) instead of consuming them as taOS
routing or stripping them. Direct navigation still uses the plain params.
Drop the now-unused _RESERVED_QUERY_KEYS. Adds a collision regression test
(site form fields literally named url + profile_id are forwarded intact).
The proxy route's profile_id/url are now Optional (to allow the __taos_*
GET-form fallback), so missing routing params return a clear 400 from the
route's own validation rather than FastAPI's generic 422. Update the two
TestParameterValidation cases to the 400 contract + assert the error body.
@jaylfc jaylfc merged commit 141960b into dev Jun 4, 2026
6 checks passed
@jaylfc jaylfc deleted the fix/browser-proxy-get-forms branch June 4, 2026 13:20
@github-project-automation github-project-automation Bot moved this from Todo to Done in TinyAgentOS Roadmap Jun 4, 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