Skip to content

Commit 0e81d81

Browse files
committed
Allow upgrades from explicitly insecure expressions
CSP2 allows developers to shoot themselves in the foot by locking themselves into insecure requests via source expressions like `'self'`, `http:` or `http://example.com`. This patch loosens the matching rules for these insecure schemes to include their secure variants. That is, `http:` is not equivalent to `http: https:`, and `ws:` to `ws: wss:`. Likewise, handling for `'self'` now includes `https:` and `wss:` on the protected resource's host. Fixes w3c/webappsec#25. Fixes w3c/webappsec#7.
1 parent fdbed0b commit 0e81d81

File tree

2 files changed

+96
-28
lines changed

2 files changed

+96
-28
lines changed

index.html

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,7 +1001,7 @@
10011001
<div class="head">
10021002
<p data-fill-with="logo"><a class="logo" href="http://www.w3.org/"> <img alt="W3C" height="48" src="https://www.w3.org/Icons/w3c_home" width="72"> </a> </p>
10031003
<h1 class="p-name no-ref" id="title">Content Security Policy Level 3</h1>
1004-
<h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Editor’s Draft, <time class="dt-updated" datetime="2015-10-21">21 October 2015</time></span></h2>
1004+
<h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Editor’s Draft, <time class="dt-updated" datetime="2015-10-28">28 October 2015</time></span></h2>
10051005
<div data-fill-with="spec-metadata">
10061006
<dl>
10071007
<dt>This version:
@@ -2429,34 +2429,46 @@ <h5 class="heading settled" data-algorithm="Does url match expression in origin
24292429
<li data-md="">
24302430
<p>If <var>expression</var> is the string "*", and <var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code> is not a <a data-link-type="dfn" href="https://url.spec.whatwg.org/#local-scheme">local scheme</a>, return "<code>Matches</code>".</p>
24312431
<li data-md="">
2432-
<p>If <var>expression</var> matches the <a data-link-type="grammar" href="#grammardef-scheme-source"><code>scheme-source</code></a> grammar:</p>
2432+
<p>If <var>expression</var> matches the <a data-link-type="grammar" href="#grammardef-scheme-source"><code>scheme-source</code></a> or <a data-link-type="grammar" href="#grammardef-host-source"><code>host-source</code></a> grammar:</p>
24332433
<ol>
24342434
<li data-md="">
2435-
<p>If <var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code> is an <a data-link-type="dfn" href="http://www.w3.org/TR/html5/infrastructure.html#ascii-case-insensitive">ASCII case-insensitive match</a> for <var>expression</var>'s <a data-link-type="grammar" href="#grammardef-scheme-part"><code>scheme-part</code></a>, return "<code>Matches</code>".</p>
2435+
<p>If <var>expression</var> has a <a data-link-type="grammar" href="#grammardef-scheme-part"><code>scheme-part</code></a> that is not an <a data-link-type="dfn" href="http://www.w3.org/TR/html5/infrastructure.html#ascii-case-insensitive">ASCII case-insensitive match</a> for <var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code>, then
2436+
return "<code>Does Not Match</code>" unless one of the following conditions is
2437+
met:</p>
2438+
<ol>
2439+
<li data-md="">
2440+
<p><var>expression</var>'s <a data-link-type="grammar" href="#grammardef-scheme-part"><code>scheme-part</code></a> is an <a data-link-type="dfn" href="http://www.w3.org/TR/html5/infrastructure.html#ascii-case-insensitive">ASCII
2441+
case-insensitive match</a> for "<code>http</code>" and <var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code> is "<code>https</code>"</p>
2442+
<li data-md="">
2443+
<p><var>expression</var>'s <a data-link-type="grammar" href="#grammardef-scheme-part"><code>scheme-part</code></a> is an <a data-link-type="dfn" href="http://www.w3.org/TR/html5/infrastructure.html#ascii-case-insensitive">ASCII
2444+
case-insensitive match</a> for "<code>ws</code>" and <var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code> is "<code>wss</code>"</p>
2445+
</ol>
24362446
<li data-md="">
2437-
<p>Return "<code>Does Not Match</code>".</p>
2447+
<p>If <var>expression</var> matches the <a data-link-type="grammar" href="#grammardef-scheme-source"><code>scheme-source</code></a> grammar,
2448+
return "<code>Matches</code>".</p>
24382449
</ol>
2450+
<p class="note" role="note">Note: This logic effectively means that <code>script-src http:</code> is
2451+
equivalent to <code>script-src http: https:</code>, and <code>script-src http://example.com/</code> is equivalent to <code>script-src http://example.com https://example.com</code>. In short, we always allow a
2452+
secure upgrade from an explicitly insecure expression.</p>
24392453
<li data-md="">
24402454
<p>If <var>expression</var> matches the <a data-link-type="grammar" href="#grammardef-host-source"><code>host-source</code></a> grammar:</p>
24412455
<ol>
24422456
<li data-md="">
24432457
<p>If <var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-host">host</a></code> is <code>null</code>, return "<code>Does Not Match</code>".</p>
2444-
<li data-md="">
2445-
<p>If <var>expression</var> has a <a data-link-type="grammar" href="#grammardef-scheme-part"><code>scheme-part</code></a> that is not an <a data-link-type="dfn" href="http://www.w3.org/TR/html5/infrastructure.html#ascii-case-insensitive">ASCII case-insensitive match</a> for <var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code>, return
2446-
"<code>Does Not Match</code>".</p>
24472458
<li data-md="">
24482459
<p>If <var>expression</var> does not have a <a data-link-type="grammar" href="#grammardef-scheme-part"><code>scheme-part</code></a>, then
24492460
return "<code>Does Not Match</code>" unless one of the following conditions is
24502461
met:</p>
24512462
<ol>
24522463
<li data-md="">
2453-
<p><var>origin</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code> is an <a data-link-type="dfn" href="http://www.w3.org/TR/html5/infrastructure.html#ascii-case-insensitive">ASCII case-insensitive
2454-
match</a> for "<code>HTTP</code>", and <var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code> is an <a data-link-type="dfn" href="http://www.w3.org/TR/html5/infrastructure.html#ascii-case-insensitive">ASCII
2455-
case-insensitive match</a> for either "<code>HTTP</code>" or "<code>HTTPS</code>".</p>
2464+
<p><var>origin</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code> is <var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code></p>
2465+
<li data-md="">
2466+
<p><var>origin</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code> is "<code>http</code>", and <var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code> one of "<code>https</code>", "<code>ws</code>", or "<code>wss</code>".</p>
24562467
<li data-md="">
2457-
<p><var>origin</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code> is an <a data-link-type="dfn" href="http://www.w3.org/TR/html5/infrastructure.html#ascii-case-insensitive">ASCII case-insensitive
2458-
match</a> for <var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code>.</p>
2468+
<p><var>origin</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code> is "<code>https</code>", and <var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code> is "<code>wss</code>".</p>
24592469
</ol>
2470+
<p class="note" role="note">Note: As with <a data-link-type="grammar" href="#grammardef-scheme-part"><code>scheme-part</code></a> above, we allow schemeless <a data-link-type="grammar" href="#grammardef-host-source"><code>host-source</code></a> expressions to be upgraded from insecure
2471+
schemes to secure schemes.</p>
24602472
<li data-md="">
24612473
<p>If the first character of <var>expression</var>'s <a data-link-type="grammar" href="#grammardef-host-part"><code>host-part</code></a> is an U+002A ASTERISK character (<code>*</code>):</p>
24622474
<ol>
@@ -2520,7 +2532,27 @@ <h5 class="heading settled" data-algorithm="Does url match expression in origin
25202532
</ol>
25212533
<li data-md="">
25222534
<p>If <var>expression</var> is an <a data-link-type="dfn" href="http://www.w3.org/TR/html5/infrastructure.html#ascii-case-insensitive">ASCII case-insensitive match</a> for "<code>'self'</code>",
2523-
and <var>origin</var> is the same as <var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-origin">origin</a></code>, return "<code>Matches</code>".</p>
2535+
return "<code>Matches</code>" if one or more of the following conditions is met:</p>
2536+
<ol>
2537+
<li data-md="">
2538+
<p><var>origin</var> is the same as <var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-origin">origin</a></code></p>
2539+
<li data-md="">
2540+
<p><var>origin</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-host">host</a></code> is the same as <var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-host">host</a></code>, <var>origin</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-port">port</a></code> and <var>url</var>'s {{URL/port} are either the same
2541+
or the <a data-link-type="dfn" href="https://url.spec.whatwg.org/#default-port">default ports</a> for their respective <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code>s, and
2542+
one or more of the following conditions is met:</p>
2543+
<ol>
2544+
<li data-md="">
2545+
<p><var>url</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code> is "<code>https</code>" or "<code>wss</code>"</p>
2546+
<li data-md="">
2547+
<p><var>origin</var>'s <code class="idl"><a data-link-type="idl" href="https://url.spec.whatwg.org/#concept-url-scheme">scheme</a></code> is "<code>http</code>"</p>
2548+
</ol>
2549+
</ol>
2550+
<p class="note" role="note">Note: Like the <a data-link-type="grammar" href="#grammardef-scheme-part"><code>scheme-part</code></a> logic above, the "<code>'self'</code>"
2551+
matching algorithm allows upgrades to secure schemes when it is safe to do
2552+
so. We limit these upgrades to endpoints running on the default port for a
2553+
particular scheme or a port that matches the origin of the protected
2554+
resource, as this seems sufficient to deal with upgrades that can be
2555+
reasonably expected to succeed.</p>
25242556
<li data-md="">
25252557
<p>Return "<code>Does Not Match</code>".</p>
25262558
</ol>

