Skip to content

fix(browser): downloads complete over CDP connections#89416

Merged
steipete merged 5 commits into
openclaw:mainfrom
zhangguiping-xydt:feat/issue-48045
Jul 6, 2026
Merged

fix(browser): downloads complete over CDP connections#89416
steipete merged 5 commits into
openclaw:mainfrom
zhangguiping-xydt:feat/issue-48045

Conversation

@zhangguiping-xydt

@zhangguiping-xydt zhangguiping-xydt commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Fixes [Bug]: Browser tool silently discards downloads and throws "Download is starting" error when using CDP connection #48045.
  • Behavior or issue addressed: Browser /navigate attachment responses in Playwright/CDP mode now complete as successful downloads instead of surfacing the navigation abort as a tool failure or dropping the file silently.
  • Why it matters / User impact: CDP-backed browser workflows that navigate directly to CSV/PDF/export URLs can now receive structured download metadata and a saved file, while rejected/private attachment targets cannot leave managed download bytes behind.
  • Intended outcome: allowed attachment navigations return { url, download }; rejected captured download URLs fail before saveAs writes managed bytes.
  • Fix classification: Root Cause.
  • Maintainer-ready confidence: High; the update is limited to the Playwright browser /navigate seam, managed download capture, and focused test-harness support, with RED/GREEN coverage for the ClawSweeper security-boundary finding.
  • What is intentionally out of scope / scope boundary: browser navigation allow/deny policy changes, unrelated Playwright session behavior, non-download navigations, and extensions outside the browser /navigate path.
  • What did NOT change: this does not change public browser API shape beyond the existing additive download result, does not change config, schema, protocol, migration, default behavior, allowlist behavior, or unrelated browser tools.
  • What does success look like: allowed attachment downloads return metadata and saved bytes; rejected captured download URLs reject before persistence; existing non-download navigation behavior remains covered.
  • What should reviewers focus on: the beforeSave ordering between captured download metadata, assertBrowserNavigationResultAllowed, and saveAs.
  • Related open PR scan: this is an existing PR repair for fix(browser): downloads complete over CDP connections #89416 rather than a new competing PR; the current daily-fix scan found fix(browser): downloads complete over CDP connections #89416 as the only author-action PR in the user's open PR set.

Linked context

Closes #48045.

Related: ClawSweeper review on this PR requested blocked attachment-download persistence ordering coverage and targeted validation.

This was requested by ClawSweeper through the status: waiting on author review signal.

