[EME] Add parameter validation to load() and update().
authorDavid Dorwin <ddorwin@google.com>
Fri, 19 Sep 2014 16:24:34 -0700
changeset 436 c64c7311ade3
parent 435 4642f0f6d841
child 437 5b5944a790a0
[EME] Add parameter validation to load() and update().
encrypted-media/encrypted-media.html
encrypted-media/encrypted-media.xml
--- a/encrypted-media/encrypted-media.html	Fri Sep 19 16:05:51 2014 -0700
+++ b/encrypted-media/encrypted-media.html	Fri Sep 19 16:24:34 2014 -0700
@@ -623,6 +623,13 @@
       <li>
 <p>Run the following steps asynchronously:</p>
         <ol>
+          <li>
+<p>Let <var>sanitized session ID</var> be a validated and/or sanitized version of <var title="true">sessionId</var>.</p>
+            <div class="note">The user agent should thoroughly validate the sessionId value before passing it to the CDM.
+              At a minimum, this shoudl include checking that the length and value (e.g. alphanumeric) are reasonable.
+            </div>
+          </li>
+          <li><p>If the previous step failed, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
           <li><p>Let <var title="true">expiration time</var> be <code>NaN</code>.</p></li>
           <li><p>Let <var title="true">message</var> be null.</p></li>
           <li><p>Let <var title="true">message type</var> be null.</p></li>
@@ -631,12 +638,12 @@
           <li>
 <p>Use the <var title="true">cdm</var> to execute the following steps:</p>
             <ol>
-              <li><p>If there is no data stored for the <var title="true">sessionId</var> in the <var title="true">origin</var>, resolve <var>promise</var> with <code>false</code>.</p></li>
-              <li><p>Let <var title="true">session data</var> be the data stored for the <var title="true">sessionId</var> in the <var title="true">origin</var>.
+              <li><p>If there is no data stored for the <var>sanitized session ID</var> in the <var title="true">origin</var>, resolve <var>promise</var> with <code>false</code>.</p></li>
+              <li><p>Let <var title="true">session data</var> be the data stored for the <var>sanitized session ID</var> in the <var title="true">origin</var>.
               This must not include data from other origin(s) or that is not associated with an origin.</p></li>
               <li>
 <p>If there is an unclosed "<code><a href="#dom-sessiontypepersistent">persistent</a></code>" session in any <a href="http://www.w3.org/TR/dom/#document">Document</a> representing the <var title="true">session data</var>, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-QuotaExceededError">"QuotaExceededError"</a></code>.</p>
-                <p class="non-normative">In other words, do not create a session if a non-closed persistent session already exists for this <var title="true">sessionId</var> in any browsing context.</p>
+                <p class="non-normative">In other words, do not create a session if a non-closed persistent session already exists for this <var>sanitized session ID</var> in any browsing context.</p>
               </li>
               <li><p>Load the <var title="true">session data</var>.</p></li>
               <li><p>If the <var title="true">session data</var> indicates an expiration time for the session, let <var title="true">expiration time</var> be the expiration time in milliseconds since 01 January 1970 UTC.</p></li>
@@ -650,7 +657,7 @@
             </ol>
           </li>
           <li><p>If any of the preceding steps failed, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is the appropriate <a href="#error-names">error name</a>.</p></li>
-          <li><p>Set the <code><a href="#dom-sessionid">sessionId</a></code> attribute to <var title="true">sessionId</var>.</p></li>
+          <li><p>Set the <code><a href="#dom-sessionid">sessionId</a></code> attribute to <var>sanitized session ID</var>.</p></li>
           <li><p>Let this object's <var title="true">callable</var> be true.</p></li>
           <li>
 <p>If the loaded session contains usable keys, run the <a href="#algorithms-keys-changed">Usable Keys Changed</a> algorithm on the <var title="true">session</var>.</p>
@@ -675,27 +682,36 @@
       <li>
 <p>Run the following steps asynchronously:</p>
         <ol>
