1 | # Use subresource integrity (`sri`)
|
2 |
|
3 | `sri` warns about requesting scripts or stylesheets without using
|
4 | subresource integrity.
|
5 |
|
6 | ## Why is this important?
|
7 |
|
8 | A common practice in modern web development is to use third party
|
9 | resources from CDNs or different services (analytics, ads, etc.).
|
10 | However, doing so can increase the attack surface of your web site/app.
|
11 |
|
12 | While there are techniques to verify the agent is talking with the
|
13 | right server (TLS, HSTS, etc.), an attacker (or administrator) with
|
14 | access to the server can manipulate the content with impunity.
|
15 |
|
16 | > If you want to load a crypto miner on 1,000+ websites you don't
|
17 | attack 1,000+ websites, you attack the 1 website that they all load
|
18 | content from.
|
19 | ([Scott Helme][weak link])
|
20 |
|
21 | Subresource integrity [is a standard][sri spec] that mitigates this
|
22 | by ensuring that an exact representation of a resource, and only that
|
23 | representation, loads and executes.
|
24 |
|
25 | ## What does the hint check?
|
26 |
|
27 | This hint checks that a website correctly uses SRI, more specifically:
|
28 |
|
29 | * All the downloaded resources by an `<script>` or
|
30 | `<link rel="stylesheet">` have an `integrity` attribute.
|
31 | * [The `integrity` attribute needs to be valid][sri format]. I.e.:
|
32 | it should contain something in the form of `sha(256|384|512)-HASH`,
|
33 | where `HASH` is the hashed value of the downloaded body's response
|
34 | using the previously specified algorithm (`sha256`, `sha384`, or
|
35 | `sha512`).
|
36 | * The minimum cryptographic hash function used is [`sha384`][collisions].
|
37 | If multiple ones are provided, the highest one will be used to
|
38 | determine if the baseline is met.
|
39 | * When using a cross-origin resource (e.g.: using a script hosted in
|
40 | a third party CDN), the `<script>` or `<link>` tag needs to have a
|
41 | valid [`crossorigin` attribute][crossorigin].
|
42 | * The resource is served on a [secure context][secure context]
|
43 | (i.e.: HTTPS) to guarantee the HTML and resource haven't been
|
44 | tampered during the delivery.
|
45 | * The hash from the `integrity` attribute needs to be the same as
|
46 | the one calculated using the response's body.
|
47 | * If multiple hashes are provided, at least one needs to be valid.
|
48 |
|
49 | ### Examples that **trigger** the hint
|
50 |
|
51 | Cross-origin resource with no `crossorigin` attribute:
|
52 |
|
53 | ```html
|
54 | <script src="https://example.com/example-framework.js"
|
55 | integrity="sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7">
|
56 | </script>
|
57 | ```
|
58 |
|
59 | Cross-origin resource with invalid `crossorigin` attribute:
|
60 |
|
61 | ```html
|
62 | <script src="https://example.com/example-framework.js"
|
63 | integrity="sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7"
|
64 | crossorigin="invalid">
|
65 | </script>
|
66 | ```
|
67 |
|
68 | Cross-origin resource loaded over `HTTP`:
|
69 |
|
70 | ```html
|
71 | <script src="http://example.com/example-framework.js"
|
72 | integrity="sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7"
|
73 | crossorigin="invalid">
|
74 | </script>
|
75 | ```
|
76 |
|
77 | Same-origin resource with no `integrity` and `originCriteria` set to `all`:
|
78 |
|
79 | ```html
|
80 | <link rel="stylesheet" href="/style.css">
|
81 | ```
|
82 |
|
83 | ### Examples that **pass** the hint
|
84 |
|
85 | Cross-origin resource with multiple hashes and `sha384` is one of them:
|
86 |
|
87 | ```html
|
88 | <script src="https://example.com/script.js"
|
89 | integrity="sha256-validHashHere
|
90 | sha384-validHashHere">
|
91 | </script>
|
92 | ```
|
93 |
|
94 | Cross-origin resource with valid `crossorigin` attribute:
|
95 |
|
96 | ```html
|
97 | <script src="https://example.com/example-framework.js"
|
98 | integrity="sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7"
|
99 | crossorigin="anonymous">
|
100 | </script>
|
101 | ```
|
102 |
|
103 | ## Can the hint be configured?
|
104 |
|
105 | Yes, you can define the baseline algorithm and the origin of the resources
|
106 | to analyze.
|
107 |
|
108 | ### Baseline algorithm
|
109 |
|
110 | By default the baseline algorithm is `sha384` but you can
|
111 | change it to `sha256`, or `sha512` by specifying that in the
|
112 | [`.hintrc`][hintrc] file:
|
113 |
|
114 | ```json
|
115 | {
|
116 | "connector": {...},
|
117 | "formatters": [...],
|
118 | "hints": {
|
119 | "sri": ["warning", {
|
120 | "baseline": "sha512"
|
121 | }],
|
122 | ...
|
123 | },
|
124 | ...
|
125 | }
|
126 | ```
|
127 |
|
128 | The above will validate that the `integrity` of all scripts and
|
129 | styles use `sha512`.
|
130 |
|
131 | ### Origin criteria
|
132 |
|
133 | By default, this hint will analyze only resources with a different origin.
|
134 | To change this behavior you will have to set the `originCriteria` property
|
135 | to one of the following:
|
136 |
|
137 | * `all`: All resources will be analyzed
|
138 | * `crossOrigin`: Only cross-origin resources will be analyzed
|
139 |
|
140 | The following will analyze all the resources:
|
141 |
|
142 | ```json
|
143 | {
|
144 | "connector": {...},
|
145 | "formatters": [...],
|
146 | "hints": {
|
147 | "sri": ["warning", {
|
148 | "originCriteria": "all"
|
149 | }],
|
150 | ...
|
151 | },
|
152 | ...
|
153 | }
|
154 | ```
|
155 |
|
156 | ## How to use this hint?
|
157 |
|
158 | This package is installed automatically by webhint:
|
159 |
|
160 | ```bash
|
161 | npm install hint --save-dev
|
162 | ```
|
163 |
|
164 | To use it, activate it via the [`.hintrc`][hintrc] configuration file:
|
165 |
|
166 | ```json
|
167 | {
|
168 | "connector": {...},
|
169 | "formatters": [...],
|
170 | "hints": {
|
171 | "sri": "error",
|
172 | ...
|
173 | },
|
174 | "parsers": [...],
|
175 | ...
|
176 | }
|
177 | ```
|
178 |
|
179 | **Note**: The recommended way of running webhint is as a `devDependency` of
|
180 | your project.
|
181 |
|
182 | ## Further Reading
|
183 |
|
184 | * [Using Subresource Integrity - by Frederik Braun][using sri]
|
185 | * [Subresource Integrity specification][sri spec]
|
186 | * [Protect your site from Cryptojacking with CSP + SRI - by Scott Helme][prevent cryptojacking]
|
187 | * [SRI Hash Generator][srihash generator]
|
188 |
|
189 |
|
190 |
|
191 | [collisions]: https://w3c.github.io/webappsec-subresource-integrity/#hash-collision-attacks
|
192 | [crossorigin]: https://w3c.github.io/webappsec-subresource-integrity/#is-response-eligible
|
193 | [prevent cryptojacking]: https://scotthelme.co.uk/protect-site-from-cryptojacking-csp-sri/
|
194 | [secure context]: https://w3c.github.io/webappsec-subresource-integrity/#non-secure-contexts
|
195 | [hintrc]: https://webhint.io/docs/user-guide/configuring-webhint/summary/
|
196 | [sri format]: https://w3c.github.io/webappsec-subresource-integrity/#resource-integrity
|
197 | [sri spec]: https://w3c.github.io/webappsec-subresource-integrity/
|
198 | [srihash generator]: https://www.srihash.org/
|
199 | [using sri]: https://frederik-braun.com/using-subresource-integrity.html
|
200 | [weak link]: https://scotthelme.co.uk/protect-site-from-cryptojacking-csp-sri/#theweaklink
|