Root Cause

  • Root cause: /navigate owned the Playwright page.goto() lifecycle, but attachment downloads caused Playwright to abort navigation with Download is starting or URL-matched net::ERR_ABORTED before navigateViaPlaywright could return useful download metadata.
  • Follow-up root cause from ClawSweeper review: the new capture path saved managed bytes before the captured download URL passed assertBrowserNavigationResultAllowed, so a policy-denied attachment could leave rejected bytes in managed storage.
  • Current author follow-up root cause: the timer-backed download capture promise was only awaited on the download-starting path. Ordinary non-download navigation could cancel the waiter after page.goto() settled, but if the capture timeout rejected first, the rejected promise was left unobserved and surfaced as an unhandled rejection.
  • Why this is root-cause fix: the invariant is that browser navigation policy must approve a target before OpenClaw stores bytes for that target. createManagedDownloadCaptureForPage now accepts a beforeSave hook, builds URL/filename candidate metadata, runs the existing navigation result policy check first, and only calls saveAs after policy approval. The /navigate path passes that hook at the point where it arms the download capture, so allowed downloads still succeed and blocked downloads reject before persistence instead of being cleaned up after the fact. The /navigate path now also observes the armed capture promise immediately, so later download-starting handling still awaits real captured downloads while ordinary non-download success/error paths cannot leave a timed-out waiter rejection unhandled.
  • Patch quality notes: the change does not broaden allowed URLs or change SSRF policy; it only moves the existing result validation ahead of managed persistence for captured navigation downloads. Timeout handling remains bounded by the existing navigation timeout, the catch blocks only distinguish timeout/policy-denial/download-starting cases, and rejected downloads still close the blocked navigation target.

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: Browser /navigate to a Content-Disposition: attachment URL in Playwright/CDP mode returns success download metadata and writes the file instead of failing the tool call.
  • Real environment tested: Local Linux host with real headless Chrome launched through a CDP debugging port, plus a local HTTP server returning Content-Disposition: attachment; filename=proof.txt.
  • Exact steps or command run after this patch: pnpm exec tsx cdp-navigate-download-proof.ts was run from the task worktree against the patched navigateViaPlaywright path.
  • Evidence after fix (screenshot, recording, terminal capture, console output, redacted runtime log, linked artifact, or copied live output): The live CDP proof connected through CDP, called the patched navigateViaPlaywright, received download.triggered: true and suggestedFilename: proof.txt, wrote the managed download bytes, and read back the saved file content.
  • Observed result after fix: The saved file content matched openclaw cdp navigate download proof\n, proving the attachment navigation returned success metadata and wrote the downloaded bytes in a real CDP browser session.
  • What was not tested: Blacksmith Testbox execution was not available locally because the crabbox binary failed its basic --version/--help sanity checks before project checks started.
  • Proof limitations or environment constraints: This live proof covers the allowed attachment download path. The latest ClawSweeper follow-up was about rejected-download persistence ordering, which is covered in the focused regression tests below.
  • Before evidence (optional but encouraged): Before this PR, Playwright surfaced attachment navigation as Download is starting or URL-matched net::ERR_ABORTED, so /navigate returned an error or no download metadata.

Proof continuity after branch update

  • The PR branch was updated through GitHub's Update branch flow after the author repair was pushed. Current PR head dc7704290e7307b9364b870a7144f8991142a3f4 is a merge commit with parents 0b7d58903f5e5c0d63f96a4cb847602b620c98f6 (the submitted browser repair/proof head) and e209a56d0b61e5d6c0b5d53b760e813d9849f85b (current main).
  • The proof-bearing browser repair commits remain in the PR branch history after the update; the Update branch merge did not replace or remove the /navigate download fix, the blocked-download persistence regression, or the capture-timeout unhandled-rejection regression.
  • The original live CDP proof above still applies to the repaired /navigate path because it was run against the submitted repair head and the branch update only merged latest main on top of that repair. The latest main-side update also cleared the unrelated src/agents/model-picker-visibility.ts unused-import blocker that previously prevented a second local submit.
  • Bot label note: proof: sufficient was removed after the head changed, but the PR body still carries the real behavior proof and this section ties that proof to the current Update branch head for the next ClawSweeper/maintainer pass.

Tests and validation

Commands run after the latest patch:

node scripts/run-vitest.mjs extensions/browser/src/browser/pw-tools-core.snapshot.navigate-guard.test.ts -t "handles capture timeouts that win before ordinary navigation settles"
node scripts/run-vitest.mjs extensions/browser/src/browser/pw-tools-core.snapshot.navigate-guard.test.ts extensions/browser/src/browser/pw-session.test.ts extensions/browser/src/browser/pw-tools-core.waits-next-download-saves-it.test.ts
node scripts/run-vitest.mjs extensions/browser/src/browser/pw-session.test.ts -t "validates captured navigation downloads before saving managed bytes"
git diff --check origin/main..HEAD
env OPENCLAW_CHECK_CHANGED_REMOTE_CHILD=1 CI=1 PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN=false pnpm check:changed --timed