+          <li>
+<p>Let <var>sanitized response</var> be a validated and/or sanitized version of <var>response copy</var>.</p>
+            <div class="note">The user agent should thoroughly validate the response before passing it to the CDM.
+              This may include verifying values are within reasonable limits, stripping irrelevant data or fields, pre-parsing it, sanitizing it, and/or generating a fully sanitized version.
+              The user agent should check that the length and values of fields are reasonable.
+              Unknown fields should be rejected or removed.
+            </div>
+          </li>
+          <li><p>If the previous step failed, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
           <li><p>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of the <code><a href="#dom-mediakeys">MediaKeys</a></code> object that created this object.</p></li>
           <li><p>Let <var title="true">message</var> be null.</p></li>
           <li><p>Let <var title="true">message type</var> be null.</p></li>
           <li>
 <p>Use the <var title="true">cdm</var> to execute the following steps:</p>
             <ol>
-              <li><p>If the format of <var>response copy</var> is invalid in any way, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
+              <li><p>If the format of <var>sanitized response</var> is invalid in any way, reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
               <li>
-<p>Process <var>response copy</var>, following the stipulation for the first matching condition from the following list:</p>
+<p>Process <var>sanitized response</var>, following the stipulation for the first matching condition from the following list:</p>
                 <dl class="switch">
-                  <dt>If <var title="true">sessionType</var> is "<code><a href="#dom-sessiontypetemporary">temporary</a></code>" and <var>response copy</var> does not specify that session data, including any license, key(s), or similar session data it contains, should be stored</dt>
-                  <dd>Continue processing <var>response copy</var>, not storing any session data.</dd>
+                  <dt>If <var title="true">sessionType</var> is "<code><a href="#dom-sessiontypetemporary">temporary</a></code>" and <var>sanitized response</var> does not specify that session data, including any license, key(s), or similar session data it contains, should be stored</dt>
+                  <dd>Continue processing <var>sanitized response</var>, not storing any session data.</dd>
                   <dt>If <var title="true">sessionType</var> is "<code><a href="#dom-sessiontypepersistent">persistent</a></code>"</dt>
-                  <dd>Continue processing <var>response copy</var>, storing the license, key(s), or similar session data contained in <var>response copy</var> as permitted or instructed by the license.
+                  <dd>Continue processing <var>sanitized response</var>, storing the license, key(s), or similar session data contained in <var>sanitized response</var> as permitted or instructed by the license.
                     Such data must be stored such that only the <a href="http://www.w3.org/TR/html5/browsers.html#origin-0">origin</a> of this object's <code><a href="http://www.w3.org/TR/dom/#document">Document</a></code> can access it.
                   </dd>
                   <dt>Otherwise</dt>
                   <dd>Reject <var>promise</var> with a new <code><a href="http://www.w3.org/TR/dom/#exception-domexception">DOMException</a></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</dd>
                 </dl>
                 <p>See also <a href="#session-storage">Session Storage and Persistence</a>.</p>
-                <p class="non-normative">Note: When <var>response copy</var> contains key(s) and/or related data, <var title="true">cdm</var> will likely cache the key and related data indexed by key ID.</p>
+                <p class="non-normative">Note: When <var>sanitized response</var> contains key(s) and/or related data, <var title="true">cdm</var> will likely cache the key and related data indexed by key ID.</p>
                 <p class="non-normative">Note: The replacement algorithm within a session is <a href="#key-system">Key System</a>-dependent.</p>
                 <p class="non-normative">Note: Keys from different sessions should be cached independently such that closing one session does not affect keys in other sessions, even if they have overlapping key IDs.</p>
                 <p class="non-normative">Note: It is recommended that CDMs support a standard and reasonably high minimum number of keys per <code><a href="#dom-mediakeysession">MediaKeySession</a></code> object, including a standard replacement algorithm, and a standard and reasonably high minimum number of <code><a href="#dom-mediakeysession">MediaKeySession</a></code> objects.
@@ -771,7 +787,7 @@
                 <p>Process the remove request.</p>
                 <p>This may involve exchanging message(s) with the application.</p>
                 <p>Unless this step fails, the CDM must have cleared all stored session data associated with this object, including the <code><a href="#dom-sessionid">sessionId</a></code>, before proceeding to the next step.
-                  <span class="non-normative">(A subsequent call to <code><a href="#dom-load">load()</a></code> with <code><a href="#dom-sessionid">sessionId</a></code> would fail because there is no data stored for the <var title="true">sessionId</var>.)</span>
+                  <span class="non-normative">(A subsequent call to <code><a href="#dom-load">load()</a></code> with <code><a href="#dom-sessionid">sessionId</a></code> would fail because there is no data stored for that session ID.)</span>
                 </p>
               </li>
             </ol>
