Skip to content

Conversation

@roraja
Copy link

@roraja roraja commented Jun 23, 2025

Summary

This PR adds a complete specification for the clipboardchange event to the W3C Clipboard API specification, including the missing ClipboardChangeEventInit dictionary and enhanced documentation based on implementation experience and the Microsoft Edge explainer.

The bikeshed rendered version can be verified from here:
https://rohanraja.github.io/cr-clipboard/clipboardchange/spec/#clipboard-event-clipboardchange

Changes

Added ClipboardChangeEventInit Dictionary

  • New: ClipboardChangeEventInit dictionary with types sequence parameter
  • Documentation: Clear specification of available mandatory data types on system clipboard
  • Security: Explicit exclusion of custom data types to prevent fingerprinting

Enhanced ClipboardChangeEvent Interface

  • Improved: Detailed documentation for the types attribute behavior
  • Clarified: Event firing conditions and focus requirements
  • Added: Constructor steps algorithm following W3C specification patterns

Implementation Status

Related Documentation

Testing

The specification includes comprehensive examples that can be used for:

  • Web Platform Tests (WPTs) development
  • Cross-browser compatibility validation
  • Security and privacy testing scenarios

Security & Privacy Considerations

  • No permissions required: Event only exposes data types, not contents
  • Fingerprinting mitigation: Custom data types excluded from event payload
  • Focus-gated: Events only fire when document has focus
  • Privacy-preserving: No clipboard contents exposed in event

Contacts: [email protected], [email protected]

Fixes #230

For normative changes, the following tasks have been completed:

  • Editing WG resolution on the proposed changes, with at least two implementers participating and not objecting:
    • WebKit
    • Chromium
    • Gecko

Preview | Diff

@roraja roraja marked this pull request as draft June 23, 2025 05:42
@roraja roraja marked this pull request as ready for review July 8, 2025 04:27
@roraja roraja added the Agenda+ label Aug 12, 2025
index.bs Outdated

3. If <var>document</var> has [=system focus=]:
1. Let <var>types</var> be a list of [=mandatory data types=] available on the [=system clipboard=].
2. Let <var>changeId</var> be a unique identifier for this clipboard change, generated by applying a partition-specific transformation to a system-level clipboard change identifier, ensuring that different [=partitions=] receive different identifiers for the same clipboard change while maintaining consistency within the same [=partition=].
Copy link
Member

Choose a reason for hiding this comment

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

You need to actually obtain the partition somehow. Maybe this should repurpose the storage key?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I would rather opt for pinning this to the appropriate local storage's storage shelf than the key. In this way we would handle the arguably partition-changing event of user deleting site data. Key won't change, but if we for example either

  • put a new UUID within the relevant shelves on each system clipboard change
  • always provide as changeId the hash of some browser-wide changeId against UUID of the shelf itself

the stability of this ID will be bound to the local storage.

Copy link
Member

Choose a reason for hiding this comment

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

I see, you are suggesting the "salt" has storage lifetime? I suppose that's reasonable, though I'm not sure a website would be able to observe either way. Though even if not observable it's probably a better model as we don't really want to expose the storage key outside of the Storage standard if we can avoid it.

Copy link
Collaborator

@zgroza zgroza Sep 12, 2025

Choose a reason for hiding this comment

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

As discussed in the meeting, yes. I too think this is rather a formality and sites most likely wouldn't be able to exploit this, but it's intuitively more consistent with how partitions are observable by the users.

Can we go with the second option—putting a random salt on every shelf?

Copy link
Author

Choose a reason for hiding this comment

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

Updated the spec, thanks for the suggestions.

Copy link
Member

Choose a reason for hiding this comment

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

The Storage Standard doesn't expose "storage shelf" for external usage so that would require new specification API of sorts.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Hm, after thinking about this a bit more—there is a similar problem with the extra permission data of the Web Bluetooth API. There this is handled through a non-normative section with similar recommendations for user agents. Maybe we can do something like that here to avoid overcomplication, potentially with a short normative provision about what not to do?

Then we could just have something like this:

Let changeId be a unique identifier for this clipboard change. User agents MUST NOT deliver the same changeId value to documents associated with different local storage shelves and MUST deliver the exact same changeId value to all documents associated with the same local storage shelf.

and a non-normative section on the privacy recommendations and potential implementations below.

The benefit would also be that this would ensure that the behavior be the same across browsers without forcing implementers to do this in any particular way (ex. hashing against the stored salt, random generation on every dispatch, even maybe hashing against the hardware address of the begin of the local storage shelf, ...).

Copy link
Member

Choose a reason for hiding this comment

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

That seems too hand-wavy to me, but maybe it's okay. And implementers are never forced to do something in a particular way: https://infra.spec.whatwg.org/#algorithm-conformance

Copy link
Author

Choose a reason for hiding this comment

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

I have updated the spec as per this discussion keeping the implementation detail non-normative while keeping the expectation from changeID normative. Would this work ?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Summarizing a bit a TPAC corridor conversation (please correct me if I remember something wrong):

  • Let's re-add the normative algorithm and add hashing of a global changeId against some (possibly user agent internal) binary representation of the storage key (getting the key via obtain-a-storage-key-for-non-storage-purposes)
    • With the planned Client-side Storage Partitioning-related changes in storage key definitions this should be enough to soon also anonymize this across partitions
  • Let's forgo the need for the (partition, origin) identifier to have the lifetime of local storage, as the final changeId will change anyway when:
    • The browser restarts (listeners obviously won't persist this, and every new event relates to a new change and thus will have a new ID)
    • User clears site data (this should trigger refresh of all the relevant tabs, which will cause re-attaching of all the listeners, thus making only the future events with new IDs available)

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add privacy considerations for the clipboardchange event

4 participants