Skip to content

fix(tools): withhold private landing pages from computer use - #7981

Open
sumedh-aerram wants to merge 2 commits into
google:mainfrom
sumedh-aerram:fix/computer-use-navigate-redirect-ssrf
Open

sumedh-aerram wants to merge 2 commits into
google:mainfrom
sumedh-aerram:fix/computer-use-navigate-redirect-ssrf

Conversation

@sumedh-aerram

Copy link
Copy Markdown

Link to Issue or Description of Change

Problem: Initial-URL validation allows browser redirects or page-driven navigation to return private content to the model.

What this does / does not do

Does: Validate returned computer states before exposing screenshots. Confirmed private network or file landings withhold content, close the backend, and disable subsequent actions. Benign blank/desktop, srcdoc, Chrome error, and data states remain usable. Unsupported internal pages and DNS failures withhold that response without disabling recovery. Normalize octal/hex/integer IPv4 aliases in the shared validator, and avoid duplicate cleanup.

Does not: Prevent outbound requests to private addresses; only their content is withheld from the model when the returned state identifies a blocked landing. Blind SSRF, intermediate redirect hops, subresources, WebSockets, DNS rebinding, and URL/screenshot timing races remain. Full prevention requires backend interception or egress enforcement. VMaaS close is a no-op.

Testing Plan

Unit Tests:

  • Final combined computer_use, URL-validator, and load_web_page suites: 249 passed; includes 30 load_web_page compatibility tests.
  • Allowed / latched / withheld-without-latch categories, transient DNS recovery, private DNS, duplicate cleanup, and numeric-host input/landing cases covered.
  • Private-content responses checked for raw and base64-encoded secret pixels.
  • Full unit suite (py311): 22,928 passed; the 15 failures are identical to a fresh upstream/main run (local environment: telemetry/A2A/macOS VMaaS). Expanded tests pass on Python 3.11-3.14.
  • Changed-file pre-commit, including pyink/isort: passed.
  • Mypy on changed files: zero new errors versus upstream/main.

Manual End-to-End (E2E) Tests: Not run; browser results and DNS are mocked. No claim of request interception or live sandbox shutdown.

Checklist

  • Read contribution guidance and performed self-review.
  • Added regression tests; focused new and existing tests pass.
  • Documented security and lifecycle limits.
  • Manually tested end-to-end.
  • Backend interception/egress enforcement completes SSRF prevention.

ComputerUseToolset.navigate validated only the model-supplied URL, so HTTP
redirects, meta refresh, or JavaScript navigation could land the browser on
a private address and return that page's screenshot to the model.

Validate every returned ComputerState with the same URL policy before its
screenshot is exposed. Confirmed private-network or file: landings withhold
the content, close the backend, and disable the toolset. Benign states
(blank, srcdoc, Chrome error, data:) stay usable; unknown internal pages and
DNS failures withhold that response without disabling the toolset. Normalize
octal, hex, and integer IPv4 aliases in the shared URL validator.

This does not prevent outbound requests to private addresses; it only
withholds their content from the model. Full prevention needs request
interception or egress enforcement in the browser backend.

Part of google#7968
@sattyamj-attri

Copy link
Copy Markdown

@sumedh-aerram, one data point for the numeric-host cases, from my own egress guard (agent-airlock 0.10.31).

I ran 0177.0.0.1, 127.1, [::ffff:127.0.0.1] and 0xa9fea9fe against it today. All four are refused, and each decision records the encoding it saw. The IPv4-mapped IPv6 form is the one I'd add to your tests if it isn't there, since the description only names octal, hex, and integer IPv4 aliases.

Also agree with the limit you wrote down: withholding the landing page doesn't stop the request itself.

@sumedh-aerram

Copy link
Copy Markdown
Author

Thanks @sattyamj-attri. All four forms were already refused here: 127.1 and 0xa9fea9fe through the numeric-IPv4 normalization, and [::ffff:127.0.0.1] through the validator's existing IPv4-mapped handling. The landing tests didn't cover the mapped form or the 127.1 shorthand, so I added both in 05db232.

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