@@ -1059,7 +1075,7 @@
       This ensures that the application is aware of the session and knows it needs to eventually remove it.
     </p>
     <p>The CDM must ensure that data for a given session is only present in one active unclosed session in any <a href="http://www.w3.org/TR/dom/#document">Document</a>.
-      In other words, <code><a href="#dom-load">load()</a></code> must fail when there is already a <code><a href="#dom-mediakeysession">MediaKeySession</a></code> representing the session specified by <var title="true">sessionId</var>, either because the object that created it via <code><a href="#dom-generaterequest">generateRequest()</a></code> is still active or it has been loaded into another object via <code><a href="#dom-load">load()</a></code>.
+      In other words, <code><a href="#dom-load">load()</a></code> must fail when there is already a <code><a href="#dom-mediakeysession">MediaKeySession</a></code> representing the session specified by the <var title="true">sessionId</var> parameter, either because the object that created it via <code><a href="#dom-generaterequest">generateRequest()</a></code> is still active or it has been loaded into another object via <code><a href="#dom-load">load()</a></code>.
       A session may only be loaded again after the <a href="#algorithms-session-close">Session Close</a> algorithm has not been run on the object representing it.
     </p>
     <p>An application that creates a "<code><a href="#dom-sessiontypepersistent">persistent</a></code>" session should later remove the stored data using <code><a href="#dom-remove">remove()</a></code>.
@@ -1362,7 +1378,7 @@
 <p>In the <code><a href="#dom-update">update()</a></code> algorithm:</p>
         <ul>
           <li><p>The <var title="true">response</var> parameter is a JWK Set as described in <a href="#clear-key-license-format">License Format</a>.</p></li>
-          <li><p><var>response copy</var> is considered invalid if it is not a valid JWK Set with at least one valid JWK key of a valid length for the media type.</p></li>
+          <li><p><var>sanitized response</var> is considered invalid if it is not a valid JWK Set with at least one valid JWK key of a valid length for the media type.</p></li>
         </ul>
       </li>
       <li><p>The <code><a href="#dom-getusablekeyids">getUsableKeyIds()</a></code> method always returns all key IDs that have been provided via <code><a href="#dom-update">update()</a></code>.</p></li>
--- a/encrypted-media/encrypted-media.xml	Fri Sep 19 16:05:51 2014 -0700
+++ b/encrypted-media/encrypted-media.xml	Fri Sep 19 16:24:34 2014 -0700
@@ -594,6 +594,12 @@
       <li><p>Let <var>promise</var> be a new promise.</p></li>
       <li><p>Run the following steps asynchronously:</p>
         <ol>
+          <li><p>Let <var>sanitized session ID</var> be a validated and/or sanitized version of <var title="true">sessionId</var>.</p>
+            <div class="note">The user agent should thoroughly validate the sessionId value before passing it to the CDM.
+              At a minimum, this shoudl include checking that the length and value (e.g. alphanumeric) are reasonable.
+            </div>
+          </li>
+          <li><p>If the previous step failed, reject <var>promise</var> with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
           <li><p>Let <var title="true">expiration time</var> be <code>NaN</code>.</p></li>
           <li><p>Let <var title="true">message</var> be null.</p></li>
           <li><p>Let <var title="true">message type</var> be null.</p></li>
@@ -601,11 +607,11 @@
           <li><p>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of <var title="true">media keys</var>.</p></li>
           <li><p>Use the <var title="true">cdm</var> to execute the following steps:</p>
             <ol>
-              <li><p>If there is no data stored for the <var title="true">sessionId</var> in the <var title="true">origin</var>, resolve <var>promise</var> with <code>false</code>.</p></li><!-- Per https://github.com/w3ctag/promises-guide#rejections-should-be-used-for-exceptional-situations. -->
-              <li><p>Let <var title="true">session data</var> be the data stored for the <var title="true">sessionId</var> in the <var title="true">origin</var>.
+              <li><p>If there is no data stored for the <var>sanitized session ID</var> in the <var title="true">origin</var>, resolve <var>promise</var> with <code>false</code>.</p></li><!-- Per https://github.com/w3ctag/promises-guide#rejections-should-be-used-for-exceptional-situations. -->
+              <li><p>Let <var title="true">session data</var> be the data stored for the <var>sanitized session ID</var> in the <var title="true">origin</var>.
               This must not include data from other origin(s) or that is not associated with an origin.</p></li>
               <li><p>If there is an unclosed "<coderef prefix="sessiontype">persistent</coderef>" session in any <dom4ref name="document">Document</dom4ref> representing the <var title="true">session data</var>, reject <var>promise</var> with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></code> whose name is <code><a href="#dfn-QuotaExceededError">"QuotaExceededError"</a></code>.</p>
