Skip to content

Commit 88eb262

Browse files
authored
Initial explainer commit
1 parent 35086c1 commit 88eb262

File tree

1 file changed

+135
-89
lines changed

1 file changed

+135
-89
lines changed

README.md

Lines changed: 135 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,16 @@
1-
# Explainer for the TODO API
1+
# Explainer for script-src-v2
22

3-
**Instructions for the explainer author: Search for "todo" in this repository and update all the
4-
instances as appropriate. For the instances in `index.bs`, update the repository name, but you can
5-
leave the rest until you start the specification. Then delete the TODOs and this block of text.**
6-
7-
This proposal is an early design sketch by [TODO: team] to describe the problem below and solicit
3+
This proposal is an early design sketch by the Chrome Secure Web and Network team to describe the problem below and solicit
84
feedback on the proposed solution. It has not been approved to ship in Chrome.
95

10-
TODO: Fill in the whole explainer template below using https://tag.w3.org/explainers/ as a
11-
reference. Look for [brackets].
12-
136
## Proponents
147

15-
- [Proponent team 1]
16-
- [Proponent team 2]
17-
- [etc.]
8+
- Chrome Secure Web and Network team
189

1910
## Participate
20-
- https://github.com/explainers-by-googlers/[your-repository-name]/issues
21-
- [Discussion forum]
11+
- https://github.com/explainers-by-googlers/script-src-v2/issues
2212

23-
## Table of Contents [if the explainer is longer than one printed page]
13+
## Table of Contents
2414

2515
<!-- Update this table of contents by running `npx doctoc README.md` -->
2616
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
@@ -50,128 +40,184 @@ reference. Look for [brackets].
5040

5141
## Introduction
5242

53-
[The "executive summary" or "abstract".
54-
Explain in a few sentences what the goals of the project are,
55-
and a brief overview of how the solution works.
56-
This should be no more than 1-2 paragraphs.]
43+
We're proposing a new CSP directive to help websites protect themselves against DOM XSS. Developers will be able to allowlist scripts that are allowed to execute through the existing hashes mechanism, that will now extend to cover [script-src](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src) URLs and [eval](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval). This facilitates an easier to deploy, robust CSP policy that mitigates XSS by blocking unallowed inline and eval scripts.
5744

58-
## Goals
45+
To be secure, a policy needs to permit legitimate scripts to execute, while blocking any scripts that the application doesn't expect. In practice, this means avoiding host-based allowlists and having a strict CSP allowing the execution of scripts by using nonces or hashes.
5946

60-
[What is the **end-user need** which this project aims to address? Make this section short, and
61-
elaborate in the Use cases section.]
47+
To be easy-to-deploy, a policy should ideally not require developers to make any changes to their application other than adding CSP (usually via an HTTP header or &lt;meta> tag).
6248

63-
## Non-goals
6449

65-
[If there are "adjacent" goals which may appear to be in scope but aren't,
66-
enumerate them here. This section may be fleshed out as your design progresses and you encounter necessary technical and other trade-offs.]
50+
## **Goals**
6751

68-
## User research
6952

70-
[If any user research has been conducted to inform your design choices,
71-
discuss the process and findings. User research should be more common than it is.]
7253

73-
## Use cases
54+
* Allow sites to protect themselves from XSS attacks, even if they rely on scripts loaded via eval, or scripts loaded via script-src that change often (i.e. cases where SRI is impractical).
55+
* Provide a safe alternative for sites that currently use <code>[unsafe-eval](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_eval_expressions)</code>.
56+
* Implement this in a backwards compatible way, so websites can use it without causing breakage for users of browsers that don’t yet support the feature.
7457