Regression coverage added or updated:

  • Target test file: extensions/browser/src/browser/pw-session.test.ts plus the existing /navigate guard files extensions/browser/src/browser/pw-tools-core.snapshot.navigate-guard.test.ts and extensions/browser/src/browser/pw-tools-core.waits-next-download-saves-it.test.ts.
  • Scenario locked in: a captured navigation attachment reports a blocked local URL and the policy hook rejects before persistence. A separate /navigate regression covers a capture timeout winning before ordinary non-download navigation settles, proving the timed-out capture promise is observed rather than reported as an unhandled rejection.
  • Why this is the smallest reliable guardrail: the regression asserts the capture promise rejects with the policy error and saveAs is not called, which directly protects the security-boundary invariant that rejected download bytes cannot enter managed storage without adding a broad end-to-end fixture.
  • extensions/browser/src/browser/pw-session.test.ts adds validates captured navigation downloads before saving managed bytes, which verifies the capture's policy hook runs before saveAs and rejected downloads do not persist managed bytes.
  • extensions/browser/src/browser/pw-tools-core.test-harness.ts mirrors the new beforeSave semantics so existing /navigate tests exercise the same ordering.

What failed before this fix:

FAIL |extension-browser| ../../extensions/browser/src/browser/pw-session.test.ts > pw-session ensurePageState > validates captured navigation downloads before saving managed bytes
AssertionError: promise resolved "{ triggered: true, …(3) }" instead of rejecting

Received: triggered=true, suggestedFilename=export.csv, url=http://127.0.0.1:18080/export.csv, path=[local path redacted]/[uuid]-export.csv

Passing evidence after fix:

RUN  v4.1.7 [local path redacted]

Test Files  1 passed (1)
     Tests  1 passed | 10 skipped (11)
  Duration  33.72s

Test Files  3 passed (3)
     Tests  36 passed (36)
  Duration  39.05s

Test Files  1 passed (1)
     Tests  1 passed | 14 skipped (15)
  Duration  29.46s

Changed-check evidence:

[check:changed] lanes=extensions, extensionTests
[check:changed] summary
   3.05s  ok         conflict markers
   1.62s  ok         changelog attributions
   1.70s  ok         guarded extension wildcard re-exports
   1.47s  ok         plugin-sdk wildcard re-exports
   1.42s  ok         duplicate scan target coverage
   2.31s  ok         dependency pin guard
   2.98s  ok         package patch guard
   203ms  ok         test temp creation report (warning-only)
 104.09s  ok         typecheck extensions
 355.54s  ok         typecheck extension tests
 452.10s  ok         lint extensions
 546.91s  ok         database-first legacy-store guard
   4.33s  ok         media download helper guard
  78.32s  ok         runtime sidecar loader guard
  29.58s  ok         runtime import cycles

Regression Test Plan

  • Target test: extensions/browser/src/browser/pw-session.test.ts / validates captured navigation downloads before saving managed bytes.
  • Regression scenario: a captured navigation attachment reports a blocked local URL and the policy hook rejects before persistence.
  • Expected guardrail: the capture promise rejects with the policy error and saveAs is not called, proving rejected bytes cannot enter managed storage.
  • Additional target tests: extensions/browser/src/browser/pw-tools-core.snapshot.navigate-guard.test.ts, extensions/browser/src/browser/pw-session.test.ts, and extensions/browser/src/browser/pw-tools-core.waits-next-download-saves-it.test.ts cover allowed metadata, URL-matched ERR_ABORTED, no-capture rethrow, save failure propagation, and existing route response behavior.

Risk checklist

Did user-visible behavior change? (Yes/No)

Yes. Browser /navigate can now return download metadata for attachment responses instead of surfacing the Playwright navigation abort.

Did config, environment, or migration behavior change? (Yes/No)

No.

Did security, auth, secrets, network, or tool execution behavior change? (Yes/No)

Yes. This touches browser navigation/download security ordering by ensuring captured download URLs pass the existing navigation policy before managed bytes are saved.

What is the highest-risk area?

Risk labels considered: browser, download-handling, SSRF policy, security-boundary, and the large-diff warning caused mostly by regression/test-harness coverage. The highest risk is weakening the browser SSRF/download boundary by treating a blocked or unrelated aborted navigation as a successful managed download, or by persisting rejected attachment bytes before policy validation.

How is that risk mitigated?