-                <p class="non-normative">In other words, do not create a session if a non-closed persistent session already exists for this <var title="true">sessionId</var> in any browsing context.</p>
+                <p class="non-normative">In other words, do not create a session if a non-closed persistent session already exists for this <var>sanitized session ID</var> in any browsing context.</p>
               </li>
               <li><p>Load the <var title="true">session data</var>.</p></li>
               <li><p>If the <var title="true">session data</var> indicates an expiration time for the session, let <var title="true">expiration time</var> be the expiration time in milliseconds since 01 January 1970 UTC.</p></li>
@@ -618,7 +624,7 @@
             </ol>
           </li>
           <li><p>If any of the preceding steps failed, reject <var>promise</var> with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></code> whose name is the appropriate <a href="#error-names">error name</a>.</p></li>
-          <li><p>Set the <coderef>sessionId</coderef> attribute to <var title="true">sessionId</var>.</p></li>
+          <li><p>Set the <coderef>sessionId</coderef> attribute to <var>sanitized session ID</var>.</p></li>
           <li><p>Let this object's <var title="true">callable</var> be true.</p></li>
           <li><p>If the loaded session contains usable keys, run the <a href="#algorithms-keys-changed">Usable Keys Changed</a> algorithm on the <var title="true">session</var>.</p>
             <p>The algorithm may also be run later should additional processing be necessary to determine with certainty whether one or more keys is usable.</p>
@@ -641,25 +647,33 @@
       <li><p>Let <var>promise</var> be a new promise.</p></li>
       <li><p>Run the following steps asynchronously:</p>
         <ol>
+          <li><p>Let <var>sanitized response</var> be a validated and/or sanitized version of <var>response copy</var>.</p>
+            <div class="note">The user agent should thoroughly validate the response before passing it to the CDM.
+              This may include verifying values are within reasonable limits, stripping irrelevant data or fields, pre-parsing it, sanitizing it, and/or generating a fully sanitized version.
+              The user agent should check that the length and values of fields are reasonable.
+              Unknown fields should be rejected or removed.
+            </div>
+          </li>
+          <li><p>If the previous step failed, reject <var>promise</var> with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
           <li><p>Let <var title="true">cdm</var> be the CDM loaded during the <a href="#dom-create">initialization</a> of the <coderef>MediaKeys</coderef> object that created this object.</p></li>
           <li><p>Let <var title="true">message</var> be null.</p></li>
           <li><p>Let <var title="true">message type</var> be null.</p></li>
           <li><p>Use the <var title="true">cdm</var> to execute the following steps:</p>
             <ol>
-              <li><p>If the format of <var>response copy</var> is invalid in any way, reject <var>promise</var> with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
-              <li><p>Process <var>response copy</var>, following the stipulation for the first matching condition from the following list:</p>
+              <li><p>If the format of <var>sanitized response</var> is invalid in any way, reject <var>promise</var> with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</p></li>
+              <li><p>Process <var>sanitized response</var>, following the stipulation for the first matching condition from the following list:</p>
                 <dl class="switch">
-                  <dt>If <var title="true">sessionType</var> is "<coderef prefix="sessiontype">temporary</coderef>" and <var>response copy</var> does not specify that session data, including any license, key(s), or similar session data it contains, should be stored</dt>
-                  <dd>Continue processing <var>response copy</var>, not storing any session data.</dd>
+                  <dt>If <var title="true">sessionType</var> is "<coderef prefix="sessiontype">temporary</coderef>" and <var>sanitized response</var> does not specify that session data, including any license, key(s), or similar session data it contains, should be stored</dt>
+                  <dd>Continue processing <var>sanitized response</var>, not storing any session data.</dd>
                   <dt>If <var title="true">sessionType</var> is "<coderef prefix="sessiontype">persistent</coderef>"</dt>