index.src.html

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1762,31 +1762,50 @@ <h5 id="match-url-to-source-expression" algorithm>
17621762
1. If |expression| is the string "*", and |url|'s {{URL/scheme}} is not a
17631763
<a>local scheme</a>, return "`Matches`".
17641764

1765-
2. If |expression| matches the <a grammar>`scheme-source`</a> grammar:
1765+
2. If |expression| matches the <a grammar>`scheme-source`</a> or
1766+
<a grammar>`host-source`</a> grammar:
17661767

1767-
1. If |url|'s {{URL/scheme}} is an <a>ASCII case-insensitive match</a>
1768-
for |expression|'s <a grammar>`scheme-part`</a>, return "`Matches`".
1768+
1. If |expression| has a <a grammar>`scheme-part`</a> that is not an
1769+
<a>ASCII case-insensitive match</a> for |url|'s {{URL/scheme}}, then
1770+
return "`Does Not Match`" unless one of the following conditions is
1771+
met:
1772+
1773+
1. |expression|'s <a grammar>`scheme-part`</a> is an <a>ASCII
1774+
case-insensitive match</a> for "`http`" and |url|'s {{URL/scheme}}
1775+
is "`https`"
1776+
1777+
2. |expression|'s <a grammar>`scheme-part`</a> is an <a>ASCII
1778+
case-insensitive match</a> for "`ws`" and |url|'s {{URL/scheme}}
1779+
is "`wss`"
1780+
1781+
2. If |expression| matches the <a grammar>`scheme-source`</a> grammar,
1782+
return "`Matches`".
17691783