75-
[Describe in detail what problems end-users are facing, which this project is trying to solve. A
76-
common mistake in this section is to take a web developer's or server operator's perspective, which
77-
makes reviewers worry that the proposal will violate [RFC 8890, The Internet is for End
78-
Users](https://www.rfc-editor.org/rfc/rfc8890).]
7958

80-
### Use case 1
59+
## <strong>Non-goals</strong>
8160

82-
### Use case 2
8361

84-
<!-- In your initial explainer, you shouldn't be attached or appear attached to any of the potential
85-
solutions you describe below this. -->
8662

87-
## [Potential Solution]
63+
* Deprecate unsafe-eval (or any other existing CSP directives).
8864

89-
[For each related element of the proposed solution - be it an additional JS method, a new object, a new element, a new concept etc., create a section which briefly describes it.]
9065

91-
```js
92-
// Provide example code - not IDL - demonstrating the design of the feature.
66+
## **Use cases**
9367

94-
// If this API can be used on its own to address a user need,
95-
// link it back to one of the scenarios in the goals section.
68+
XSS is arguably the most dangerous vulnerability class affecting web services for the past 15 years. Content Security Policy was created as a defense-in-depth mechanism to ensure that even when a document suffers from HTML injection, and thus contains arbitrary markup controlled by an attacker, the application will be protected from the execution of untrusted scripts.
9669

97-
// If you need to show how to get the feature set up
98-
// (initialized, or using permissions, etc.), include that too.
99-
```
70+
The core challenge for CSP is to distinguish between legitimate scripts (intended by the author of the page to execute and usually necessary for an application to function properly) and malicious scripts (potentially injected by an attacker via an HTML injection bug, for example, if a developer has neglected to appropriately escape attacker-controlled data when embedding it in their HTML).
10071

101-
[Where necessary, provide links to longer explanations of the relevant pre-existing concepts and API.
102-
If there is no suitable external documentation, you might like to provide supplementary information as an appendix in this document, and provide an internal link where appropriate.]
10372

104-
[If this is already specced, link to the relevant section of the spec.]
73+
### Allowlisting specific URLs for use with script-src
10574

106-
[If spec work is in progress, link to the PR or draft of the spec.]
75+
Sites that want to allowlist specific scripts for use with script-src currently have 2 options, allowlist the specific scripts contents through [subresource integrity](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity), which is not practical for scripts that change often (e.g. analytics scripts), or use [host-source](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#host-source) to allowlist hostnames, which has the issues [described in further detail below](?tab=t.0#bookmark=id.i59bvq2i29zz). These issues would be addressed if we have a mechanism to allowlist full URLs for script-src.
10776

108-
[If you have more potential solutions in mind, add ## Potential Solution 2, 3, etc. sections.]
10977

110-
### How this solution would solve the use cases
78+
### Allowlisting specific scripts for use with `eval` or `Function`
11179

112-
[If there are a suite of interacting APIs, show how they work together to solve the use cases described.]
80+
The only existing mechanism to use eval or Function is by enabling them with [unsafe-eval](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_eval_expressions), which allows all scripts. This means that currently any site that needs to use eval must expose itself to eval-based XSS risks. Allowlisting individual scripts would prevent this risk.
11381

114-
#### Use case 1
11582

116-
[Description of the end-user scenario]
83+
## **Proposed Solution**
11784

118-
```js
119-
// Sample code demonstrating how to use these APIs to address that scenario.
120-
```
12185

122-
#### Use case 2
86+
### Add new CSP directive
87+
88+
Since this proposal adds new ways to allowlist scripts, it would run into backwards compatibility issues in browsers that do not yet support it (e.g. a developer allowlists a URL they’re using in script-src, this will work in browsers that support the new functionality, but will be blocked in older browsers that do not). To address this, we propose adding a new “script-src-v2”\* directive to support the new features. This way sites can add a fallback more permissive script-src (e.g. https: or unsafe-eval) directive that older browsers (which don’t support “script-src-v2” and will ignore it) can fall back to.
89+
90+
\*The naming aims to capture that this is meant to improve coverage of script-src, however this directive does not fully replace script-src, as it doesn’t cover all of what script-src does.
91+
92+
This new directive would support a subset of what script-srcs covers, namely:
93+
94+
95+
96+
* [nonce](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#nonce-nonce_value)
97+
* [<hash_algorithm>-&lt;hash_value>](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#hash_algorithm-hash_value) (which will now cover eval)
98+
* [unsafe-hashes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#unsafe-hashes)
99+
* [strict-dynamic](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#strict-dynamic)
100+
* [unsafe-inline](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#unsafe-inline)
101+
* [unsafe-eval](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#unsafe-eval)
102+
* The new url-hashes keyword, which will cover script-src URLs, as described in the next section
103+
104+
A point of discussion is whether script-src-v2 replaces script-src if both are set, or we try to enforce both at the same time (see detailed design section below).
105+
106+
107+
### Introduce new url-hashes keyword to cover script-src attributes
108+
109+
Currently, if the CSP header is set, scripts loaded via script-src need to be allowlisted, which can only be done through [nonces](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#nonce-nonce_value) or SRI. This proposes adding a mechanism to allowlist individual URLs (the initial URL, without following redirects, since following redirects would cause a XSLeak, by exposing whether the URL triggers a redirect) via their hash by adding a new ‘url-hashes’ expression that can be added to script-src.This new url-hashes directive would support both absolute and relative URLs, e.g.:
123110

124-
[etc.]
125111

126-
## Detailed design discussion
112+
```
113+
Content-Security-Policy: script-src 'url-hashes' 'sha256-SHA256("https://example.com/script.js")';
114+
<script src="https://example.com/script.js"></script>
115+
```
127116

128-
### [Tricky design choice #1]
129117

130-
[Talk through the tradeoffs in coming to the specific design point you want to make.]
118+
or
131119

132-
```js
133-
// Illustrated with example code.
120+
121+
```
122+
Content-Security-Policy: script-src 'url-hashes' 'sha256-SHA256("script.js")';
123+
<script src="script.js"></script>
134124
```
135125

136-
[This may be an open question,
137-
in which case you should link to any active discussion threads.]
138126

139-
### [Tricky design choice 2]
140127

141-
[etc.]
128+
### Extend script hashes to cover eval
129+
130+
Similarly, scripts run within eval() currently can only be allowed via unsafe-eval, which allows any script, with no mechanism to allowlist only specific ones. This proposes that script hashes should cover scripts loaded via eval, in addition to inline scripts, e.g. given a CSP of `script-src 'sha256-SHA256(foo)'; `permitting `eval(foo);`
131+
132+
133+
### Add hashes to CSP reporting
134+
135+
In order to facilitate easier adoption, script hashes should also be added to CSP reports. This would permit a developer to set a restrictive [report-only CSP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only), and use the hashes reported to build out a narrowly-defined hash-based allowlist.
136+
137+
This necessitates adding two fields: the hash of the content of a script (for inline/eval scripts), and the hash of the URL (initial URL, without following redirects) of the script (for script src elements).
138+
139+
140+
### **Deployment use case examples**
141+
142+
143+
### Single-page applications
144+
145+
To create a hash-based policy for a static, single-page application, the developer can run tooling to parse the HTML of the application and calculate the hashes of all inline &lt;script> blocks, URLs present in &lt;script src> attributes, and code blocks used in eval or New Function() blocks.
142146

143-
## Considered alternatives
147+
The tooling can generate a list of hashes and potentially automatically insert an HTML &lt;meta> tag with their values, e.g. &lt;meta http-equiv="Content-Security-Policy" content="script-src ‘sha256-abc...” url-hashes 'sha256-xyz…'">. The developer can optionally add the 'strict-dynamic' keyword to permit allowlisted scripts to transitively load additional scripts at runtime.
144148

145-
[This should include as many alternatives as you can,
146-
from high level architectural decisions down to alternative naming choices.]
149+
This could be achieved at compilation time. Any time the application is redeployed, if the scripts have changed, the hashes will be updated to match the new script values.
147150

148-
### [Alternative 1]
149151

150-
[Describe an alternative which was considered,
151-
and why you decided against it.]
152+
### Server-side applications
152153

153-
### [Alternative 2]
154+
To semi-automatically create a strong hash-based policy for an application with a server-side component developers can use the following approach:
154155

155-
[etc.]
156156

157-
## Stakeholder Feedback / Opposition
158157

159-
[Implementors and other stakeholders may already have publicly stated positions on this work. If you can, list them here with links to evidence as appropriate.]
158+
* Set an application-wide report-only CSP of script-src 'report-hashes' 'report-sample'; report-uri /csp-reports in a production environment.
159+
* Collect the reported hashes and create a list of all the hashes of scripts executing in the production environment.
160+
* The developer could optionally investigate the reported hashes (to verify that they correspond to expected application markup) before adding them to the CSP directive and removing report-only. URLs could also be included in the report to facilitate this.
161+
* Create an enforcing policy listing all the collected hashes.
160162

161-
- [Implementor A] : Positive
162-
- [Stakeholder B] : No signals
163-
- [Implementor C] : Negative
163+
This process could also be delegated to a third-party service - the developer would only need to set a reporting CSP header and after a few days/weeks would receive a list of hashes to include in their enforcing CSP.
164164

165-
[If appropriate, explain the reasons given by other implementors for their concerns.]
165+
After the application enforces a hash-based CSP, if a developer adds a new script or modifies an existing one, they will immediately notice that the script is blocked from executing and needs a new hash to be added to the policy to be enabled.
166166

167-
## References & acknowledgements
167+
This carries a significant promise of allowing the deployment of CSP in legacy applications which don't undergo frequent changes, but which might otherwise process sensitive data.
168168

169-
[Your design will change and be informed by many people; acknowledge them in an ongoing way! It helps build community and, as we only get by through the contributions of many, is only fair.]
170169

171-
[Unless you have a specific reason not to, these should be in alphabetical order.]
170+
## **Open questions**
171+
172+
173+
### Should the new script-src-v2 directive override script-src?
174+
175+
As described in the previous section, this would launch with a new directive so it can be used only on browsers that support the new hashes functionality, while keeping the less strict directives in place to prevent breakage in older browsers that don’t yet support it. This means we have to decide whether the new directive completely replaces script-src in browsers that support it, or whether the browser attempts to enforce both (and prefers the stricter one). The main advantage of completely replacing it is that there is no ambiguity in which directives will be enforced, however it means there is an opportunity for script-src-v2 to be mistakenly configured as less strict than script-src.
176+
177+
178+
## **Considered alternatives**
179+
180+
181+
### Allowlist external scripts directly by URL, instead of URL hash
182+
183+
The `host-sources` directive allows allowlisting by hostname, but has the following limitations:
184+
185+
186+
187+
* host-sources does not include anything after the path (e.g. can allowlist /foo/bar.js, but not /jsonp?callback=foo)
188+
* host-sources follows redirects (i.e. the redirect target needs to also be part of the allowlist), which we do not want for the new directive
189+
* ‘strict-dynamic’ makes the browser ignore host-sources.
190+
191+
While it would be possible to introduce a new URL-based directive with different semantics (e.g. that includes URL parameters), including a large list of URLs may exceed the response header limit quickly. Some cursory investigation of HTTP Archive data suggests that, for large sites, hashes result in significantly shorter allowlists than do raw URLs.
192+
193+
194+
### Overload the existing unsafe-hashes keyword
195+
196+
[unsafe-hashes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy#unsafe-hashes) is an existing directive that allows hashes to apply to event handlers (if not set, hashes currently only apply to inline &lt;script> blocks). It was introduced [[1](https://github.com/w3c/webappsec-csp/issues/13#issuecomment-186708533), [2](https://docs.google.com/document/d/1_nYS4gWYO2Oh8rYDyPglXIKNsgCRVhmjHqWlTAHst7c/edit?tab=t.0#heading=h.h95n37p306j5)] because allowlisting inline scripts for event handlers is considered unsafe even when using hashes, as a script that can be safe when used for a particular event handler (e.g. `<button onclick="transferAllMyMoney()">Transfer all my money&lt;/button>`) might not be safe for a different handler (e.g. `<image src="doesnotexist.test" onerror="transferAllMyMoney() />`) or as an inline script.
197+
198+
For simplicity, we could reuse `unsafe-hashes` to have hashes apply to eval and script URLs, however in the eval case, this would mean that scripts would be implicitly allowlisted for event handlers, which is not intended. For this reason we decided not to require unsafe-hashes for eval. This design implicitly allows scripts allowlisted for eval via hashes to also be used in an inline block. This seems fine, but if it’s determined that we do need a keyword to split allowlisting scripts for eval from allowlisting them for inline use, we can add a separate eval-hashes keyword.
199+
200+
We propose using the new url-hashes keyword instead of reusing unsafe-hashes to avoid confusion from using the same directive to allow two different uses (and since allowlisting urls is not, in fact, “unsafe”).
201+
202+
203+
### report-hash keyword
204+
205+
There is also [a proposal](https://github.com/w3c/webappsec-csp/pull/693) for reporting hashes of content of all scripts, including script src elements. That proposal aims to audit the content of all scripts running on the page, while the reporting in this proposal aims to facilitate the deployment of this proposal's policy. Reporting also happens at different times in the two proposals (request time or parsing/eval time for this CSP-building proposal, and response time for the other proposal).
206+
207+
208+
## **Stakeholder Feedback / Opposition**
209+
210+
No signals yet
211+
212+
213+
## **References & acknowledgements**
172214

173215
Many thanks for valuable feedback and advice from:
174216

175-
- [Person 1]
176-
- [Person 2]
177-
- [etc.]
217+
218+
219+
* Arthur Janc
220+
* David Dworken
221+
* Domenic Denicola
222+
* Lukas Weichselbaum
223+
* Mike West

0 commit comments

Comments
 (0)