-                  <dd>Continue processing <var>response copy</var>, storing the license, key(s), or similar session data contained in <var>response copy</var> as permitted or instructed by the license.
+                  <dd>Continue processing <var>sanitized response</var>, storing the license, key(s), or similar session data contained in <var>sanitized response</var> as permitted or instructed by the license.
                     Such data must be stored such that only the <a href="http://www.w3.org/TR/html5/browsers.html#origin-0">origin</a> of this object's <code><dom4ref name="document">Document</dom4ref></code> can access it.
                   </dd>
                   <dt>Otherwise</dt>
                   <dd>Reject <var>promise</var> with a new <code><dom4ref name="exception-domexception">DOMException</dom4ref></code> whose name is <code><a href="#dfn-InvalidAccessError">"InvalidAccessError"</a></code>.</dd>
                 </dl>
                 <p>See also <a href="#session-storage">Session Storage and Persistence</a>.</p>
-                <p class="non-normative">Note: When <var>response copy</var> contains key(s) and/or related data, <var title="true">cdm</var> will likely cache the key and related data indexed by key ID.</p>
+                <p class="non-normative">Note: When <var>sanitized response</var> contains key(s) and/or related data, <var title="true">cdm</var> will likely cache the key and related data indexed by key ID.</p>
                 <p class="non-normative">Note: The replacement algorithm within a session is <a href="#key-system">Key System</a>-dependent.</p>
                 <p class="non-normative">Note: Keys from different sessions should be cached independently such that closing one session does not affect keys in other sessions, even if they have overlapping key IDs.</p>
                 <p class="non-normative">Note: It is recommended that CDMs support a standard and reasonably high minimum number of keys per <coderef>MediaKeySession</coderef> object, including a standard replacement algorithm, and a standard and reasonably high minimum number of <coderef>MediaKeySession</coderef> objects.
@@ -729,7 +743,7 @@
                 <p>Process the remove request.</p>
                 <p>This may involve exchanging message(s) with the application.</p>
                 <p>Unless this step fails, the CDM must have cleared all stored session data associated with this object, including the <coderef>sessionId</coderef>, before proceeding to the next step.
-                  <span class="non-normative">(A subsequent call to <methodref>load</methodref> with <coderef>sessionId</coderef> would fail because there is no data stored for the <var title="true">sessionId</var>.)</span>
+                  <span class="non-normative">(A subsequent call to <methodref>load</methodref> with <coderef>sessionId</coderef> would fail because there is no data stored for that session ID.)</span>
                 </p>
               </li>
             </ol>
@@ -1001,7 +1015,7 @@
       This ensures that the application is aware of the session and knows it needs to eventually remove it.
     </p>
     <p>The CDM must ensure that data for a given session is only present in one active unclosed session in any <dom4ref name="document">Document</dom4ref>.
-      In other words, <methodref>load</methodref> must fail when there is already a <coderef>MediaKeySession</coderef> representing the session specified by <var title="true">sessionId</var>, either because the object that created it via <methodref>generateRequest</methodref> is still active or it has been loaded into another object via <methodref>load</methodref>.
+      In other words, <methodref>load</methodref> must fail when there is already a <coderef>MediaKeySession</coderef> representing the session specified by the <var title="true">sessionId</var> parameter, either because the object that created it via <methodref>generateRequest</methodref> is still active or it has been loaded into another object via <methodref>load</methodref>.
       A session may only be loaded again after the <a href="#algorithms-session-close">Session Close</a> algorithm has not been run on the object representing it.
     </p>
     <p>An application that creates a "<coderef prefix="sessiontype">persistent</coderef>" session should later remove the stored data using <methodref>remove</methodref>.
@@ -1288,7 +1302,7 @@
       <li><p>In the <methodref>update</methodref> algorithm:</p>
         <ul>
           <li><p>The <var title="true">response</var> parameter is a JWK Set as described in <a href="#clear-key-license-format">License Format</a>.</p></li>
-          <li><p><var>response copy</var> is considered invalid if it is not a valid JWK Set with at least one valid JWK key of a valid length for the media type.</p></li>
+          <li><p><var>sanitized response</var> is considered invalid if it is not a valid JWK Set with at least one valid JWK key of a valid length for the media type.</p></li>
         </ul>
       </li>
       <li><p>The <methodref>getUsableKeyIds</methodref> method always returns all key IDs that have been provided via <methodref>update</methodref>.</p></li>