anthropics / anthropics/claude-code
claude-in-chrome: an UNGRANTED host makes executeScript-based tools hang their full timeout and blame the page, instead of denying
- 主要语言
- Python
- 星标
- 145k
- 派生
- 23.1k
- PR 合并指标
- PR 指标待抓取
描述
## Summary
An `executeScript`-based browser tool called on a host the extension has **not been granted** does not return a permission error. It **hangs for its full timeout** and reports that the *page* is busy or still loading:
```
Failed to extract page text: Page still loading
(executeScript waited 45000ms for document_idle).
Error capturing screenshot: Script injection timed out after 5000ms —
the page is busy or mid-navigation ...
```
Every clause of that is false. The page is `readyState: "complete"`, the tab is `visibilityState: "visible"`, the connection is healthy, and `javascript_tool` answers instantly on the same tab in the same `browser_batch`.
The message misdirects to three things that are all fine — the page, the connection, and the browser selection — and never mentions permissions. Cost here: two separate multi-hour investigations across two days, both of which concluded "the Chrome connection is unstable."
## Reproduction
Grant the extension a host (e.g. `www.google.com`) and leave another ungranted (e.g. `example.com`). Then, in one tab:
| host | granted | `javascript_tool` | `get_page_text` | `computer` screenshot |
|---|---|---|---|---|
| `www.google.com` | yes | works | **works** | **works** |
| `example.com` | no | works | **45 000 ms timeout** | **5 000 ms timeout** |
Steps:
1. `tabs_context_mcp { createIfEmpty: true }`
2. `navigate` to the **ungranted** host.
3. `javascript_tool` → succeeds, returns the real `document.title`, `readyState: "complete"`, `visibilityState: "visible"`.
4. `get_page_text` on the same tab → hangs 45 s, then reports the page is still loading.
5. `navigate` the same tab to the **granted** host → `get_page_text` and screenshot both succeed immediately.
6. **Control:** navigate the same tab *back* to the ungranted host → fails again immediately.
Step 6 is what makes this a permission fault rather than a transient: the only variable is the host.
## What appears to be happening
There seem to be (at least) three injection paths that fail differently on an ungranted host:
| path | tools | on an ungranted host |
|---|---|---|
| immediate evaluation | `javascript_tool`, `navigate`, `chrome.tabs` reads | **succeeds** |
| `executeScript` at `document_idle` | `get_page_text`, `read_page`, `find`, `computer` screenshot | **hangs to timeout** |
| up-front permission check | `computer` click | **denies immediately, by name** |
A `computer` click on an ungranted domain returns `Permission denied for this action on this domain` — immediate and explicit. So the extension *can* produce a correct denial; the `executeScript` path just doesn't consult the grant before waiting.
A related contrast, same setup: `javascript_tool` is denied immediately and by name on some granted hosts (`Permission denied for JavaScript execution on this domain`). So `javascript_tool` and `executeScript` consult different policies, and only one of them reports failure honestly.
## Why this is worth fixing beyond the message
Chrome resets `runtime_granted_permissions` whenever its HMAC over `extensions.settings` fails to verify — a hard kill of Chrome can cause it. So grants can disappear with nobody having touched them, and the symptom is not "permission denied", it is every page-read and screenshot timing out while navigation keeps working. That reads exactly like a flaky connection.
Inside `browser_batch` it is worse: a 45 s hang blows the tool's response budget, so the batch returns `browser_batch did not respond in time` and the remaining actions are discarded — a third distinct message for the same root cause.
## Expected behaviour
`get_page_text`, `read_page`, `find` and `computer` screenshot should check the host grant **before** waiting for `document_idle`, and return the same immediate, named error that `computer` click already returns — ideally naming the host and pointing at the extension's site-access UI.
Failing that, the timeout message should not assert that the page is loading when the extension has not established that it can inject at all.
## Environment
- macOS 26.6.2 (Apple Silicon)
- Google Chrome 152.0.7977.83
- Claude extension 1.0.91
- Claude Code 2.1.267
- One Chrome install, one profile, extension present in that profile only
贡献指南
这个仓库没有索引到贡献指南
调研方向
Start by tracing the executeScript paths used by get_page_text, read_page, find, and computer screenshot, comparing them with computer click’s permission check. Reproduce on a granted and ungranted host, then verify these tools deny immediately with a named permission error rather than waiting for document_idle or blaming page loading; confirm browser_batch no longer loses remaining actions.
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- javascript
- 领域
- security, tooling
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 活跃
- 描述清晰度
- 基本清楚
- 新手友好度
- 55/100