Skip to content

Harden screen snapshot format handling#823

Merged
shanselman merged 1 commit into
openclaw:mainfrom
bkudiess:bkudiess-security-hardening-parity
Jun 26, 2026
Merged

Harden screen snapshot format handling#823
shanselman merged 1 commit into
openclaw:mainfrom
bkudiess:bkudiess-security-hardening-parity

Conversation

@bkudiess

@bkudiess bkudiess commented Jun 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

Harden screen.snapshot format handling before screen capture runs.

  • Validate requested snapshot formats against png, jpeg, and jpg (normalized to jpeg).
  • Reject unsupported formats before invoking the capture backend.
  • Build the response data:image/... MIME type from the validated format instead of the backend echo.
  • Add coverage for unsupported formats, alias normalization, and backend-echo hardening.

Why

screen.snapshot includes a data URI in its response. Previously the requested/echoed format could flow into that MIME type, which could cause MIME confusion or advertise a format that did not match the encoded bytes. This keeps the advertised MIME type aligned with the supported encoder output.

Behavioral proof

Real local proof using an isolated tray instance with the MCP server enabled, invoked through winnode against the live MCP endpoint on port 8766. Base64 image data is redacted.

REAL MCP/WINNODE PROOF (isolated tray, port 8766)
Tray PID: 67880

STEP 1: live MCP tools include screen.snapshot
screen.snapshot advertised:       "name": "screen.snapshot",

STEP 2: unsupported format is rejected by real MCP call
Unsupported screen snapshot format. Supported formats: png, jpeg.

STEP 3: valid png snapshot returns png data URI (redacted)
ok=true
format=png
width=64
height=42
imagePrefix=data:image/png;base64,...
base64Length=3028

This proves the live MCP/winnode path rejects unsupported formats and returns a valid PNG data URI for supported snapshot requests.

Validation

  • ./build.ps1 ✅ all 5 projects
  • dotnet test ./tests/OpenClaw.Shared.Tests/OpenClaw.Shared.Tests.csproj ✅ 2426 passed / 0 failed
  • dotnet test ./tests/OpenClaw.Tray.Tests/OpenClaw.Tray.Tests.csproj ✅ 1163 passed / 0 failed

Review

  • Final rubber-duck review: no blocking, non-blocking, or suggested issues.

@clawsweeper

clawsweeper Bot commented Jun 25, 2026

Copy link
Copy Markdown

Codex review: found issues before merge. Reviewed June 25, 2026, 10:27 PM ET / 02:27 UTC.

Summary
The branch validates and normalizes screen.snapshot formats, derives the response MIME from the normalized format, rejects unsupported formats before capture, and adds shared tests plus test README updates.

Reproducibility: yes. Source inspection shows current main can be exercised by calling screen.snapshot with an unsupported format: the backend writes PNG bytes while the response can advertise the caller-provided format.

Review metrics: 3 noteworthy metrics.

  • Changed surface: 3 files changed; 150 additions, 7 deletions. The runtime change is confined to one shared capability file, with tests and test documentation covering the behavior.
  • Focused coverage: 4 shared tests added. The added tests cover rejection, alias normalization, backend echo hardening, and the format allowlist.
  • Real proof: 1 terminal transcript in PR body. The contributor supplied live MCP/winnode output rather than relying only on unit tests or CI.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🦞 diamond lobster
Patch quality: 🦐 gold shrimp
Result: needs maintainer review before merge.

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

Rank-up moves:

  • [P1] Have maintainers explicitly accept the unsupported-format fail-closed behavior, or revise the patch to preserve PNG fallback while using a trusted MIME value.

Risk before merge

  • [P1] Unsupported snapshot formats such as webp, gif, or svg+xml currently fall through to PNG bytes while reporting the caller/backend format; after this PR they return a structured error, so existing callers outside the documented contract may break at runtime.

Maintainer options:

  1. Accept documented-format enforcement
    Maintainers can merge after explicitly accepting that unsupported snapshot formats now fail with a clear error instead of falling back to PNG bytes.
  2. Preserve invalid-format tolerance
    Revise the patch so invalid requested formats fall back to PNG while the response MIME still comes from a trusted normalized encoder value.
  3. Pause for API contract confirmation
    Keep the PR open if snapshot format behavior needs a broader node/MCP compatibility decision first.

