Medium CVSS 4.3 webkit Cross Origin 🔧 Commit mapped

Overview

Medium
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionA website may exfiltrate image data cross-origin
ComponentWebCore HTML
Bug ClassCross Origin
Tracker297566
Fix commit569f9f075028 (WebKit/WebKit) +72/-8
CWECWE-942
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N
CISA KEVNot listed
CreditedTom Van Goethem
Disclosed2025-11-03

Background

Origin-clean flag / canvas taint
A canvas becomes tainted (origin-clean=false) when it draws cross-origin pixels, which blocks pixel read-back (toDataURL/getImageData).
OffscreenCanvas placeholder
An OffscreenCanvas transferred from a canvas commits its rendered frames back to a visible placeholder HTMLCanvasElement.
setPlaceholderBuffer pipeline
The path (source -> main thread -> placeholder) that hands the rendered ImageBuffer to the visible canvas.
Same-origin policy for canvas
Reading pixels from a tainted canvas is forbidden to prevent cross-origin image exfiltration.

Root Cause Analysis

An OffscreenCanvas can draw a cross-origin image (which taints the canvas, clearing its origin-clean flag) and then transfer its rendered bitmap to a visible placeholder HTMLCanvasElement via commitToPlaceholderCanvas / PlaceholderRenderingContextSource::setPlaceholderBuffer.

Pre-patch, that transfer carried the bitmap and its opaque flag but NOT the origin-clean/tainted status: setPlaceholderBuffer took only (ImageBuffer&, bool opaque), so the output placeholder canvas was left origin-clean even though the pixels came from a tainted OffscreenCanvas. With the destination canvas wrongly considered origin-clean, script could call toDataURL()/getImageData()/toBlob() on it and read back the cross-origin image pixels – a same-origin-policy bypass that exfiltrates cross-origin image data.

The fix threads an originClean boolean through the whole placeholder pipeline (OffscreenCanvas::commitToPlaceholderCanvas passes m_context->canvasBase().originClean(); PlaceholderRenderingContextSource::setPlaceholderBuffer and PlaceholderRenderingContext::setPlaceholderBuffer take and forward it), and the output side applies it: if (originClean) canvasBase().setOriginClean(); else canvasBase().setOriginTainted();.

The restored invariant is that the origin-clean taint of the OffscreenCanvas is preserved when its bitmap is committed to the placeholder canvas, so a tainted source keeps the destination tainted and read-back is blocked.

Key insight
Committing an OffscreenCanvas bitmap to its placeholder canvas failed to carry the origin-clean/tainted flag, so a canvas holding cross-origin pixels was treated as readable; propagating and applying the taint blocks the cross-origin read-back.

Attack Path

  1. Taint an OffscreenCanvas Draw a cross-origin image (no CORS) into an OffscreenCanvas, clearing its origin-clean flag (canvas becomes tainted).
  2. Commit to a placeholder canvas Transfer control / commit the OffscreenCanvas bitmap to a visible HTMLCanvasElement via the placeholder rendering context.
  3. Lose the taint Pre-patch, setPlaceholderBuffer did not carry originClean, so the destination canvas is treated as origin-clean despite holding cross-origin pixels.
  4. Read back cross-origin pixels Call toDataURL()/getImageData() on the destination canvas to exfiltrate the cross-origin image data – an SOP bypass.

Impact Assessment

A same-origin-policy bypass: the OffscreenCanvas taint was dropped when committing to the placeholder canvas, letting script read back cross-origin image pixels (toDataURL/getImageData). It is an information-disclosure primitive with no memory-safety component, in the WebContent process. Rated medium.

Changed Functions

FunctionChangeNotes
OffscreenCanvas::commitToPlaceholderCanvas
Source/WebCore/html/OffscreenCanvas.cpp
modified Passes m_context->canvasBase().originClean() into setPlaceholderBuffer so the taint travels with the bitmap.
PlaceholderRenderingContextSource::setPlaceholderBuffer
Source/WebCore/html/canvas/PlaceholderRenderingContext.cpp
modified Gains an originClean parameter and captures/forwards it through the callOnMainThread hop to the placeholder.
PlaceholderRenderingContext::setPlaceholderBuffer
Source/WebCore/html/canvas/PlaceholderRenderingContext.cpp
modified Applies the flag to the destination: canvasBase().setOriginClean() or setOriginTainted().
PlaceholderRenderingContext(.h) setPlaceholderBuffer decls
Source/WebCore/html/canvas/PlaceholderRenderingContext.h
modified Signatures updated to carry originClean end-to-end.

Files Changed

  • LayoutTests/http/tests/security/offscreen-canvas-remote-read-remote-image-expected.txt
  • LayoutTests/http/tests/security/offscreen-canvas-remote-read-remote-image.html
  • Source/WebCore/html/OffscreenCanvas.cpp
  • Source/WebCore/html/canvas/PlaceholderRenderingContext.cpp
  • Source/WebCore/html/canvas/PlaceholderRenderingContext.h

Audit Directions

  • Other bitmap transfers
    Audit canvas/ImageBitmap transfer paths (transferToImageBitmap, drawImage from canvas, VideoFrame) to ensure origin-clean/taint travels with pixel data.
  • Placeholder pipeline flags
    Review what metadata setPlaceholderBuffer carries (opaque, originClean) for any other security-relevant flag dropped across the main-thread hop.
  • setOriginClean/Tainted callers
    grep for setOriginClean()/setOriginTainted() to confirm every path that copies external pixels into a canvas sets taint correctly.

Original Bug Report

The reporter's bug is still restricted on the tracker.