Skip to content

Guard navigator.clipboard in the WebKit clipboard workaround - #334878

Open
Florian Schirmer (joltcoke) wants to merge 1 commit into
microsoft:mainfrom
joltcoke:fix/webkit-clipboard-insecure-context
Open

Guard navigator.clipboard in the WebKit clipboard workaround#334878
Florian Schirmer (joltcoke) wants to merge 1 commit into
microsoft:mainfrom
joltcoke:fix/webkit-clipboard-insecure-context

Conversation

@joltcoke

@joltcoke Florian Schirmer (joltcoke) commented Sep 7, 2026

Copy link
Copy Markdown

BrowserClipboardService.installWebKitWriteTextWorkaround() calls
getActiveWindow().navigator.clipboard.write(...) without checking that the async clipboard API is
there. Outside a secure context — plain http:// on anything but localhostnavigator.clipboard
is undefined, and since the handler is bound to click and keydown on every container, Safari
throws on every click and keystroke:

TypeError: undefined is not an object (evaluating 'getActiveWindow().navigator.clipboard.write')

Every other clipboard access in this very file is already guarded; five of them carry the comment
// Guard access to navigator.clipboard with try/catch. This one is the exception.

Why it is more than noise

The handler assigns this.webKitPendingClipboardWritePromise = currentWritePromise before the
throwing line. writeText() then takes its early exit and never reaches the working fallback:

if (this.webKitPendingClipboardWritePromise) {
    return this.webKitPendingClipboardWritePromise.complete(text);   // stops here
}

this.fallbackWriteText(text);   // execCommand('copy') — never reached

So copying inside the editor silently does nothing on Safari over http, even though
fallbackWriteText() would handle it.

The change

Read navigator.clipboard once and return early when it is absent. That leaves
webKitPendingClipboardWritePromise untouched, so writeText() proceeds to fallbackWriteText()
and copying keeps working. Where the API is present nothing changes; the local binding also removes
a repeated getActiveWindow() lookup.

Reported downstream

microsoft/monaco-editor#4496 describes this exactly, with the same reproduction: serve monaco over
http:// on a LAN address, open it in Safari, type. Open since 2024-05-05 with three independent
confirmations and no maintainer response — reported against monaco-editor, while the code lives
here.

Reproducing

  1. Serve a monaco-based page over http:// on a non-loopback address, so window.isSecureContext
    is false and navigator.clipboard is undefined
  2. Open it in Safari and click into the editor
  3. Every click and keystroke raises the TypeError above; copying does nothing

installWebKitWriteTextWorkaround() called navigator.clipboard.write() without
checking that the async clipboard API exists. Outside a secure context it does
not, and since the handler is bound to click and keydown on every container,
Safari throws on every click and keystroke.

Worse, the handler assigns webKitPendingClipboardWritePromise before the
throwing line, so writeText() takes its early exit and never reaches
fallbackWriteText() - copying silently does nothing although the execCommand
fallback would work.

Reading the clipboard once and returning early when it is absent leaves that
promise untouched, so writeText() falls through to the fallback as intended.
Every other clipboard access in this file is already guarded.
Copilot AI balanced review requested due to automatic review settings September 7, 2026 09:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The guard preserves fallback behavior, with only a non-blocking comment-style nit remaining.

Pull request overview

Guards the WebKit clipboard workaround when navigator.clipboard is unavailable, preserving fallback copying in insecure Safari contexts.

Changes:

  • Checks for the Clipboard API before creating a pending write.
  • Reuses the guarded clipboard reference.
File summaries
File Review
src/vs/platform/clipboard/browser/clipboardService.ts Correctly adds the availability guard. Nit: shorten the three-line method comment to retain only the secure-context constraint.
Review details

Suppressed comments (1)

src/vs/platform/clipboard/browser/clipboardService.ts:94

  • This three-line method-body comment exceeds the one-line limit for inline comments. The control flow already shows that the pending promise remains unset; please keep only the non-obvious secure-context constraint.
			// Guard access to navigator.clipboard, it is only present in a secure context.
			// Returning early leaves `webKitPendingClipboardWritePromise` unset, so `writeText`
			// keeps falling through to `fallbackWriteText` and copying still works.
  • Files reviewed: 1/1 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants