Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spec: Pose privacy considerations #761

Merged
merged 7 commits into from
Jul 22, 2019
Merged
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
121 changes: 103 additions & 18 deletions index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -322,9 +322,11 @@ When the <dfn method for="XR">requestSession(|mode|, |options|)</dfn> method is
1. Let |promise| be [=a new Promise=].
1. Let |immersive| be <code>true</code> if |mode| is {{XRSessionMode/"immersive-vr"}} or {{XRSessionMode/"immersive-ar"}}, and <code>false</code> otherwise.
1. If |immersive| is <code>true</code>:
1. If the algorithm is not [=triggered by user activation=], [=reject=] |promise| with a "{{SecurityError}}" {{DOMException}} and return |promise|.
1. Check if an [=immersive session request is allowed=], and if not [=reject=] |promise| with a "{{SecurityError}}" {{DOMException}} and return |promise|.
1. If [=pending immersive session=] is <code>true</code> or [=active immersive session=] is not <code>null</code>, [=reject=] |promise| with an "{{InvalidStateError}}" {{DOMException}} and return |promise|.
1. Set [=pending immersive session=] to <code>true</code>.
1. If |immersive| is <code>false</code>:
1. Check if an [=inline session request is allowed=], and if not [=reject=] |promise| with a "{{SecurityError}}" {{DOMException}} and return |promise|.
1. Run the following steps [=in parallel=]:
1. Choose |device| based on the following:
<dl class="switch">
Expand Down Expand Up @@ -440,6 +442,8 @@ Some {{XRSessionMode}}s enable certain [=feature names=] as [=optional features=
</tbody>
</table>

The combined list of [=feature names=] given by the {{XRSessionInit/requiredFeatures}}, {{XRSessionInit/optionalFeatures}}, and [=default features=] are collectively considered the <dfn>requested features</dfn> for an {{XRSession}}.

<div class="algorithm" data-algorithm="resolve-features">

To <dfn>resolve the requested features</dfn> given |requiredFeatures| and |optionalFeatures| for an {{XRSession}} |session|, the user agent MUST run the following steps:
Expand Down Expand Up @@ -964,6 +968,7 @@ To <dfn>populate the pose</dfn> of an {{XRSpace}} |space| in an {{XRSpace}} |bas
1. Let |session| be |frame|'s {{XRFrame/session}} object.
1. If |space|'s [=XRSpace/session=] does not equal |session|, throw an {{InvalidStateError}} and abort these steps.
1. If |baseSpace|'s [=XRSpace/session=] does not equal |session|, throw an {{InvalidStateError}} and abort these steps.
1. Check if [=poses may be reported=] and, if not, throw a {{SecurityError}} and abort these steps.
1. Let |transform| be |pose|'s {{XRPose/transform}}.
1. Query the [=/XR device=]'s tracking system for |space|'s pose relative to |baseSpace| at the time represented by |frame|, then perform the following steps:
<dl class="switch">
Expand Down Expand Up @@ -2108,29 +2113,29 @@ Sensitive Information {#sensitive-information-header}

In the context of XR, <dfn>sensitive information</dfn> includes, but is not limited to, user configurable data such as interpupillary distance (IPD) and sensor-based data such as {{XRPose}}s. All {{XRSessionMode/"immersive-vr"}} and {{XRSessionMode/"immersive-ar"}} sessions will expose some amount of sensitive data, due to the user's pose being necessary to render anything. However, in some cases, the same sensitive information will also be exposed via {{XRSessionMode/"inline"}} sessions.

### Trustworthy documents and origins ### {#trustworthy-documents}
In order to expose any [=sensitive information=] the requesting document MUST be considered [=trustworthy=].
### Active and focused document ### {#active-and-focused-document}
A document MUST be [=active and focused=] at the time that [=sensitive information=] is requested.

<div class="algorithm" data-algorithm="document-is-trustworthy">
<div class="algorithm" data-algorithm="document-is-active-and-focused">

To determine if a given {{Document}} |document| is <dfn>trustworthy</dfn> the user agent MUST run the following steps:
To determine if a given {{Document}} |document| is <dfn>active and focused</dfn> the user agent MUST run the following steps:

1. If |document| is not a [=responsible=] document, return <code>false</code>
1. If |document| is not of a [=secure context=], return <code>false</code>
1. If |document|'s origin is blocked by [[#feature-policy|feature policy]], return <code>false</code>
1. If the [=currently focused area=] does not belong to |document|, return <code>false</code>
1. If |document| is not of the [=same origin-domain=] as the [=active document=], return <code>false</code>
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if there's an unintended implication of this requirement on desktop VR. For example, if you've got a page with two iframes on it of different origins and one of them has an active immersive session (i.e. user activation happened and the iframe had the right feature policy). If you've got someone in the headset viewing it and someone sitting next to them at the computer with the mouse... what happens if the person with the mouse clicks on the iframe with the different origin?

I'm guessing this requirement was originally about inline sessions, so we might just need to tweak the language a bit to accommodate this.

Also this may be related to #696 and #747

Copy link
Contributor

Choose a reason for hiding this comment

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

A primary consideration of this requirement is input sniffing. I could imagine a scenario where a user in an immersive session was presented with an OS-level virtual keyboard or notification input (possibly in response to an event triggered by a different origin).

Copy link
Member

Choose a reason for hiding this comment

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

@johnpallett I'm not sure we're talking about the same thing? In that case, wouldn't the previous bullet be the one that cause the algorithm to return false?

1. Return <code>true</code>

</div>

### Active and focused document ### {#active-and-focused-document}
In addition to being [=trustworthy=], a document MUST be [=active and focused=] at the time that [=sensitive information=] is requested.
### Trustworthy documents and origins ### {#trustworthy-documents}
In order to expose any [=sensitive information=] the requesting document MUST be considered [=trustworthy=].

<div class="algorithm" data-algorithm="document-is-active-and-focused">
<div class="algorithm" data-algorithm="document-is-trustworthy">

To determine if a given {{Document}} |document| is <dfn>active and focused</dfn> the user agent MUST run the following steps:
To determine if a given {{Document}} |document| is <dfn>trustworthy</dfn> the user agent MUST run the following steps:

1. If the [=currently focused area=] does not belong to |document|, return <code>false</code>
1. If |document| is not of the [=same origin-domain=] as the [=active document=], return <code>false</code>
1. If |document| is not a [=responsible=] document, return <code>false</code>
1. If |document| is not [=active and focused=], return <code>false</code>
1. If |document|'s origin is not allowed to use the WebXR [[#feature-policy|feature policy]], return <code>false</code>
1. Return <code>true</code>

</div>
Expand All @@ -2141,10 +2146,13 @@ User intention {#user-intention}
It is often necessary to be sure of <dfn>user intent</dfn> before exposing sensitive information or allowing actions with a significant effect on the user's experience. This intent may be communicated or observed in a number of ways.

### User activation ### {#user-activation}
Events which are [=triggered by user activation=] can serve as an indication of [=user intent=] in some scenarios.
Events which are [=triggered by user activation=] MAY serve as an indication of [=user intent=] in some scenarios.

### Launching a web application ### {#application-launch}
In some environments a page may be presented as an application, installed with the express intent of running immersive content. In that case <dfn>launching a web application</dfn> MAY also serve as an indication of [=user intent=].

### Implicit and Explicit consent ### {#user-consent}
A user agent may use <dfn>implicit consent</dfn> based, for example, on the install status of a web application or frequency and recency of visits. Given the sensitivity of XR data, caution is strongly advised when relying on implicit signals.
A user agent MAY use <dfn>implicit consent</dfn> based, for example, on the install status of a web application or frequency and recency of visits. Given the sensitivity of XR data, caution is strongly advised when relying on implicit signals.

It is often useful to get <dfn>explicit consent</dfn> from the user before exposing [=sensitive information=]. When gathering explicit user consent, user agents present an explanation of what is being requested and provide users the option to decline. Requests for user consent can be presented in many visual forms based on the features being protected and user agent choice.

Expand All @@ -2160,6 +2168,85 @@ There are multiple non-XR APIs which cause user agents to request [=explicit con

Note: This limitation is to ensure that there is behavioral parity between all user agents until consensus is reached about how user agents should manage mid-session [=explicit consent=]. It is not expected to be a long term requirement.

Data adjustments {#data-adjustments-header}
----------------

In some cases, security and privacy threats can be mitigated through <dfn>data adjustment</dfn>s such as throttling, quantizing, rounding, limiting, or otherwise manipulating the data reported from the [=/XR device=]. This may sometimes be necessary to avoid fingerprinting, even in situations when [=user intent=] has been established. However, [=data adjustment=] mitigations MUST only be used in situations which would not result in user discomfort.

### Throttling ### {#throttling}
Throttling is when [=sensitive information=] is reported at a lower frequency than otherwise possible. This mitigation has the potential to reduce a site's ability to infer user intent, infer location, or perform user profiling. However, when not used appropriately throttling runs a significant risk of causing user discomfort. In addition, under many circumstances it may be inadequate to provide a complete mitigation.

### Rounding, quantization, and fuzzing ### {#rounding-and-friends}
Rounding, quantization, and fuzzing are three categories of mitigations that modify the raw data that would otherwise be returned to the developer. Rounding decreases the precision of data by reducing the number of digits used to express it. Quantization constrains continuous data to instead report a discrete subset of values. Fuzzing is the introduction of slight, random errors into the the data. Collectively, these mitigations are useful to avoid fingerprinting, and are especially useful when doing so does not cause noticeable impact on user comfort.

### Limiting ### {#limiting}
Limiting is when data is reported only when it is within a specific range. For example, it is possible to comfortably limit reporting positional pose data when a user has moved beyond a specific distance away from an approved location. Care should be taken to ensure that the user experience is not negatively affected when employing this mitigation. It is often desireable to avoid a 'hard stop' at the at the end of a range as this may cause disruptive user experiences.

Protected functionality {#protected-functionality}
-----------------------

The [=sensitive information=] exposed by the API can be divided into categories that share threat profiles and necessary protections against those threats.

### Immersiveness ### {#protect-immersiveness}
Users must be in control of when immersive sessions are created because the creation causes invasive changes on a user's machine. For example, starting an [=immersive session=] will engage the [=/XR device=] sensors, take over access to the device's display, and begin presentating immersive content which may terminate another application's access to the XR hardware. It may also incur significant power or performance overhead on some systems or trigger the launching of a status tray or storefront.

<div class="algorithm" data-algorithm="immersive-session-allowed">

To determine if an <dfn>immersive session request is allowed</dfn> the user agent MUST run the following steps:

1. If the request was not [=triggered by user activation=] or [=launching a web application=], return <code>false</code>
1. If the requesting document is not considered [=trustworthy=], return <code>false</code>
1. If [=user intent=] to begin an [=immersive session=] is not well understood, either via [=explicit consent=] or [=implicit consent=], return <code>false</code>
1. Return <code>true</code>

</div>

Starting an {{XRSessionMode/"inline"}} session does not implicitly carry the same requirements, though additional requirements may be imposed depending on the session's [=requested features=].

<div class="algorithm" data-algorithm="inline-session-allowed">

To determine if an <dfn>inline session request is allowed</dfn> the user agent MUST run the following steps:

1. If the session request contained any [=required features=] or [=optional features=] and the request was not [=triggered by user activation=] or [=launching a web application=], return <code>false</code>
1. If the requesting document is not [=responsible=], return <code>false</code>
1. If requesting document's origin is not allowed to use the WebXR [[#feature-policy|feature policy]] return <code>false</code>
1. Return <code>true</code>

</div>

### Poses ### {#protect-poses}
When based on sensor data, {{XRPose}} and {{XRViewerPose}} will expose [=sensitive information=] that may be misused in a number of ways, including input sniffing, gaze tracking, or fingerprinting.

<div class="algorithm" data-algorithm="poses-allowed">

To determine if <dfn>poses may be reported</dfn> to an {{XRSession}} |session|, the user agent MUST run the following steps:

1. Let |document| be the document that owns |session|.
1. If the request does not originate from |document|, return <code>false</code>.
1. If |document| is not [=active and focused=], return <code>false</code>.
1. If |session|'s {{XRSession/visibilityState}} in not {{XRVisibilityState/"visible"}}, return <code>false</code>.
1. Determine if the pose data can be returned as follows:
<dl class="switch">
<dt> If the pose data is known by the user agent to not expose fingerprintable sensor data
<dd> Return <code>true</code>.
<dt> If [=data adjustments=] will be applied to the underlying sensor data to prevent fingerprinting or profiling
<dd> Return <code>true</code>.
<dt> If [=user intent=] is well understood, either via [=explicit consent=] or [=implicit consent=]
<dd> Return <code>true</code>.
<dt> Otherwise
<dd> Return <code>false</code>.
</dl>

</div>

Note: The method by which a user agent determines that poses do not expose fingerprintable data is left to the user agent's discretion.

The primary difference between {{XRViewerPose}} and {{XRPose}} is the inclusion of {{XRView}} information. When more than one view is present and the physical relationship between these views is configurable by the user, the relationship between these views is considered [=sensitive information=] as it can be used to fingerprint or profile the user.

If the relationship between {{XRView}}s could uniquely identify the [=/XR device=], then the user agent MUST anonymize the {{XRView}} data to prevent fingerprinting. The method of anonymization is at the discretion of the user agent.

Note: Furthermore, if the relationship between {{XRView}}s is affected by a user-configured interpupillary distance, then it is strongly recommended that the user agent require [=explicit consent=] during session creation, prior to reporting any {{XRView}} data.

<section class="unstable">
Gaze Tracking {#gazetracking-security}
-------------
Expand Down Expand Up @@ -2204,8 +2291,6 @@ The feature identifier for this feature is <code>"xr"</code>.

The [=default allowlist=] for this feature is <code>["self"]</code>.

In addition to the <code>"xr"</code> feature policy, feature policies for underlying sensors must also be respected if a site could isolate and extract sensor data that would otherwise be blocked by those feature policies.

Acknowledgements {#ack}
================

Expand Down