Next step before merge

  • [P1] Maintainer review should decide whether unsupported snapshot formats may fail closed; automation should not choose the API compatibility contract.

Security
Cleared: The diff narrows accepted snapshot formats and removes backend-controlled MIME construction without adding dependency, workflow, secret, or supply-chain surface.

Review findings

  • [P1] Preserve invalid-format tolerance until maintainers accept the break — src/OpenClaw.Shared/Capabilities/ScreenCapability.cs:54
Review details

Best possible solution:

Land the MIME hardening once maintainers explicitly choose the unsupported-format API behavior; keep png/jpeg as the documented contract and prevent MIME construction from untrusted backend or caller values.

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

Yes. Source inspection shows current main can be exercised by calling screen.snapshot with an unsupported format: the backend writes PNG bytes while the response can advertise the caller-provided format.

Is this the best way to solve the issue?

Mostly yes, with one maintainer compatibility check. Validating png/jpeg, normalizing jpg, and deriving MIME from the trusted normalized value is narrow, but fail-closed unsupported-format behavior should be accepted explicitly.

Full review comments:

  • [P1] Preserve invalid-format tolerance until maintainers accept the break — src/OpenClaw.Shared/Capabilities/ScreenCapability.cs:54
    This new error path makes callers that currently pass unsupported values fail before capture, where main currently falls through to PNG bytes and echoes the requested format. If maintainers have not explicitly accepted that API break, keep fallback behavior while deriving the response MIME from a trusted normalized encoder value.
    Confidence: 0.84

Overall correctness: patch is incorrect
Overall confidence: 0.86

AGENTS.md: found and applied where relevant.

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

Label changes

Label changes:

  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • add status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (terminal): The PR body contains terminal proof from an isolated tray/MCP winnode run showing unsupported-format rejection and a successful PNG data URI response with image data redacted.
  • remove rating: 🐚 platinum hermit: Current PR rating is rating: 🦐 gold shrimp, so this older rating label is no longer current.
  • remove status: 👀 ready for maintainer look: Current PR status label is status: ⏳ waiting on author.

Label justifications:

  • P2: This is a focused screen snapshot hardening fix with limited blast radius but user-visible node/MCP behavior.
  • merge-risk: 🚨 compatibility: The PR intentionally changes unsupported snapshot formats from accidental PNG fallback to a structured error.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (terminal): The PR body contains terminal proof from an isolated tray/MCP winnode run showing unsupported-format rejection and a successful PNG data URI response with image data redacted.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body contains terminal proof from an isolated tray/MCP winnode run showing unsupported-format rejection and a successful PNG data URI response with image data redacted.
Evidence reviewed

What I checked:

Likely related people:

  • shanselman: GitHub path history shows the Windows node mode and screen capability work, screen recording parity, and related screen backend changes were authored or carried by this person. (role: introduced screen capability and recent area owner; confidence: high; commits: e3eeef33672d, c1296be7fd43, dba534250cd7; files: src/OpenClaw.Shared/Capabilities/ScreenCapability.cs, src/OpenClaw.Tray.WinUI/Services/ScreenCaptureService.cs)
  • codemonkeychris: Recent history shows local MCP capability-boundary hardening and WinNode CLI tool documentation work touching the MCP-visible surface this PR changes. (role: adjacent MCP and winnode contributor; confidence: medium; commits: 353a4b9a5356, 3b8793db3702; files: src/OpenClaw.Shared/Capabilities/ScreenCapability.cs, src/OpenClaw.Shared/Mcp/McpToolBridge.cs, src/OpenClaw.WinNode.Cli/skill.md)
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.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. labels Jun 25, 2026
@bkudiess

Copy link
Copy Markdown
Collaborator Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 25, 2026

Copy link
Copy Markdown

🦞🧹
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 Contributor real behavior proof is sufficient. 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: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 25, 2026
@bkudiess bkudiess marked this pull request as ready for review June 25, 2026 23:16
Validate screen.snapshot image formats before invoking the capture backend, normalize jpg to jpeg, and derive the response data URI MIME type from the validated format instead of the backend echo.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@shanselman shanselman force-pushed the bkudiess-security-hardening-parity branch from 1aa5f3e to 4e074a1 Compare June 26, 2026 02:24
@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. 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 26, 2026
@shanselman shanselman merged commit 9447c0f into openclaw:main Jun 26, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants