Skip to content
Open
Show file tree
Hide file tree
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
42 changes: 27 additions & 15 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1431,7 +1431,7 @@
<div class="head">
<p data-fill-with="logo"><a class="logo" href="https://www.w3.org/"> <img alt="W3C" height="48" src="https://www.w3.org/StyleSheets/TR/2016/logos/W3C" width="72"> </a> </p>
<h1>Credential Management Level 1</h1>
<h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Editor’s Draft, <time class="dt-updated" datetime="2017-01-13">13 January 2017</time></span></h2>
<h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Editor’s Draft, <time class="dt-updated" datetime="2017-02-14">14 February 2017</time></span></h2>
<div data-fill-with="spec-metadata">
<dl>
<dt>This version:
Expand Down Expand Up @@ -2909,10 +2909,21 @@ <h3 class="heading settled" data-level="6.1" id="security-cross-origin-leakage">
of a credential by comparing the <a data-link-type="dfn" href="https://publicsuffix.org/list/#">registerable domains</a> of the
credential’s <code class="idl"><a data-link-type="idl" href="#dom-siteboundcredential-origin-slot" id="ref-for-dom-siteboundcredential-origin-slot-9">[[origin]]</a></code> with the origin in which <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-get" id="ref-for-dom-credentialscontainer-get-11">get()</a></code> is called. That is: credentials saved on <code>https://admin.example.com/</code> and <code>https://example.com/</code> MAY be offered to users when <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-get" id="ref-for-dom-credentialscontainer-get-12">get()</a></code> is called from <code>https://www.example.com/</code>.
<li> MUST NOT offer credentials to an origin in response to <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-get" id="ref-for-dom-credentialscontainer-get-13">get()</a></code> without user mediation if the credential’s
origin is not an exact match for the calling origin. That is, <code class="idl"><a data-link-type="idl" href="#credential" id="ref-for-credential-35">Credential</a></code> objects for <code>https://example.com</code> would not be
returned directly to <code>https://www.example.com</code>, but could be
origin is not an exact match for the calling origin. That is, <code class="idl"><a data-link-type="idl" href="#credential" id="ref-for-credential-35">Credential</a></code> objects for <code>https://example.com/</code> would not be
returned directly to <code>https://www.example.com/</code>, but could be
offered to the user via the chooser.
<li> MAY store credentials without user mediation when <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-store" id="ref-for-dom-credentialscontainer-store-9">store()</a></code> is called if the credential was
retrieved via a user mediated <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-get" id="ref-for-dom-credentialscontainer-get-14">get()</a></code> from a
PSL-matched domain and new domain is still PSL-matching the original
domain for which the credentials were stored.
</ol>
<div class="example" id="example-2e4ce27d"><a class="self-link" href="#example-2e4ce27d"></a> A user stores a credential for <code>https://www.example.com/</code> on
their computer. This credential is synced via the browser’s syncing
technologies to the user’s phone. The user visits <code>https://m.example.com/</code>. The browser may provide the stored
credential to <code>https://m.example.com/</code> in a user mediated way
due to the Public Suffix List <a data-link-type="biblio" href="#biblio-psl">[PSL]</a>. After that the website can call <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-store" id="ref-for-dom-credentialscontainer-store-10">store()</a></code> and the browser may silently store a
second credential or a reference that allows <code>https://m.example.com/</code> to retrieve the credential without user
mediation in the future. </div>
<p><code class="idl"><a data-link-type="idl" href="#passwordcredential" id="ref-for-passwordcredential-32">PasswordCredential</a></code>s further mitigate the risk of data leakage by never
exposing the <code class="idl"><a data-link-type="idl" href="#dom-passwordcredential-password-slot" id="ref-for-dom-passwordcredential-password-slot-7">[[password]]</a></code> slot directly to a page’s JavaScript, but only
allowing its submission to a same-origin server-side endpoint via <code class="idl"><a data-link-type="idl" href="https://fetch.spec.whatwg.org/#dom-global-fetch">fetch()</a></code>.</p>
Expand Down Expand Up @@ -2943,7 +2954,7 @@ <h3 class="heading settled" data-level="6.3" id="security-origin-confusion"><spa
which users can reasonably be expected to understand.</p>
<p>Therefore, <a data-link-type="dfn" href="http://www.w3.org/TR/html5/browsers.html#nested-browsing-context">Nested browsing contexts</a> and other environments like
Workers <a data-link-type="biblio" href="#biblio-workers">[WORKERS]</a> cannot receive or store <code class="idl"><a data-link-type="idl" href="#credential" id="ref-for-credential-36">Credential</a></code> objects; the user
agent MUST reject promises generated by calls to <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-get" id="ref-for-dom-credentialscontainer-get-14">get()</a></code> and <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-store" id="ref-for-dom-credentialscontainer-store-9">store()</a></code> with a <code>SecurityError</code> when
agent MUST reject promises generated by calls to <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-get" id="ref-for-dom-credentialscontainer-get-15">get()</a></code> and <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-store" id="ref-for-dom-credentialscontainer-store-11">store()</a></code> with a <code>SecurityError</code> when
called from a context which is not a <a data-link-type="dfn" href="http://www.w3.org/TR/html5/browsers.html#top-level-browsing-context">top-level browsing context</a>.</p>
<p>See the algorithms defined in <a href="#request-credential">§4.1.1 Request a Credential</a> and <a href="#store-credential">§4.1.2 Store a Credential</a> for details.</p>
<h3 class="heading settled" data-level="6.4" id="security-insecure-origins"><span class="secno">6.4. </span><span class="content">Insecure Sites</span><a class="self-link" href="#security-insecure-origins"></a></h3>
Expand All @@ -2956,7 +2967,7 @@ <h3 class="heading settled" data-level="6.4" id="security-insecure-origins"><spa
contexts</a> (as discussed in <a href="#security-cross-origin-leakage">§6.1 Cross-origin Credential Leakage</a>.</p>
<h3 class="heading settled" data-level="6.5" id="security-xss"><span class="secno">6.5. </span><span class="content">Script Injection</span><a class="self-link" href="#security-xss"></a></h3>
<p>If a malicious party is able to inject script into an origin, they could
(among many other things you wouldn’t like) overwrite the behavior of <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-store" id="ref-for-dom-credentialscontainer-store-10">store()</a></code> to steal a user’s credentials as they’re written into the <a data-link-type="dfn" href="#credential-store" id="ref-for-credential-store-11">credential store</a>.</p>
(among many other things you wouldn’t like) overwrite the behavior of <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-store" id="ref-for-dom-credentialscontainer-store-12">store()</a></code> to steal a user’s credentials as they’re written into the <a data-link-type="dfn" href="#credential-store" id="ref-for-credential-store-11">credential store</a>.</p>
<p>Authors SHOULD mitigate the risk of such attacks by properly escaping input
and output, and add layers of defense in depth by setting a reasonably
strong Content Security Policy <a data-link-type="biblio" href="#biblio-csp">[CSP]</a> which restricts the origins from
Expand All @@ -2965,11 +2976,11 @@ <h3 class="heading settled" data-level="6.5" id="security-xss"><span class="secn
<section>
<h2 class="heading settled" data-level="7" id="privacy-considerations"><span class="secno">7. </span><span class="content">Privacy Considerations</span><a class="self-link" href="#privacy-considerations"></a></h2>
<h3 class="heading settled" data-level="7.1" id="privacy-timing-attacks"><span class="secno">7.1. </span><span class="content">Timing Attacks</span><a class="self-link" href="#privacy-timing-attacks"></a></h3>
<p>If the user has no credentials for an origin, a call to <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-get" id="ref-for-dom-credentialscontainer-get-15">get()</a></code> will resolve very quickly indeed. A malicious
<p>If the user has no credentials for an origin, a call to <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-get" id="ref-for-dom-credentialscontainer-get-16">get()</a></code> will resolve very quickly indeed. A malicious
website could distinguish between a user with no credentials and a user with
credentials who chooses not to share them.</p>
<p>This could allow a malicious website to determine if a user has credentials
saved for particular federated identity providers by repeatedly calling <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-get" id="ref-for-dom-credentialscontainer-get-16">get()</a></code> with a single item in the <code class="idl"><a data-link-type="idl" href="#dom-federatedcredentialrequestoptions-providers" id="ref-for-dom-federatedcredentialrequestoptions-providers-7">providers</a></code> array. The risk is mitigated
saved for particular federated identity providers by repeatedly calling <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-get" id="ref-for-dom-credentialscontainer-get-17">get()</a></code> with a single item in the <code class="idl"><a data-link-type="idl" href="#dom-federatedcredentialrequestoptions-providers" id="ref-for-dom-federatedcredentialrequestoptions-providers-7">providers</a></code> array. The risk is mitigated
by the fact that the user would, sooner or later, be prompted to provide
credentials to the site which would certainly raise her suspicions as to its
behavior.</p>
Expand Down Expand Up @@ -3072,7 +3083,7 @@ <h3 class="heading settled" data-level="8.3" id="implementation-browser-extensio
the behavior of third party credential management software in the same way
that user agents can improve their own via this imperative approach.</p>
<p>This could range from a complex new API that the user agent mediates, or
simply by allowing extensions to overwrite the <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-get" id="ref-for-dom-credentialscontainer-get-17">get()</a></code> and <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-store" id="ref-for-dom-credentialscontainer-store-11">store()</a></code> endpoints for their own purposes.</p>
simply by allowing extensions to overwrite the <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-get" id="ref-for-dom-credentialscontainer-get-18">get()</a></code> and <code class="idl"><a data-link-type="idl" href="#dom-credentialscontainer-store" id="ref-for-dom-credentialscontainer-store-13">store()</a></code> endpoints for their own purposes.</p>
</section>
<section>
<h2 class="heading settled" data-level="9" id="future-work"><span class="secno">9. </span><span class="content">Future Work</span><a class="self-link" href="#future-work"></a></h2>
Expand Down Expand Up @@ -3987,10 +3998,10 @@ <h2 class="no-num no-ref heading settled" id="issues-index"><span class="content
<li><a href="#ref-for-dom-credentialscontainer-get-9">4.1.1.
Request a Credential </a>
<li><a href="#ref-for-dom-credentialscontainer-get-10">5.3. Credential Selection</a>
<li><a href="#ref-for-dom-credentialscontainer-get-11">6.1. Cross-origin Credential Leakage</a> <a href="#ref-for-dom-credentialscontainer-get-12">(2)</a> <a href="#ref-for-dom-credentialscontainer-get-13">(3)</a>
<li><a href="#ref-for-dom-credentialscontainer-get-14">6.3. Origin Confusion</a>
<li><a href="#ref-for-dom-credentialscontainer-get-15">7.1. Timing Attacks</a> <a href="#ref-for-dom-credentialscontainer-get-16">(2)</a>
<li><a href="#ref-for-dom-credentialscontainer-get-17">8.3. Browser Extensions</a>
<li><a href="#ref-for-dom-credentialscontainer-get-11">6.1. Cross-origin Credential Leakage</a> <a href="#ref-for-dom-credentialscontainer-get-12">(2)</a> <a href="#ref-for-dom-credentialscontainer-get-13">(3)</a> <a href="#ref-for-dom-credentialscontainer-get-14">(4)</a>
<li><a href="#ref-for-dom-credentialscontainer-get-15">6.3. Origin Confusion</a>
<li><a href="#ref-for-dom-credentialscontainer-get-16">7.1. Timing Attacks</a> <a href="#ref-for-dom-credentialscontainer-get-17">(2)</a>
<li><a href="#ref-for-dom-credentialscontainer-get-18">8.3. Browser Extensions</a>
</ul>
</aside>
<aside class="dfn-panel" data-for="dom-credentialscontainer-get-options-options">
Expand All @@ -4006,9 +4017,10 @@ <h2 class="no-num no-ref heading settled" id="issues-index"><span class="content
<li><a href="#ref-for-dom-credentialscontainer-store-3">1.2.4. Change Password</a> <a href="#ref-for-dom-credentialscontainer-store-4">(2)</a>
<li><a href="#ref-for-dom-credentialscontainer-store-5">3.2. Credential Manager</a> <a href="#ref-for-dom-credentialscontainer-store-6">(2)</a> <a href="#ref-for-dom-credentialscontainer-store-7">(3)</a>
<li><a href="#ref-for-dom-credentialscontainer-store-8">5.1. Storing and Updating Credentials</a>
<li><a href="#ref-for-dom-credentialscontainer-store-9">6.3. Origin Confusion</a>
<li><a href="#ref-for-dom-credentialscontainer-store-10">6.5. Script Injection</a>
<li><a href="#ref-for-dom-credentialscontainer-store-11">8.3. Browser Extensions</a>
<li><a href="#ref-for-dom-credentialscontainer-store-9">6.1. Cross-origin Credential Leakage</a> <a href="#ref-for-dom-credentialscontainer-store-10">(2)</a>
<li><a href="#ref-for-dom-credentialscontainer-store-11">6.3. Origin Confusion</a>
<li><a href="#ref-for-dom-credentialscontainer-store-12">6.5. Script Injection</a>
<li><a href="#ref-for-dom-credentialscontainer-store-13">8.3. Browser Extensions</a>
</ul>
</aside>
<aside class="dfn-panel" data-for="dom-credentialscontainer-store-credential-credential">
Expand Down
23 changes: 21 additions & 2 deletions index.src.html
Original file line number Diff line number Diff line change
Expand Up @@ -2089,12 +2089,31 @@ <h3 id="security-cross-origin-leakage">Cross-origin Credential Leakage</h3>
MUST NOT offer credentials to an origin in response to
{{CredentialsContainer/get()}} without user mediation if the credential's
origin is not an exact match for the calling origin. That is,
{{Credential}} objects for <code>https://example.com</code> would not be
returned directly to <code>https://www.example.com</code>, but could be
{{Credential}} objects for <code>https://example.com/</code> would not be
returned directly to <code>https://www.example.com/</code>, but could be
offered to the user via the chooser.
</li>
<li>
MAY store credentials without user mediation when
{{CredentialsContainer/store()}} is called if the credential was
retrieved via a user mediated {{CredentialsContainer/get()}} from a
PSL-matched domain and new domain is still PSL-matching the original
Copy link
Member

Choose a reason for hiding this comment

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

I think we could be a little more precise. How about something like: "... via a user-mediated {{CredentialsContainer/get()}}, if the credential's {{[[origin]]}}'s <a>registerable domain</a> is the same as the <a>current settings object</a>'s <a for="environment settings object">origin</a>'s <a>registerable domain</a>."

domain for which the credentials were stored.
Copy link
Member

Choose a reason for hiding this comment

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

Nit: </li>

</ol>

<div class="example">
A user stores a credential for <code>https://www.example.com/</code> on
Copy link
Member

Choose a reason for hiding this comment

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

Nit: s/<\/?code>/`/, here and elsewhere.

their computer. This credential is synced via the browser's syncing
technologies to the user's phone. The user visits
Copy link
Member

Choose a reason for hiding this comment

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

Nit: I'd suggest dropping the sync bit. It's irrelevant to your example.

"""
A user stores a credential after creating an account for https://accounts.example.com/. When they wish to sign into https://example.com/ in the future, the user agent can offer that credential in response to {{CredentialsContainer/get()}} with user mediation, as described above. If the user chooses that credential, the website can call {{CredentialsContainer/store()}} to ensure that the credential is available to https://example.com/ in the future. Since the two origins have the same registerable domain, and the user indicated that the credentials are valid for both origins, the user agent can store a credential for https://example.com/ without further prompting.
"""

<code>https://m.example.com/</code>. The browser may provide the stored
credential to <code>https://m.example.com/</code> in a user mediated way
due to the Public Suffix List [[!PSL]]. After that the website can call
{{CredentialsContainer/store()}} and the browser may silently store a
second credential or a reference that allows
<code>https://m.example.com/</code> to retrieve the credential without user
mediation in the future.
</div>

{{PasswordCredential}}s further mitigate the risk of data leakage by never
exposing the {{[[password]]}} slot directly to a page's JavaScript, but only
allowing its submission to a same-origin server-side endpoint via {{fetch()}}.
Expand Down