The patch only handles Playwright download-starting errors or URL-matched ERR_ABORTED, requires an armed captured download before returning success, validates the captured download URL through the existing browser navigation policy before saveAs, closes blocked navigation targets on policy denial, and adds a regression proving blocked downloads do not call saveAs. The production scope is limited to pw-session.ts and pw-tools-core.snapshot.ts; the rest of the line count is targeted browser regression coverage and harness support.

Current review state

Next action: maintainer/ClawSweeper review of the updated branch after this author follow-up.

Still waiting on author, maintainer, CI, or external proof:

  • Author-side code and validation work for the visible ClawSweeper findings is addressed in this update, including the capture-timeout unhandled rejection follow-up.
  • The previous remote checks-node-agentic-commands-agent-channel failure was on the old head 286a934bcf5115f52f32037e8ddc95a2ffcf0eaf; this branch has been synced onto current main again after the local repair and needs remote CI to rerun on the pushed head.
  • No new external proof gap is introduced by the follow-up; the original live CDP allowed-download proof remains the real behavior proof, and the latest reviewer request was specifically a blocked-download persistence ordering regression.

Bot or reviewer comments addressed:

  • RF-001 status: waiting on author: addressed by this follow-up update; label removal is maintainer/bot-owned after review.
  • RF-002 Add focused regression for capture timeout winning before page.goto() settles: addressed by handles capture timeouts that win before ordinary navigation settles.
  • RF-004/RF-007 Handle capture timeouts on non-download navigations: addressed by observing the armed capture promise immediately after creation while still awaiting it on the download-starting path.
  • RF-002 Add blocked attachment-download regression proving no rejected file remains in managed storage: addressed by extensions/browser/src/browser/pw-session.test.ts regression that fails before the repair and passes after it.
  • RF-003 Rerun targeted browser vitest files after the repair: addressed; targeted browser vitest passed with 3 files and 35 tests.
  • RF-004 Security-boundary merge risk that successful attachment-download path must not leave rejected bytes in managed storage: addressed by validating the captured download candidate before saveAs and by the no-saveAs regression.
  • RF-005 Queue focused repair for narrow validation/persistence ordering defect: addressed; the code change is limited to managed download capture ordering and /navigate policy wiring.
  • RF-006 Validate blocked downloads before persisting bytes at extensions/browser/src/browser/pw-tools-core.snapshot.ts: addressed by passing beforeSave into createManagedDownloadCaptureForPage from navigateViaPlaywright.
  • RF-007 Run targeted vitest command: addressed; node scripts/run-vitest.mjs extensions/browser/src/browser/pw-tools-core.snapshot.navigate-guard.test.ts extensions/browser/src/browser/pw-session.test.ts extensions/browser/src/browser/pw-tools-core.waits-next-download-saves-it.test.ts passed.
  • RF-008 Targeted browser vitest command: addressed; node scripts/run-vitest.mjs extensions/browser/src/browser/pw-tools-core.snapshot.navigate-guard.test.ts extensions/browser/src/browser/pw-session.test.ts extensions/browser/src/browser/pw-tools-core.waits-next-download-saves-it.test.ts passed.
  • RF-009 Exact captured-download validation command: addressed; node scripts/run-vitest.mjs extensions/browser/src/browser/pw-session.test.ts -t "validates captured navigation downloads before saving managed bytes" passed.
  • RF-010 Run git diff --check origin/main..HEAD: addressed; command passed with exit code 0.
  • RF-011 Run OPENCLAW_CHECK_CHANGED_REMOTE_CHILD=1 CI=1 PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN=false ... check:changed --timed: addressed; command passed with typecheck, lint, and guard summary all ok.

@openclaw-barnacle openclaw-barnacle Bot added size: L proof: supplied External PR includes structured after-fix real behavior proof. labels Jun 2, 2026
@clawsweeper

clawsweeper Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 5, 2026, 9:22 PM ET / 01:22 UTC.

Summary
The PR adds shared Playwright download capture for browser /navigate, returns optional download metadata, validates captured URLs before saving bytes, updates docs/client types, and adds regression coverage.

PR surface: Source +167, Tests +347, Docs +1. Total +515 across 13 files.

Reproducibility: yes. source-reproducible: current main's navigate helper is URL-only and rethrows Playwright's Download is starting abort, and Playwright 1.61.1 source shows Chromium throws that abort when Page.navigate reports a download. I did not run a live CDP browser in this read-only pass.

Review metrics: 2 noteworthy metrics.

  • Navigate response contract: 1 optional field added. The /navigate route spreads helper results into JSON, so maintainers should notice the new nested download payload before merge.
  • Download persistence gate: 1 policy hook before saveAs. The highest-risk behavior is whether policy-denied attachment bytes can enter managed storage; the hook is the intended guardrail.

Stored data model
Persistent data-model change detected: serialized state: extensions/browser/src/browser/pw-session.test.ts, serialized state: extensions/browser/src/browser/pw-tools-core.waits-next-download-saves-it.test.ts, vector/embedding metadata: docs/tools/browser.md, vector/embedding metadata: extensions/browser/src/browser/pw-tools-core.snapshot.navigate-guard.test.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #48045
Summary: This PR is the active fix candidate for the canonical CDP direct browser /navigate attachment-download failure; adjacent download PRs cover different or superseded paths.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • none.

Risk before merge

  • [P1] This intentionally changes the browser navigation/download security boundary; maintainers should confirm that treating Playwright's download-starting abort as success is acceptable only after captured URL policy validation.
  • [P1] The live CDP proof covers the allowed attachment-download path, while the denied-download persistence ordering is covered by focused regression tests rather than a live blocked-download run.

Maintainer options:

  1. Merge after security-boundary approval (recommended)
    Accept the current policy-before-save design once a maintainer confirms the browser download boundary and response contract are intended.
  2. Request one more blocked-download proof
    Ask for a live or artifact-backed denied-download run if maintainers want runtime evidence beyond the focused no-saveAs regression.
  3. Pause for API redesign
    Pause this PR if maintainers prefer a different public /navigate result shape or a lower-level CDP download implementation.

Next step before merge

  • [P2] No narrow automated repair remains; maintainers should review the browser navigation/download security boundary and additive response contract before merge.

Maintainer decision needed

  • Question: Should OpenClaw accept this browser /navigate download contract and the policy-before-save security-boundary handling in this PR?
  • Rationale: The patch appears correct, but it changes how a navigation abort becomes a successful saved download and therefore needs a maintainer to accept the SSRF/download boundary and public response contract.
  • Likely owner: steipete — Best available owner because recent history shows direct work on the browser plugin ownership and managed download path touched here.
  • Options:
    • Accept guarded download capture (recommended): Approve the additive download payload and merge once maintainer review confirms captured URLs are validated before persistence.
    • Ask for live denied-download proof: Require an additional real browser run showing a blocked attachment URL rejects without a managed file before merge.
    • Pause for a different boundary: Hold the PR if maintainers want direct CDP protocol handling or a different browser API contract instead of the current Playwright capture seam.

Security
Cleared: No concrete security or supply-chain defect was found; the diff is security-boundary-sensitive but validates captured download URLs before writing managed bytes.

Review details

Best possible solution:

Land this PR or an equivalent browser-plugin fix after maintainer security-boundary review, preserving policy validation before saveAs and the additive nested download payload.

Do we have a high-confidence way to reproduce the issue?

Yes, source-reproducible: current main's navigate helper is URL-only and rethrows Playwright's Download is starting abort, and Playwright 1.61.1 source shows Chromium throws that abort when Page.navigate reports a download. I did not run a live CDP browser in this read-only pass.

Is this the best way to solve the issue?

Yes. The PR fixes the owner seam around Playwright /navigate, reuses a shared download capture helper for explicit and passive paths, and validates the captured download URL before writing bytes; a route-level special case would be a weaker duplicate path.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 3c2316c43cd2.

Label changes

Label justifications:

  • P2: This is a bounded browser-plugin bug fix for real CDP download workflows with normal backlog priority and no core-runtime outage.
  • merge-risk: 🚨 security-boundary: The PR changes when browser navigation download bytes are saved and relies on URL policy validation before persistence to preserve the SSRF/download boundary.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (live_output): The PR body provides copied live-output proof from a real headless Chrome CDP session showing /navigate returned download metadata and saved/read back the attachment; no contributor action is needed.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body provides copied live-output proof from a real headless Chrome CDP session showing /navigate returned download metadata and saved/read back the attachment; no contributor action is needed.
Evidence reviewed

PR surface:

Source +167, Tests +347, Docs +1. Total +515 across 13 files.

View PR surface stats
Area Files Added Removed Net
Source 7 358 191 +167
Tests 5 349 2 +347
Docs 1 1 0 +1
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 13 708 193 +515

What I checked:

  • Current main gap: Current main types navigateViaPlaywright as URL-only and rethrows non-retryable page.goto errors, so a Playwright download-starting abort still fails the direct navigate path. (extensions/browser/src/browser/pw-tools-core.snapshot.ts:400, 3c2316c43cd2)
  • PR navigate capture: The PR arms passive download capture around guarded navigation, validates captured download URLs before persistence, and returns the nested download payload only when capture succeeds. (extensions/browser/src/browser/pw-tools-core.snapshot.ts:446, c8fc83c22438)
  • Policy-before-save helper: saveBrowserDownload builds candidate metadata, awaits beforeSave, then calls saveAs, which preserves the security invariant that denied download URLs do not write managed bytes. (extensions/browser/src/browser/pw-download-capture.ts:44, c8fc83c22438)
  • Regression coverage: The PR adds a regression that rejects a blocked captured download before saveAs is called, plus navigate tests for download-starting, ERR_ABORTED, timeout, and no-capture cases. (extensions/browser/src/browser/pw-session.test.ts:279, c8fc83c22438)
  • Playwright dependency contract: OpenClaw pins playwright-core 1.61.1, and Playwright's Chromium _navigate throws NavigationAbortedError(..., 'Download is starting') when Page.navigate reports isDownload. (package.json:2017, c8fc83c22438)
  • Linked canonical issue: The open linked issue describes the same CDP direct navigation attachment-download failure and its latest ClawSweeper review identifies this PR as the active fix candidate.

Likely related people:

  • steipete: Peter Steinberger moved browser ownership into the bundled plugin, authored adjacent managed-download work, and contributed the latest refactor/test commits on this PR branch. (role: recent browser plugin area contributor; confidence: high; commits: 8eeb7f082975, 41ed7fa53538, dee088843291; files: extensions/browser/src/browser/pw-session.ts, extensions/browser/src/browser/pw-tools-core.snapshot.ts, extensions/browser/src/browser/pw-tools-core.downloads.ts)
  • pgondhi987: Authored the browser SSRF redirect guard hardening that this download fix must preserve while treating attachment navigations as successful. (role: navigation guard contributor; confidence: medium; commits: 462b4020bc41; files: extensions/browser/src/browser/pw-session.ts, extensions/browser/src/browser/pw-tools-core.snapshot.ts, extensions/browser/src/browser/navigation-guard.ts)
  • vincentkoc: Recent release/current-main history carries the browser navigate and download surfaces, so this is a plausible routing candidate if release inclusion or broad browser ownership questions arise. (role: recent release/current-main integrator; confidence: low; commits: e085fa1a3ffd; files: extensions/browser/src/browser/pw-session.ts, extensions/browser/src/browser/pw-tools-core.snapshot.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (1 earlier review cycle)
  • reviewed 2026-06-25T11:26:15.470Z sha dc77042 :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jun 2, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 8, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jun 8, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 8, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jun 8, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jun 15, 2026
@openclaw-barnacle openclaw-barnacle Bot removed the proof: sufficient ClawSweeper judged the real behavior proof convincing. label Jun 17, 2026
@clawsweeper clawsweeper Bot removed the rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. label Jun 17, 2026
@clawsweeper clawsweeper Bot removed the status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. label Jun 17, 2026
@zhangguiping-xydt

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jun 18, 2026
@zhangguiping-xydt zhangguiping-xydt changed the title fix #48045: [Bug]: Browser tool silently discards downloads and throws "Download is starting" error when using CDP connection fix(browser): downloads complete over CDP connections Jun 22, 2026
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. and removed rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. labels Jun 23, 2026
@steipete
steipete force-pushed the feat/issue-48045 branch from dc77042 to e7af667 Compare July 6, 2026 01:03
@openclaw-barnacle openclaw-barnacle Bot added the docs Improvements or additions to documentation label Jul 6, 2026
@steipete
steipete force-pushed the feat/issue-48045 branch from e7af667 to c8fc83c Compare July 6, 2026 01:07
@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Maintainer verification for exact head c8fc83c2243862c6da91bf13e004724d3da43a06 is complete.

What changed from the submitted fix:

  • Kept direct attachment navigation support, but consolidated navigation, explicit wait/download, explicit click/download, and unobserved page downloads onto one capture/save owner.
  • Added the public typed { url, suggestedFilename, path } result.
  • Preserved sanitized names, atomic root-scoped writes, final-URL policy validation before saveAs, passive/explicit ownership, and latest-waiter-only overlap behavior.
  • Removed roughly 70 net production lines; updated Browser docs.

Automated proof:

  • Sanitized AWS lease cbx_28641474a6c5: public network, no Tailscale, empty instance profile, no hydration; released after proof.
  • AWS run run_c8f167c88061: 5 focused browser files, 60/60 tests, Linux Node 24.15.0, pnpm 11.2.2.
  • AWS run run_37830a97ebf8: pnpm check:changed passed production/test typechecks, extension lint (6,161 files), database-first, media, sidecar, import-cycle, dependency, and repository guards.
  • Hosted CI run 28761433681: complete/success at the exact head.
  • Exact-head macOS pnpm build: passed.
  • Fresh Codex autoreview: clean after fixing and regression-testing its valid unbound-Download.saveAs finding.

Real Gateway/browser-agent proof:

  • Started the exact-head Dev Gateway with OpenAI gpt-5.5 and a Browser-only agent. Run d54d9d85-5a3c-4800-b0ad-5d165b7c8664 made one Browser call to a real local attachment endpoint and returned the expected URL, openclaw-89416-proof.txt, and managed path. The saved file was mode 0600; SHA-256 bd8cae7787dcb4c51e52f58f18e02da873030ce6139b18b147cdb94a169f2cc4 matched the expected bytes.
  • Restarted with strict policy allowing only localhost. Run ef8ea5ed-ab3a-407d-b7ea-a4488a59b622 made one Browser call to localhost, which redirected to disallowed 127.0.0.1; Browser failed closed. Managed downloads stayed at 91 files with identical pre/post digest d650466cb92e142d4a91a3595a74f7f97ed6d14ea1230612c0b74cbfdb491b6a; blocked filename count was zero.
  • Gateway, managed Chrome, proof server, and AWS lease were stopped after verification.

This is the best fix: one maintained capture/persistence path, useful attachment navigation, and no weakening of the network-to-file trust boundary. Ready to land. Thank you, @zhangguiping-xydt.

@steipete
steipete merged commit 7a49b16 into openclaw:main Jul 6, 2026
88 checks passed
@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 6, 2026
* fix(browser): surface navigate downloads in CDP mode

* Validate navigation downloads before saving

* fix(browser): observe navigation download capture timeouts

* refactor(browser): unify managed download capture

* test(browser): satisfy download fixture lint

---------

Co-authored-by: Peter Steinberger <[email protected]>
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
* fix(browser): surface navigate downloads in CDP mode

* Validate navigation downloads before saving

* fix(browser): observe navigation download capture timeouts

* refactor(browser): unify managed download capture

* test(browser): satisfy download fixture lint

---------

Co-authored-by: Peter Steinberger <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: L status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Browser tool silently discards downloads and throws "Download is starting" error when using CDP connection

2 participants