Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 149 additions & 40 deletions index.src.html
Original file line number Diff line number Diff line change
Expand Up @@ -1857,6 +1857,12 @@

5. Otherwise, return false.

NOTE: To reduce fingerprinting entropy, User Agents can limit the configurations
they provide to a common baseline subset (including codec-specific
extensions in [[WEBCODECS-CODEC-REGISTRY]]). Because both
`isConfigSupported()` and `configure()` invoke this algorithm, both reflect
the same supported set. See [[#privacy-capability-fingerprinting]].

<dfn>Clone Configuration</dfn> (with |config|) {#clone-config}
--------------------------------------------------------------

Expand Down Expand Up @@ -6333,46 +6339,149 @@
<div class=non-normative>
This section is non-normative.

The primary privacy impact is an increased ability to fingerprint users by
querying for different codec capabilities to establish a codec feature profile.
Much of this profile is already exposed by existing APIs. Such profiles are very
unlikely to be uniquely identifying, but can be used with other metrics to
create a fingerprint.

An attacker can accumulate a codec feature profile by calling
`IsConfigSupported()` methods with a number of different configuration
dictionaries. Similarly, an attacker can attempt to `configure()` a codec with
different configuration dictionaries and observe which configurations are
accepted.

Attackers can also use existing APIs to establish much of the codec feature
profile. For example, the [[media-capabilities]] {{decodingInfo()}} API
describes what types of decoders are supported and its {{powerEfficient}}
attribute can signal when a decoder uses hardware acceleration. Similarly, the
[[WebRTC]] {{RTCRtpSender/getCapabilities()}} API can be used to determine what
types of encoders are supported and the {{RTCPeerConnection/getStats()}} API can
be used to determine when an encoder uses hardware acceleration. WebCodecs will
expose some additional information in the form of low level codec features.

A codec feature profile alone is unlikely to be uniquely identifying. Underlying
codecs are often implemented entirely in software (be it part of the User Agent
binary or part of the operating system), such that all users who run that
software will have a common set of capabilities. Additionally, underlying codecs
are often implemented with hardware acceleration, but such hardware is mass
produced and devices of a particular class and manufacture date (e.g. flagship
phones manufactured in 2020) will often have common capabilities. There will be
outliers (some users can be running outdated versions of software codecs or use
a rare mix of custom assembled hardware), but most of the time a given codec
feature profile is shared by a large group of users.

Segmenting groups of users by codec feature profile still amounts to a bit of
entropy that can be combined with other metrics to uniquely identify a user.
User Agents <em class="rfc2119">MAY</em> partially mitigate this by returning an
error whenever a site attempts to exhaustively probe for codec capabilities.
Additionally, User Agents <em class="rfc2119">MAY</em> implement a "privacy
budget", which depletes as authors use WebCodecs and other identifying APIs.
Upon exhaustion of the privacy budget, codec capabilities could be reduced to a
common baseline or prompt for user approval.
The primary privacy impact of WebCodecs is an increased surface for
fingerprinting a user's device and observing hardware characteristics through
three main vectors: probing supported codec configurations, inspecting encoded
or decoded output bytes, and measuring codec timing or resource limits. While
similar signals are partially exposed by higher-level media APIs, WebCodecs
provides more direct, lower-level access that makes collecting these signals
easier.
</div>

Codec Capability Fingerprinting{#privacy-capability-fingerprinting}
-------------------------------------------------------------------

<div class=non-normative>
A site can accumulate a codec feature profile by calling
{{AudioDecoder/isConfigSupported()|AudioDecoder.isConfigSupported()}},
{{VideoDecoder/isConfigSupported()|VideoDecoder.isConfigSupported()}},
{{AudioEncoder/isConfigSupported()|AudioEncoder.isConfigSupported()}}, or
{{VideoEncoder/isConfigSupported()|VideoEncoder.isConfigSupported()}} with
various configuration dictionaries (including codec-specific dictionary
extensions defined in specifications listed in the [[WEBCODECS-CODEC-REGISTRY]]),
or by calling {{ImageDecoder/isTypeSupported()|ImageDecoder.isTypeSupported()}}
with various MIME type strings. Similarly, a site can pass different
configuration dictionaries to `configure()` or different MIME type strings to
the {{ImageDecoder}} constructor and observe whether the codec asynchronously
fails with {{NotSupportedError}} (via the error callback or rejected
{{ImageTrackList/ready|tracks.ready}} and
{{ImageDecoder/decode()|ImageDecoder.decode()}} promises).

Much of a device's codec feature profile is already exposed by existing APIs.
For example, the [[media-capabilities]] {{decodingInfo()}} and
{{encodingInfo()}} APIs describe supported codec configurations and their
{{powerEfficient}} attribute can indicate hardware acceleration, while the
[[WebRTC]] {{RTCRtpSender/getCapabilities()}} API reveals supported codec
profiles (and {{RTCPeerConnection/getStats()}} in [[WEBRTC-STATS]] exposes
hardware implementation details in capturing contexts). Beyond what those APIs
already reveal, WebCodecs mainly adds low-level configuration parameters (such
as specific pixel formats, bitrate modes, or codec-specific options).

Whether a codec feature profile helps distinguish a device depends on how the
underlying codecs are provided. Codecs bundled directly with the User Agent
binary generally expose uniform capabilities across users of the same User Agent
version and CPU architecture, whereas codecs provided by the operating system or
backed by dedicated hardware vary across operating system versions, GPU models,
and driver versions. Although mass-produced device classes (e.g. phones or
laptops of the same model generation) often share identical profiles, devices
with uncommon hardware combinations, driver versions, or operating system
configurations stand out as outliers. Even when shared by a group of users, a
codec feature profile contributes entropy that can be combined with other
signals to fingerprint a user.

As specified in [[#hardware-acceleration]], {{HardwareAcceleration}} values are
hints that User Agents can ignore for reasons of user privacy, and acceptance or
rejection of a {{HardwareAcceleration}} preference is constrained so that it
reveals no additional information beyond what is already exposed by
[[media-capabilities]] (or is expected to be ignored when [[media-capabilities]]
is omitted to prevent fingerprinting).

User Agents can further mitigate capability fingerprinting by exposing only a
common baseline subset of supported capabilities across devices, similar to
[[media-capabilities]], or by throttling or reporting configurations as
unsupported when a site attempts to exhaustively probe configurations. Baseline
restrictions apply equally to core configuration members and to codec-specific
extensions defined in the [[WEBCODECS-CODEC-REGISTRY]], and need to be applied
consistently across `isConfigSupported()` and `configure()` so that
`configure()` cannot be used as a fallback probing oracle.
</div>

Codec Output Fingerprinting{#privacy-output-fingerprinting}
-----------------------------------------------------------

<div class=non-normative>
Processing identical inputs on different devices, even with the same User Agent
version, can produce different output bytes:

* For encoding, compressed bitstreams vary across hardware encoders, GPU
drivers, operating system media frameworks, software encoder rate-control
and motion-estimation heuristics, and CPU-architecture-specific
optimizations.
* For decoding, conforming decoders for modern video codecs (such as AVC, HEVC,
VP8, VP9, and AV1) produce bit-exact reconstructed YUV samples in their
native format, so video decode differences arise primarily from output frame
format and alignment metadata (e.g. {{VideoFrame/format|VideoFrame.format}},
{{VideoFrame/codedWidth|VideoFrame.codedWidth}},
{{VideoFrame/codedHeight|VideoFrame.codedHeight}}, and
{{VideoFrame/colorSpace|VideoFrame.colorSpace}}) and from post-decode pixel
format or color space conversions (such as during
{{VideoFrame/copyTo()|VideoFrame.copyTo()}}). Decode outputs can also differ
directly when using codecs whose specifications do not mandate
bit-exactness, such as floating-point audio decoders (e.g. MP3, AAC, Vorbis,
and Opus) or image decoders in {{ImageDecoder}} (e.g. JPEG inverse DCT
implementations, scaling via {{ImageDecoderInit/desiredWidth}} and
{{ImageDecoderInit/desiredHeight}}, and platform color management).

Because User Agents share the same underlying codecs across WebCodecs,
[[WebRTC]], [[MEDIASTREAM-RECORDING]], {{HTMLMediaElement}} with `<canvas>`,
and [[WEBAUDIO]], the output bytes accessible via
{{EncodedAudioChunk/copyTo()|EncodedAudioChunk.copyTo()}},
{{EncodedVideoChunk/copyTo()|EncodedVideoChunk.copyTo()}},
{{AudioData/copyTo()|AudioData.copyTo()}}, and
{{VideoFrame/copyTo()|VideoFrame.copyTo()}} reflect the same implementation
characteristics that are already observable through those existing APIs.
Moreover, codec outputs are consistent across large cohorts of users with the
same device class, operating system, or User Agent build rather than being
unique to an individual user.

In heightened privacy modes, User Agents can substantially reduce hardware- and
driver-specific output variation by ignoring {{HardwareAcceleration}}
preferences and routing operations to a bundled software codec implementation
where available, producing uniform output across devices that share the same
User Agent build and CPU architecture. Selecting a consistent software codec
avoids the compression efficiency, visual quality, and lossless-workflow
tradeoffs that would come from injecting synthetic noise into encoder inputs or
decoder outputs.
</div>

Timing and Resource Side-Channels{#privacy-timing-side-channels}
----------------------------------------------------------------

<div class=non-normative>
Measuring the latency and throughput of `encode()`, `decode()`, and `flush()`
operations (particularly in combination with {{HardwareAcceleration}}
preferences) allows a site to profile the performance characteristics of the
user's CPU and GPU hardware. Although timing measurements are already possible
through {{MediaSource}}, [[MEDIASTREAM-RECORDING]], and [[WebRTC]], frame-level
submission and output callbacks in WebCodecs make fine-grained timing
observation more direct.

Additionally, observing dynamic resource limits can leak information about the
underlying hardware or concurrent activity on the user's device. For example,
retaining {{VideoFrame}} instances until decoding stalls can reveal hardware or
driver buffer pool sizes. Similarly, concurrent media usage in other
applications or tabs (such as an active video call) can be inferred if hardware
codec instances are exhausted during new configuration attempts, or by
[=inactive=] or [=background=] codecs observing [=reclaim a codec|codec
reclamation=] ({{QuotaExceededError}}, see [[#resource-reclamation]]).

User Agents can mitigate timing and resource side-channels by ignoring
{{HardwareAcceleration}} preferences, silently falling back to software codecs
where available when hardware codec instances are exhausted, coarsening
completion timing to limit fine-grained per-frame latency side-channels, pacing
or throttling excessive or background codec operations to limit aggregate
throughput profiling and background monitoring, and normalizing or virtualizing
buffer pool limits across devices.
</div>

Best Practices for Authors Using WebCodecs{#best-practices-developers}
Expand Down
Loading