1770-
2. Return "`Does Not Match`".
1784+
Note: This logic effectively means that `script-src http:` is
1785+
equivalent to `script-src http: https:`, and
1786+
`script-src http://example.com/` is equivalent to `script-src
1787+
http://example.com https://example.com`. In short, we always allow a
1788+
secure upgrade from an explicitly insecure expression.
17711789

17721790
3. If |expression| matches the <a grammar>`host-source`</a> grammar:
17731791

17741792
1. If |url|'s {{URL/host}} is `null`, return "`Does Not Match`".
17751793

1776-
2. If |expression| has a <a grammar>`scheme-part`</a> that is not an
1777-
<a>ASCII case-insensitive match</a> for |url|'s {{URL/scheme}}, return
1778-
"`Does Not Match`".
1779-
1780-
3. If |expression| does not have a <a grammar>`scheme-part`</a>, then
1794+
2. If |expression| does not have a <a grammar>`scheme-part`</a>, then
17811795
return "`Does Not Match`" unless one of the following conditions is
17821796
met:
17831797

1784-
1. |origin|'s {{URL/scheme}} is an <a>ASCII case-insensitive
1785-
match</a> for "`HTTP`", and |url|'s {{URL/scheme}} is an <a>ASCII
1786-
case-insensitive match</a> for either "`HTTP`" or "`HTTPS`".
1798+
1. |origin|'s {{URL/scheme}} is |url|'s {{URL/scheme}}
17871799

1788-
2. |origin|'s {{URL/scheme}} is an <a>ASCII case-insensitive
1789-
match</a> for |url|'s {{URL/scheme}}.
1800+
2. |origin|'s {{URL/scheme}} is "`http`", and |url|'s {{URL/scheme}}
1801+
one of "`https`", "`ws`", or "`wss`".
1802+
1803+
3. |origin|'s {{URL/scheme}} is "`https`", and |url|'s {{URL/scheme}}
1804+
is "`wss`".
1805+
1806+
Note: As with <a grammar>`scheme-part`</a> above, we allow schemeless
1807+
<a grammar>`host-source`</a> expressions to be upgraded from insecure
1808+
schemes to secure schemes.
17901809

17911810
4. If the first character of |expression|'s <a grammar>`host-part`</a>
17921811
is an U+002A ASTERISK character (`*`):
@@ -1858,7 +1877,24 @@ <h5 id="match-url-to-source-expression" algorithm>
18581877
10. Return "`Matches`".
18591878

18601879
4. If |expression| is an <a>ASCII case-insensitive match</a> for "`'self'`",
1861-
and |origin| is the same as |url|'s {{URL/origin}}, return "`Matches`".
1880+
return "`Matches`" if one or more of the following conditions is met:
1881+
1882+
1. |origin| is the same as |url|'s {{URL/origin}}
1883+
1884+
2. |origin|'s {{URL/host}} is the same as |url|'s {{URL/host}},
1885+
|origin|'s {{URL/port}} and |url|'s {{URL/port} are either the same
1886+
or the <a>default ports</a> for their respective {{URL/scheme}}s, and
1887+
one or more of the following conditions is met:
1888+
1889+
1. |url|'s {{URL/scheme}} is "`https`" or "`wss`"
1890+
2. |origin|'s {{URL/scheme}} is "`http`"
1891+
1892+
Note: Like the <a grammar>`scheme-part`</a> logic above, the "`'self'`"
1893+
matching algorithm allows upgrades to secure schemes when it is safe to do
1894+
so. We limit these upgrades to endpoints running on the default port for a
1895+
particular scheme or a port that matches the origin of the protected
1896+
resource, as this seems sufficient to deal with upgrades that can be
1897+
reasonably expected to succeed.
18621898

18631899
5. Return "`Does Not Match`".
18641900

0 commit comments

Comments
 (0)