├── .github └── workflows │ └── auto-publish.yml ├── .gitignore ├── .pr-preview.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE.md ├── Makefile ├── README.md ├── index.bs ├── published ├── 2015-02-FPWD.html ├── 2015-10-CR.html ├── ECHIDNA ├── WD.html └── default.css └── w3c.json /.github/workflows/auto-publish.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | pull_request: {} 4 | push: 5 | branches: [main] 6 | 7 | jobs: 8 | main: 9 | name: Build, Validate, and Publish 10 | runs-on: ubuntu-20.04 11 | steps: 12 | - uses: actions/checkout@v2 13 | - uses: w3c/spec-prod@v2 14 | with: 15 | GH_PAGES_BRANCH: gh-pages 16 | BUILD_FAIL_ON: warning 17 | VALIDATE_LINKS: false 18 | VALIDATE_MARKUP: true 19 | W3C_ECHIDNA_TOKEN: ${{ secrets.ECHIDNA_TOKEN }} 20 | W3C_WG_DECISION_URL: https://lists.w3.org/Archives/Public/public-webappsec/2015Mar/0170.html 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | index.html 2 | -------------------------------------------------------------------------------- /.pr-preview.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_file": "index.bs", 3 | "type": "bikeshed", 4 | "params": { 5 | "force": 1 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | All documentation, code and communication under this repository are covered by the [W3C Code of Ethics and Professional Conduct](https://www.w3.org/Consortium/cepc/). 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Web Application Security Working Group 2 | 3 | Contributions to this repository are intended to become part of Recommendation-track documents 4 | governed by the [W3C Patent Policy](https://www.w3.org/Consortium/Patent-Policy/) and 5 | [Document License](https://www.w3.org/Consortium/Legal/copyright-documents). To contribute, you must 6 | either participate in the relevant W3C Working Group or make a non-member patent licensing 7 | commitment. 8 | 9 | If you are not the sole contributor to a contribution (pull request), please identify all 10 | contributors in the pull request's body or in subsequent comments. 11 | 12 | To add a contributor (other than yourself, that's automatic), mark them one per line as follows: 13 | 14 | ``` 15 | +@github_username 16 | ``` 17 | 18 | If you added a contributor by mistake, you can remove them in a comment with: 19 | 20 | ``` 21 | -@github_username 22 | ``` 23 | 24 | If you are making a pull request on behalf of someone else but you had no part in designing the 25 | feature, you can remove yourself with the above syntax. 26 | 27 | # Tests 28 | 29 | See [CONTRIBUTING.md](https://github.com/w3c/webappsec/blob/master/CONTRIBUTING.md). 30 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All documents in this Repository are licensed by contributors under the [W3C Document 2 | License](http://www.w3.org/Consortium/Legal/copyright-documents). 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: index.html 2 | 3 | force: 4 | bikeshed -f spec ./index.bs 5 | 6 | index.html: index.bs 7 | bikeshed -f spec ./index.bs 8 | 9 | CR: index.bs 10 | bikeshed -f spec --md-status=CR --md-date=2015-10-08 --md-deadline=2015-11-08 ./index.bs ./published/2015-10-CR.html 11 | 12 | clean: 13 | $(RM) index.html 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Specification 'webappsec-upgrade-insecure-requests' 3 | 4 | This is the repository for webappsec-upgrade-insecure-requests. You're welcome to contribute! Let's make the Web rock our socks 5 | off! 6 | -------------------------------------------------------------------------------- /index.bs: -------------------------------------------------------------------------------- 1 |

Upgrade Insecure Requests

2 |
   3 | Status: ED
   4 | Group: WebAppSec
   5 | ED: https://w3c.github.io/webappsec-upgrade-insecure-requests/
   6 | TR: http://www.w3.org/TR/upgrade-insecure-requests/
   7 | Previous Version: from biblio
   8 | Shortname: upgrade-insecure-requests
   9 | Editor: Carlos Joan Rafael Ibarra Lopez 117196, Google Inc., carlosil@google.com
  10 | Former Editor: Mike West 56384, Google Inc., mkwst@google.com
  11 | Abstract:
  12 |   This document defines a mechanism which allows authors to instruct a user
  13 |   agent to upgrade insecure resource requests to secure transport before
  14 |   fetching them.
  15 | Indent: 2
  16 | Level: None
  17 | Version History: https://github.com/w3c/webappsec-upgrade-insecure-requests/commits/main/index.bs
  18 | Boilerplate: omit conformance, omit feedback-header
  19 | !Participate: File an issue (open issues)
  20 | 
21 |
  22 | spec: CSP; urlPrefix: https://www.w3.org/TR/CSP/
  23 |   type: dfn
  24 |     text: content-security-policy
  25 |     text: content-security-policy-report-only
  26 |     text: default-src
  27 |     text: report-uri
  28 |     text: protected resource
  29 |     text: security policy
  30 |     text: send violation reports
  31 |     text: report a violation
  32 |     text: violation report; url: example-violation-report
  33 |     url: enforce
  34 |       text: enforce
  35 |       text: enforced
  36 |     url: monitor
  37 |       text: monitor
  38 |       text: monitored
  39 | spec: DOM; urlPrefix: http://www.w3.org/TR/dom/
  40 |   type: interface
  41 |     text: Document; url: interface-document
  42 | spec: FETCH; urlPrefix: https://fetch.spec.whatwg.org/
  43 |   type: dfn
  44 |     text: main fetch
  45 | spec: HTML; urlPrefix: https://html.spec.whatwg.org/multipage/
  46 |   type: dfn
  47 |     urlPrefix: browsers.html
  48 |       text: ancestor browsing context
  49 |       text: browsing context
  50 |       text: creating a new document object; url: create-a-document-object
  51 |       text: nested browsing context
  52 |     urlPrefix: webappapis.html
  53 |       text: environment settings object
  54 |       text: incumbent settings object
  55 |       text: responsible document
  56 |       text: responsible browsing context
  57 |       text: relevant settings object for a script
  58 | spec: MIX; urlPrefix: https://w3c.github.io/webappsec/specs/mixedcontent/
  59 |   type: dfn
  60 |     text: strict mode
  61 |     text: block-all-mixed-content
  62 | spec: SERVICE-WORKERS; urlPrefix: https://slightlyoff.github.io/ServiceWorker/spec/service_worker/
  63 |   type: interface
  64 |     text: ServiceWorker; url: service-worker-interface
  65 | spec: WORKERS; urlPrefix: http://www.w3.org/TR/workers/
  66 |   type: dfn
  67 |     text: set up a worker environment settings object; url: script-settings-for-workers
  68 |   type: interface
  69 |     text: SharedWorker
  70 |     text: Worker
  71 | spec: RFC5234; urlPrefix: https://tools.ietf.org/html/rfc5234
  72 |   type: dfn
  73 |     text: BIT; url: appendix-B.1
  74 |     text: WSP; url: appendix-B.1
  75 | spec: RFC6454; urlPrefix: https://tools.ietf.org/html/rfc6454
  76 |   type: dfn
  77 |     text: origin; url: section-3.2
  78 | spec: RFC6797; urlPrefix: https://tools.ietf.org/html/rfc6797
  79 |   type: dfn
  80 |     text: Strict-Transport-Security; url: section-6.1
  81 |     text: congruent match; url: section-8.2
  82 |     text: superdomain match; url: section-8.2
  83 |     text: includeSubDomains; url: section-6.1.2
  84 |     text: Known HSTS Host Domain Name Matching; url: section-8.2
  85 |     text: Known HSTS Host; url: section-8.1.1
  86 | spec: RFC7231; urlPrefix: https://tools.ietf.org/html/rfc7231
  87 |   type: dfn
  88 |     text: Vary; url: section-7.1.4
  89 |     text: resource representation; url: section-3
  90 | spec: RFC7234; urlPrefix: https://tools.ietf.org/html/rfc7234
  91 |   type: dfn
  92 |     text: Cache-Control; url: section-5.2
  93 |     text: no-store; url: section-5.2.2.3
  94 | spec: RFC7240; urlPrefix: https://tools.ietf.org/html/rfc7240
  95 |   type: dfn
  96 |     text: Prefer; url: section-2
  97 | 
98 | 99 | 100 |
 101 | {
 102 |   "BBC-ARCHIVE": {
 103 |     "authors": [ "Neil McIntosh" ],
 104 |     "title": "Labelling BBC Online's archived websites",
 105 |     "href": "http://www.bbc.co.uk/blogs/internet/entries/f7126d19-2afa-3231-9c4e-0f7198c468ab"
 106 |   },
 107 |   "CSP": {
 108 |     "authors": [ "Mike West", "Adam Barth", "Dan Veditz" ],
 109 |     "title": "Content Security Policy",
 110 |     "href": "https://www.w3.org/TR/CSP/",
 111 |     "status": "CR",
 112 |     "publisher": "W3C"
 113 |   },
 114 |   "NYT-HTTPS": {
 115 |     "authors": [ "Eitan Konigsburg", "Rajiv Pant", "Elena Kvochko" ],
 116 |     "title": "Embracing HTTPS",
 117 |     "href": "http://open.blogs.nytimes.com/2014/11/1%33/embracing-https/"
 118 |   },
 119 |   "WEB-HTTPS": {
 120 |     "authors": [ "Mark Nottingham" ],
 121 |     "title": "Securing the Web",
 122 |     "href": "http://www.w3.org/2001/tag/doc/web-https",
 123 |     "status": "TAG Finding",
 124 |     "publisher": "W3C"
 125 |   },
 126 |   "WORKERS": {
 127 |     "authors": [ "Ian Hickson" ],
 128 |     "title": "Web Workers",
 129 |     "href": "http://www.w3.org/TR/workers/",
 130 |     "status": "WD",
 131 |     "publisher": "W3C"
 132 |   }
 133 | }
 134 | 
135 | 136 | 145 |
146 |

Introduction

147 | 148 | This section is not normative. 149 | 150 | Increasingly, we encourage authors to transition their sites and applications 151 | away from insecure transport, and onto encrypted and authenticated connections 152 | [[WEB-HTTPS]]. While this migration has significant advantages for both 153 | authors and users, it isn't without negative side-effects. 154 | 155 | Most notably, mixed content checking [[MIX]] has the potential to cause real 156 | headache for administrators tasked with moving substantial amounts of legacy 157 | content onto HTTPS. In particular, going through old content and rewriting 158 | resource URLs manually is a huge undertaking. Moreover, it's often the case 159 | that truly legacy content is difficult or impossible to update. Consider the 160 | BBC's archived websites [[BBC-ARCHIVE]], or the New York Times' hard-coded 161 | URLs [[NYT-HTTPS]]. 162 | 163 | We should remove this burden from site authors by allowing them to assert to a 164 | user agent that they intend a site to load only secure resources, and that 165 | insecure URLs ought to be treated as though they had been replaced with equivalent secure 166 | URLs. 167 | 168 | This document defines a new Content Security Policy directive, 169 | upgrade-insecure-requests, through which authors can make 170 | this assertion. 171 | Note: Delivering the policy as a header allows an administrator to easily 172 | opt a set of pages into the upgrade mechanism without touching their source 173 | code individually. The legacy content examples above would not be feasible 174 | with an approach that inlined the policy into HTML, for example. 175 | 176 |

Goals

177 | 178 | The overarching goal is to reduce the burden of migrating websites from 179 | insecure origins by reducing the negative side effects of mixed content 180 | blocking [[MIX]]. 181 | 182 | If we assume that authors do the server-side legwork (obtaining a certificate, 183 | configuring the server, setting up redirects), and that authors also ensure 184 | that both first- and third-party content is accessible at the same 185 | [=url/host=] and [=url/path=] on a secure [=url/scheme=], then the 186 | following statements ought to hold after implementing this feature: 187 | 188 |
    189 |
  1. 190 | Authors should be able to ensure that all content requested by a given 191 | page loads successfully, and securely. Mixed content blocking should not 192 | break pages as a result of migrating to a secure origin. 193 | 194 | Note: This requirement is not met by Mixed Content's strict 195 | mode, which makes something like the opposite assertion. 196 |
  2. 197 |
  3. 198 | As a result of #1, the user agent should not degrade any security 199 | indicators related to requesting mixed content, as no insecure content 200 | should be requested. 201 |
  4. 202 |
  5. 203 | Authors should be able to ensure that all internal links correctly send 204 | users to the site's secure address, and not to its pre-migration insecure 205 | address. 206 |
  6. 207 |
  7. 208 | Authors should be able to achieve all these goals without editing a site's 209 | content. This is particularly important for archived content and legacy 210 | systems for which maintenance is difficult enough, never mind upgrades. 211 |
  8. 212 |
  9. 213 | Authors should be able to pursue a gradual transition from insecure to 214 | secure, serving secure resources to clients that support upgrades, while 215 | retaining insecure resources for clients that don't. 216 |
  10. 217 |
218 | 219 | Note: The mechanism defined here does not intend to supplant Strict 220 | Transport Security [[RFC6797]]. See [[#relation-to-hsts]] for details. 221 | 222 |

Examples

223 | 224 |

Non-navigational Upgrades

225 | 226 |
227 | Megacorp, Inc. wishes to migrate http://example.com/ to 228 | https://example.com. They set up their servers 229 | to make their own resources available over HTTPS, and work with partners in 230 | order to make third-party widgets available securely as well. 231 | 232 | They quickly realize, however, that the majority of their content is locked 233 | up in a database tied to an old content management system, and it contains 234 | hardcoded links to insecure resources (e.g., http:// URLs to images and 235 | other content). Unfortunately, it's a substantial amount of work to update 236 | it. 237 | 238 | As a stopgap measure, Megacorp injects the following header field into every 239 | HTML response that goes out from their servers: 240 | 241 |
 242 |       Content-Security-Policy: upgrade-insecure-requests
 243 |     
244 | 245 | This automatically upgrades all insecure resource requests from their pages 246 | to secure variants, allowing a user agent to treat the following HTML code: 247 | 248 |
 249 |       <img src="http://example.com/image.png">
 250 |       <img src="http://not-example.com/image.png">
 251 |     
252 | 253 | as though it had been delivered as: 254 | 255 |
 256 |       <img src="https://example.com/image.png">
 257 |       <img src="https://not-example.com/image.png">
 258 |     
259 | 260 | The URL will be rewritten before the request is made, meaning that no 261 | insecure requests will hit the network. Users will be safer, and Megacorp's 262 | administrators will be happier, as all resource requests will be 263 | transparently upgraded with no effort on their part. 264 |
265 | 266 |

Navigational Upgrades

267 | 268 |
269 | Megacorp, Inc. isn't quite ready to deliver Strict Transport Security 270 | headers [[RFC6797]], but does want to keep users on secure pages when 271 | possible. Happily, this comes for free with 272 | upgrade-insecure-requests. That is, they're already 273 | delivering pages with the following header: 274 | 275 |
 276 |       Content-Security-Policy: upgrade-insecure-requests
 277 |     
278 | 279 | This allows user agents to treat the following HTML code: 280 | 281 |
 282 |       <a href="http://example.com/">Home</a>
 283 |     
284 | 285 | as though it had been delivered as: 286 | 287 |
 288 |       <a href="https://example.com/">Home</a>
 289 |     
290 | 291 | Links to third-party sites will not be upgraded. That is, the following 292 | HTML code: 293 | 294 |
 295 |       <a href="http://not-example.com/">Home</a>
 296 |     
297 | 298 | won't be upgraded. 299 |
300 | 301 |

Failed Upgrade

302 | 303 |
304 | Tinycorp, Inc. enabled upgrade-insecure-requests a bit 305 | earlier than they should have, as they don't actually support HTTPS on 306 | http://cdn.example.com/. Given the following code: 307 | 308 |
 309 |       <img src="http://cdn.example.com/image.png">
 310 |     
311 | 312 | User agents will upgrade requests, as described in [[#example-nonnavigational]], 313 | rewriting the URL as https://cdn.example.com/image.png. As the 314 | server doesn't respond to secure requests, this results in a network error. 315 | 316 | There is no fallback in this scenario: the user agent acts just as though 317 | the request had been intentionally made, and the request fails. 318 |
319 | 320 |

Recommendations

321 | 322 | We recommend that authors who wish to ensure that user agents which support 323 | upgrade-insecure-requests are as secure as possible do the following: 324 | 325 |
    326 |
  1. 327 | Redirect insecure, safely upgradable requests from HTTP to HTTPS by 328 | responding with a Location header and a 307 329 | status code. 330 | 331 |
    332 | In Nginx, this kind of redirection might look like this: 333 | 334 |
     335 |             server {
     336 |               if ($http_upgrade_insecure_requests = "1") {
     337 |                 add_header Vary Upgrade-Insecure-Requests;
     338 |                 return 307 https://$host$request_uri;
     339 |               }
     340 |             }
     341 |         
    342 | 343 | This is, of course, greatly simplified; your configuration will likely 344 | be significantly more complex. 345 |
    346 |
  2. 347 |
  3. 348 | Respond to potentially trustworthy URL safely 349 | upgradable requests with a upgrade-insecure-requests 350 | directive if necessary for the resource being requested. 351 | 352 |
    353 | In Nginx, adding this directive might look like this: 354 | 355 |
     356 |             server {
     357 |               ...
     358 | 
     359 |               add_header Content-Security-Policy upgrade-insecure-requests;
     360 | 
     361 |               ...
     362 |             }
     363 |         
    364 | 365 | This is, of course, greatly simplified; your configuration will likely 366 | be significantly more complex. 367 |
    368 |
  4. 369 |
  5. 370 | If the origin is HSTS-safe, then protect 371 | against SSL-stripping man-in-the-middle attacks by sending a 372 | Strict-Transport-Security header with the 373 | preload directive, and ensure that insecure content is 374 | never loaded by enabling Mixed Content's strict mode. 375 | 376 |
    377 | In Nginx, adding this header might look like this (note the use of 378 | the preloaded directive, which signifies that this 379 | origin's HSTS state can be safely imported into user agents' HSTS 380 | preload lists): 381 | 382 |
     383 |             server {
     384 |               ...
     385 | 
     386 |               add_header Strict-Transport-Security "max-age=10886400; preload"
     387 |               add_header Content-Security-Policy block-all-mixed-content;
     388 | 
     389 |               ...
     390 |             }
     391 |         
    392 | 393 | This is, of course, greatly simplified; your configuration will likely 394 | be significantly more complex. 395 |
    396 | 397 | Additionally, work with user agent vendors to add the origin to 398 | HSTS Preload Lists (for example, by submitting the origin to 399 | hstspreload.appspot.com). 400 |
  6. 401 |
  7. 402 | If the origin is conditionally HSTS-safe, then opt-into HSTS only 403 | in response to safely upgradable requests. 404 | 405 |
    406 | In Nginx, adding this header conditionally might look like this (note 407 | the use of map, as setting headers inside if 408 | without returning immediately is, well, iffy): 409 | 410 |
     411 |             server {
     412 |               ...
     413 | 
     414 |               map $http_https $sts {
     415 |                 "1" "max-age=10886400"
     416 |               }
     417 | 
     418 |               add_header Strict-Transport-Security $sts;
     419 | 
     420 |               ...
     421 |             }
     422 |         
    423 | 424 | This is, of course, greatly simplified; your configuration will likely 425 | be significantly more complex. 426 |
    427 |
  8. 428 |
429 |
430 | 431 | 440 |
441 |

Key Concepts and Terminology

442 | 443 | : upgrade 444 | :: A [=/request=] is said to be upgraded if it is rewritten 445 | to contain a URL with a [=url/scheme=] of https or 446 | wss. 447 | 448 | : safely upgradable requests 449 | :: A [=/request=] is said to be safely upgradable if the 450 | resource representation which will be returned does not require the 451 | upgrade-insecure-requests mechanism described in this 452 | document to avoid breakage, or if the [=/request=]'s 453 | [=request/header list=] contains an 454 | Upgrade-Insecure-Requests header field with a value of 455 | 1. 456 | 457 | : HSTS-safe origin 458 | :: An origin is said to be HSTS-safe if no 459 | resource representations it returns requires the the 460 | upgrade-insecure-requests mechanism described in 461 | this document to avoid breakage, and if all resource representations 462 | it returns can be served over HTTPS. 463 | 464 | HSTS-safe origins can safely opt-into 465 | Strict-Transport-Security for all user agents, 466 | without risking broken pages for user agents which do not support 467 | upgrade-insecure-requests. 468 | 469 | : conditionally HSTS-safe origin 470 | :: An origin is said to be conditionally HSTS-safe 471 | if one or more resource representations it returns requires the 472 | upgrade-insecure-requests mechanism described in 473 | this document to avoid breakage, and if all resource representations it 474 | returns can be served over HTTPS. 475 | 476 | Conditionally HSTS-safe origins can safely opt-into 477 | Strict-Transport-Security only for user agents which 478 | support upgrade-insecure-requests. 479 | 480 | : preloadable HSTS host 481 | :: A [=url/host=] host is a preloadable HSTS 482 | host if, when performing Known HSTS Host Domain Name 483 | Matching, host is a superdomain match for a 484 | Known HSTS Host which asserts both the includeSubDomains 485 | directive and the preload directive, or host 486 | is a congruent matchfor a Known HSTS Host which asserts 487 | the preload directive. 488 | 489 | Note: This is a long way of saying "any host the user agent has pinned 490 | with a Strict-Transport-Security header that contained 491 | a preload directive". 492 | 493 | The Augmented Backus-Naur Form (ABNF) notation used in [[#delivery]] is 494 | specified in RFC5234. [[!ABNF]] 495 |
496 | 497 | 498 |
499 |

Upgrading Insecure Resource Requests

500 | 501 | In order to allow authors to mitigate the negative side-effects of migration 502 | away from insecure origins, authors may instruct the user agent to 503 | transparently upgrade resource requests to potentially trustworthy URL 504 | variants of the original request's URL. 505 | 506 | To support this instruction: 507 | 508 |
    509 |
  1. 510 | Environment settings objects and browsing contexts are 511 | given an insecure requests policy which has two 512 | potential values Do Not 513 | Upgrade and 514 | Upgrade. It is 515 | set to Do Not Upgrade unless otherwise specified. This policy 516 | is checked in [[#upgrade-request]] in order to determine whether or not 517 | non-navigation requests and form submissions should be upgraded during 518 | [=/fetching=]. 519 |
  2. 520 |
  3. 521 | Environment settings objects and browsing contexts are 522 | given an upgrade insecure navigations set which 523 | contains a set of ([=url/host=], [=url/port=]) tuples to which navigations 524 | ought to be upgraded. Its value is the empty set unless otherwise 525 | specified. This set is checked in [[#upgrade-request]] in order to 526 | determine whether or not navigation requests should be upgraded. 527 |
  4. 528 |
529 | 530 |

531 | The upgrade-insecure-requests Content Security Policy directive 532 |

533 | 534 | A server MAY instruct a user agent to upgrade insecure requests for a 535 | particular protected resource by sending a 536 | Content-Security-Policy header [[!CSP]] that contains a 537 | upgrade-insecure-requests directive, defined via the 538 | following ABNF grammar: 539 | 540 |
 541 |     directive-name  = "upgrade-insecure-requests"
 542 |     directive-value = ""
 543 |   
544 | 545 | When enforcing the upgrade-insecure-requests directive: 546 | 547 |
    548 |
  1. 549 | Let settings be the protected resource's incumbent 550 | settings object. 551 |
  2. 552 |
  3. 553 | Set settings's insecure requests policy to 554 | Upgrade. 555 |
  4. 556 |
  5. 557 | Let tuple be a tuple of the protected resource's 558 | [=/URL=]'s [=url/host=] and [=url/port=]. 559 |
  6. 560 |
  7. 561 | Insert tuple into settings's upgrade insecure 562 | navigations set. 563 |
  8. 564 |
565 | 566 | Monitoring the upgrade-insecure-requests directive has 567 | no effect: the directive is ignored when sent via a 568 | Content-Security-Policy-Report-Only header. Authors can 569 | determine whether or not upgraded resources' original URLs 570 | were insecure via Content-Security-Policy-Report-Only. For 571 | example, Content-Security-Policy-Report-Only: 572 | default-src https:; report-uri /endpoint. See [[#reporting-upgrades]] 573 | for additional detail. 574 | 575 |

Relation to "Mixed Content"

576 | 577 | The upgrade-insecure-requests directive results in 578 | requests being rewritten at the top of the [=/Fetching=] algorithm 579 | [[!FETCH]], as specified in [[#upgrade-request]]. It's important to note that 580 | the rewrite happens before either Mixed Content [[MIX]] or Content 581 | Security Policy checks take effect [[CSP]]. 582 | 583 | This ordering means that upgraded requests will not be flagged as 584 | mixed content. Moreover, it means that 585 | upgrade-insecure-requests's effect takes place before 586 | the block-all-mixed-content directive would have a chance 587 | to block the request. If the former is set, the latter is effectively a no-op. 588 | 589 | We recommend that authors set one directive or the other, as outlined in 590 | [[#recommendations]]. 591 | 592 |

Feature Detecting Clients Capable of Upgrading

593 | 594 | Sites which require the upgrade mechanism laid out in this document in order 595 | to provide users with a reasonable experience over secure transit need some 596 | way to determine whether or not a particular [=/request=] can safely be 597 | redirected from HTTP to HTTPS (and vice-versa). Moreover, conditionally 598 | HSTS-safe origins can only opt-into 599 | Strict-Transport-Security for supported user agents, and 600 | doing otherwise could have negative consequences for the site's users. 601 | 602 | Rather than relying on user-agent sniffing to make this decision, user agents 603 | can advertise their upgrade capability when making navigation requests 604 | by including an Upgrade-Insecure-Requests header field as 605 | described in [[#preference]]. 606 | 607 |

608 | The Upgrade-Insecure-Requests HTTP Request Header Field 609 |

610 | 611 | The 612 | Upgrade-Insecure-Requests HTTP request header 613 | field sends a signal to the server expressing the client's preference 614 | for an encrypted and authenticated response, and that it can successfully 615 | handle the upgrade-insecure-requests directive in order 616 | to make that preference as seamless as possible to provide. 617 | 618 | This preference is represented by the following ANBF: 619 | 620 |
 621 |     "Upgrade-Insecure-Requests:" *WSP "1" *WSP
 622 |   
623 | 624 | Note: Though the Upgrade-Insecure-Requests header expresses a 625 | preference, sending it via the existing Prefer header is 626 | problematic, as we expect the response from the server to use it as part of 627 | the cache key. Vary: Prefer is too broad, as discussed in 628 | w3/webappsec#216. 629 | 630 | User agent conformance details are described in step #1 of the the 631 | [[#upgrade-request]] algorithm. That step represents the following 632 | requirements: 633 | 634 |
    635 |
  1. 636 | User agents MUST send an Upgrade-Insecure-Requests header 637 | field along with [=/request=]s for insecure URLs. 638 | 639 | Note: Servers can use this signal to upgrade HTTP requests to HTTPS for 640 | pages that require upgrade-insecure-requests support. 641 |
  2. 642 |
  3. 643 | User agents MUST send an Upgrade-Insecure-Requests header 644 | field along with [=/request=]s for potentially trustworthy URLs 645 | whose [=request/URL=]'s 646 | [=url/host=] is not a preloadable HSTS host. 647 | 648 | Note: Servers can use the absence of this signal to downgrade HTTPS 649 | requests to HTTP for pages that require 650 | upgrade-insecure-requests support. 651 |
  4. 652 |
  5. 653 | User agents SHOULD periodically send an 654 | Upgrade-Insecure-Requests header field along with 655 | [=/request=]s for potentially trustworthy URLs 656 | whose [=request/URL=]'s [=url/host=] is a 657 | preloadable HSTS host. For example, user agents could send an 658 | Upgrade-Insecure-Requests header field only when 659 | the asserted max-age is a few days from expiration, or 660 | only for a small percentage of requests. 661 | 662 | Note: preloadable HSTS hosts have asserted that they are 663 | HSTS-safe, and therefore don't need a downgrade signal. They will 664 | need to refresh HSTS status before the asserted max-age 665 | expires, and the Upgrade-Insecure-Requests header 666 | field serves as a fine signal that HSTS could be refreshed. 667 |
  6. 668 |
669 | 670 | When a server encounters this preference in an HTTP request's headers, it 671 | SHOULD redirect the user to a potentially trustworthy URL variant 672 | of the resource being requested. 673 | 674 | When a server encounters this preference in an HTTPS request's headers, 675 | it SHOULD include a Strict-Transport-Security header in 676 | the response if the request's [=url/host=] is HSTS-safe or 677 | conditionally HSTS-safe [[RFC6797]]. 678 | 679 |
680 | A client that supports this document's upgrade mechanism requests 681 | http://example.com/ as follows: 682 | 683 |
 684 |       GET / HTTP/1.1
 685 |       Host: example.com
 686 |       Upgrade-Insecure-Requests: 1
 687 |     
688 | 689 | The server parses the preference, notices that the user's client can deal 690 | well with upgrade requests, and therefore responds to the request by 691 | redirecting the user to a secure version of the resource she's requesting: 692 | 693 |
 694 |       HTTP/1.1 307 Moved Temporarily
 695 |       Location: https://example.com/
 696 |       Vary: Upgrade-Insecure-Requests
 697 |     
698 | 699 | The Upgrade-Insecure-Requests 700 | header field is listed in the Vary header, as the 701 | redirect response might otherwise be served by caches to clients that 702 | don't support the upgrade mechanism defined here. A similar effect could be 703 | achieved by making this redirect response uncachable via the 704 | Cache-Control header: 705 | 706 |
 707 |       HTTP/1.1 307 Moved Temporarily
 708 |       Location: https://example.com/
 709 |       Cache-Control: no-store
 710 |     
711 |
712 | 713 |

Policy Inheritance

714 | 715 | If a {{Document}}'s incumbent settings object's insecure requests 716 | policy is set to Upgrade, the user agent MUST ensure that 717 | all nested browsing contexts inherit the setting in the following ways: 718 | 719 |
    720 |
  1. 721 | When a nested browsing context context is created: 722 | 723 |
      724 |
    1. 725 | If context's embedding document's insecure 726 | requests policy is Upgrade, then: 727 | 728 |
        729 |
      1. 730 | Set context's insecure requests policy to 731 | Upgrade. 732 |
      2. 733 |
      3. 734 | For each value in context's embedding 735 | document's upgrade insecure navigations set, add 736 | value to context's upgrade insecure 737 | navigations set. 738 |
      4. 739 |
      740 |
    2. 741 |
    742 |
  2. 743 |
  3. 744 | When creating a new Document object 745 | document in a browsing context context: 746 | 747 |
      748 |
    1. 749 | If context's insecure requests policy is 750 | Upgrade, then: 751 | 752 |
        753 |
      1. 754 | Let settings be document's incumbent 755 | settings object. 756 |
      2. 757 |
      3. 758 | Set settings' insecure requests policy to 759 | Upgrade. 760 |
      4. 761 |
      5. 762 | For each value in context's upgrade 763 | insecure navigations set, add value to 764 | settings's upgrade insecure navigations set. 765 |
      6. 766 |
      767 |
    2. 768 |
    769 |
  4. 770 |
771 | 772 | Likewise, when spinning up a worker, the user agent MUST ensure that it 773 | inherits the setting from the context that created it in the following ways: 774 | 775 |
    776 |
  1. 777 | When executing the set up a worker environment settings object 778 | algorithm, perform the following steps after the current step #4: 779 | 780 |
      781 |
    1. 782 | If inherited responsible browsing context's insecure 783 | requests policy is Upgrade, then: 784 | 785 |
        786 |
      1. 787 | Set settings object's insecure requests policy 788 | to Upgrade. 789 |
      2. 790 |
      3. 791 | For each value in inherited responsible browsing 792 | context's upgrade insecure navigations set, add 793 | value to settings object's upgrade 794 | insecure navigations set. 795 |
      4. 796 |
      797 |
    2. 798 |
    799 |
  2. 800 |
801 | 802 |

Reporting Upgrades

803 | 804 | Upgrading insecure requests MUST not interfere with an authors' ability to 805 | track down requests that would be insecure in a user agent that does not 806 | support upgrades. To that end, upgrades MUST be performed after 807 | evaluating request against all monitored security policies, 808 | but before evaluating request against all enforced 809 | policies. 810 | 811 |
812 | Within the context of a protected resource which contains the 813 | insecure image <img src="http://example.com/image.png">, 814 | and delivers the following HTTP headers: 815 | 816 |
 817 |       Content-Security-Policy: upgrade-insecure-requests; default-src https:
 818 |       Content-Security-Policy-Report-Only: default-src https:; report-uri /endpoint
 819 |     
820 | 821 | The user agent will fire off a [=/request=] request that: 822 | 823 |
    824 |
  1. 825 | Violates the policy being monitored, thereby delivering a 826 | violation report to /endpoint. 827 |
  2. 828 |
  3. 829 | Is upgraded from http://example.com/image.png to 830 | https://example.com/image.png. 831 |
  4. 832 |
  5. 833 | Does not violate the policy being enforced. 834 |
  6. 835 |
836 |
837 | 838 | Note: This will be significantly clarified once [[CSP]] is rewritten in terms 839 | of [[FETCH]]. 840 |
841 | 842 | 843 |
844 |

Processing Algorithms

845 | 846 |

847 | Upgrade request to a potentially trustworthy URL, if appropriate 848 |

849 | 850 | Given a [=/request=] request, this algorithm will rewrite its 851 | [=request/URL=] if the [=request/client=] from which the request originates 852 | has opted-in to upgrades. It will also inject an 853 | Upgrade-Insecure-Requests header field header for 854 | insecure navigation requests in order to improve a server's ability to 855 | feature-detect a client's upgrade capabilities. 856 | 857 | We will not upgrade cross-origin navigation requests, with the 858 | exception of form submissions. Form submissions will be upgraded to mitigate 859 | the risk of data leakage via plaintext submissions. 860 | 861 | Note: This algorithm is called at the top of the Main Fetch algorithm. 862 | 863 |
    864 |
  1. 865 | If request is a navigation request, [=header list/append=] a 866 | header named Upgrade-Insecure-Requests with a value of 867 | 1 to request's 868 | [=request/header list=] if any of the following 869 | criteria are met: 870 | 871 |
      872 |
    1. 873 | request's [=request/URL=] is not a 874 | potentially trustworthy URL 875 |
    2. 876 |
    3. 877 | request's [=request/URL=]'s [=url/host=] 878 | is not a preloadable HSTS host 879 |
    4. 880 |
    881 | 882 | Note: User agents can choose to append the 883 | Upgrade-Insecure-Requests header field for other 884 | requests, as discussed in [[#preference]]. 885 |
  2. 886 |
  3. 887 | If request is a navigation request, then: 888 | 889 |
      890 |
    1. 891 | If request is a form submission, skip the remaining 892 | substeps, and continue upgrading request. 893 |
    2. 894 |
    3. 895 | If request's [=request/client=]'s 896 | [=environment/target browsing context=] 897 | is a nested browsing context, skip the remaining substeps 898 | and continue upgrading request. 899 |
    4. 900 |
    5. 901 | Let tuple be a tuple of request's 902 | [=request/URL=]'s [=url/host=] and [=url/port=]. 903 |
    6. 904 |
    7. 905 | If tuple is contained in [=request/client=]'s 906 | upgrade insecure navigations set, then skip the remaining 907 | substeps, and continue upgrading request. 908 | 909 |
    8. 910 |
    9. 911 | Return without further modifying request. 912 |
    10. 913 |
    914 | 915 | Note: We only upgrade top-level navigation requests for hosts 916 | that have explicitly opted-into the behavior for a particular 917 | protected resource, as described in [[#examples]]. Performing 918 | upgrades for top-level navigations to third-party resources brings a 919 | significantly higher potential for breakage, so we're avoiding it for 920 | the moment. Nested navigations (via <{iframe}>, for example) affect 921 | the security status of their embedder, so we ensure that they are 922 | upgraded if necessary. 923 |
  4. 924 |
  5. 925 | Let upgrade state be the result of executing 926 | [[#should-upgrade-for-client]] upon request's 927 | [=request/client=]. 928 |
  6. 929 |
  7. 930 | If upgrade state is Do Not Upgrade, return without 931 | modifying request. 932 |
  8. 933 |
  9. 934 | If request's [=request/URL=]'s [=url/scheme=] is 935 | "http", set request's [=request/URL=]'s 936 | [=url/scheme=] to "https", and return. 937 |
  10. 938 |
939 | 940 | Note: Due to [[FETCH]]'s recursive nature, this algorithm will upgrade 941 | insecurely-redirected requests as well as insecure initial requests. 942 | 943 |

944 | Should insecure [=/request=]s be upgraded for client? 945 |

946 | 947 | Given an [=/request=]'s [=request/client=] 948 | client (an environment settings object), this algorithm 949 | returns Enforced Upgrade if insecure requests associated with 950 | that client should be upgraded, or Do Not Upgrade otherwise. In 951 | short, this will check the client and return the appropriate insecure 952 | requests policy set on it or its browsing context. 953 | 954 |
    955 |
  1. 956 | If client has a responsible document, return the value 957 | of its insecure requests policy. 958 | 959 | Note: This catches {{Document}}s or {{Worker}}s whose policy is set 960 | directly by the upgrade-insecure-requests directive, 961 | or which have inherited the policy from an embedding document. 962 |
  2. 963 |
  3. 964 | If client has a responsible browsing context, return the 965 | value of its insecure requests policy. 966 | 967 | Note: This catches requests triggered from detached 968 | [=request/client=]s. Not sure this is necessary, really, 969 | given the inheritance structure defined in [[#nesting]]. 970 |
  4. 971 |
  5. 972 | Return Do Not Upgrade. 973 |
  6. 974 |
975 |
976 | 977 |
978 |

Security Considerations

979 | 980 |

Interaction with HSTS

981 | 982 | The upgrade-insecure-requests directive does not replace 983 | the Strict-Transport-Security HTTP response header 984 | [[RFC6797]]. Authors who serve their site over secure transport SHOULD send 985 | that header with an appropriate max-age in order to ensure that 986 | users are not subject to SSL stripping attacks by maliciously active network 987 | attackers, or monitoring by maliciously passive network attackers. 988 | 989 |

CSP Violation Reports

990 | 991 | When sending a violation report for an upgraded resource, user agents MUST 992 | target the {{Document}} or {{Worker}} that triggered the request, rather 993 | than the {{Document}} or {{Worker}} on which the 994 | upgrade-insecure-requests directive was set. Due to 995 | [[#nesting]], the latter might be a cross-origin ancestor of the former, and 996 | sending violation reports to that set of reporting endpoints could leak data 997 | in unexpected ways. 998 | 999 | Likewise, the SecurityPolicyViolationEvent MUST NOT target any 1000 | {{Document}} other than the one which triggered the request, for the same 1001 | reasons. 1002 |
1003 | 1004 |
1005 |

Performance Considerations

1006 | 1007 | The upgrade mechanism specified here adds Upgrade-Insecure-Requests: 1008 | 1\r\n to every outgoing navigation request to non-preloadable 1009 | HSTS hosts (as discussed at length on public-webappsec@, and 1010 | w3c/webappsec#216). 1011 | The advantages and intent of the header are laid out in [[#preference]], and 1012 | though we've taken some steps to ensure that it won't be a permanent fixture 1013 | of the platform (by carving out preloadable HSTS hosts), it's going 1014 | to be a long, long time before the header vanishes. 1015 | 1016 | User agents are encouraged to find additional carveouts, and implement them. 1017 |
1018 | 1019 |
1020 |

Authoring Considerations

1021 | 1022 |

Legacy Clients

1023 | 1024 | Legacy clients which do support mixed content blocking [[MIX]], but do not 1025 | support the upgrade-insecure-requests directive will 1026 | continue to have a suboptimal experience on pages containing insecure URLs. 1027 | Authors SHOULD ensure that they collect 1028 | violation reports in order to determine 1029 | which resources are most problematic for their users, and SHOULD use that 1030 | information to prioritize fixes for URLs in legacy content that users will 1031 | most likely request. 1032 | 1033 |

Relation to HSTS

1034 | 1035 | The mechanism specified here deals only with the security policy for a 1036 | specific protected resource. It does not deprecate, replace, or in any 1037 | way reduce the value of the Strict-Transport-Security HTTP 1038 | response header [[RFC6797]]. Authors can and should continue to use that 1039 | header to ensure that their users are not subject to SSL stripping downgrade 1040 | attacks, as the upgrade-insecure-requests directive will 1041 | not ensure that users visiting your site via links on third-party sites will 1042 | be upgraded to HTTPS for the top-level navigation. 1043 | 1044 | Likewise, the Strict-Transport-Security header does not imply 1045 | the behavior that upgrade-insecure-requests activates. 1046 | It only ensures that resources requested from an origin will never hit the 1047 | network insecurely. 1048 | 1049 | We are intentionally keeping these concepts distinct, as authors may choose 1050 | to activate one or the other behavior, but ought not be forced to bind them 1051 | together. 1052 | 1053 |
1054 | 1055 |
1056 |

IANA Considerations

1057 | 1058 |

1059 | Upgrade-Insecure-Requests Header 1060 |

1061 | 1062 | The permanent message header field registry should be updated 1063 | with the following registration: [[!RFC3864]] 1064 | 1065 |
1066 |
Header field name
1067 |
Upgrade-Insecure-Requests
1068 | 1069 |
Applicable protocol
1070 |
http
1071 | 1072 |
Status
1073 |
standard
1074 | 1075 |
Author/Change controller
1076 |
W3C
1077 | 1078 |
Specification document
1079 |
This specification (See [[#preference]])
1080 |
1081 | 1082 |

1083 | Upgrade-Insecure-Requests Directive 1084 |

1085 | 1086 | The Content Security Policy Directive registry should be updated with the 1087 | following registration: [[!RFC7762]] 1088 | 1089 |
1090 |
Directive name
1091 |
Upgrade-Insecure-Requests
1092 | 1093 |
Reference
1094 |
This specification (See [[#delivery]])
1095 |
1096 |
1097 | 1098 |
1099 |

Acknowledgements

1100 | 1101 | Anne van Kesteren helped ensure that the initial draft of this document was 1102 | sane. Peter Eckersley and Daniel Kahn Gillmor clarified the problem space, and 1103 | helped point out the impact. 1104 |
1105 | -------------------------------------------------------------------------------- /published/2015-02-FPWD.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Upgrade Insecure Requests 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 |

28 |

29 | 30 |

Upgrade Insecure Requests

31 | 32 |

W3C First Public Working Draft, 33 |

34 | 35 |
36 |
37 |
This version: 38 |
http://www.w3.org/TR/2015/WD-upgrade-insecure-requests-20150226/ 39 |
Latest version: 40 |
http://www.w3.org/TR/upgrade-insecure-requests/ 41 |
Editor's Draft: 42 |
https://w3c.github.io/webappsec/specs/upgrade/ 43 |
Feedback: 44 |
public-webappsec@w3.org with subject line “[upgrade-insecure-requests] … message topic …” (archives) 45 |
Issue Tracking: 46 |
Inline In Spec 47 |
Editor: 48 |
(Google Inc.) 49 |
50 |
51 | 52 |
53 | 54 | 56 | 57 |
58 |
59 | 60 | 61 |

Abstract

62 | 63 |
64 |

This document defines a mechanism which allows authors to instruct a user 65 | 66 | agent to upgrade a priori insecure resource requests to 67 | secure transport before Fetching them.

68 | 69 |
70 | 71 | 72 |

Status of this document

73 | 74 |
75 |

76 | This section describes the status of this document at the time of 77 | its publication. Other documents may supersede this document. A list of 78 | current W3C publications and the latest revision of this technical report 79 | can be found in the W3C technical reports 80 | index at http://www.w3.org/TR/. 81 | 82 |

83 |

84 | This document was published by the 85 | Web Application Security Working Group 86 | as a Working Draft. This document is intended to become a W3C Recommendation. 87 | 88 |

89 |

90 | The (archived) public mailing list 91 | public-webappsec@w3.org 92 | (see instructions) 93 | is preferred for discussion of this specification. 94 | When sending e-mail, 95 | please put the text “upgrade-insecure-requests” in the subject, 96 | preferably like this: 97 | “[upgrade-insecure-requests] …summary of comment…” 98 | 99 |

100 |

101 | This document is a First Public Working Draft. 102 | 103 |

104 |

105 | Publication as a First Public Working Draft does not imply endorsement by the W3C 106 | Membership. This is a draft document and may be updated, replaced or 107 | obsoleted by other documents at any time. It is inappropriate to cite this 108 | document as other than work in progress. 109 | 110 |

111 |

112 | This document was produced by the 113 | Web Application Security Working Group. 114 | 115 |

116 |

117 | This document was produced by a group operating under 118 | the 5 February 2004 W3C Patent Policy. 119 | W3C maintains a public list of any patent disclosures 120 | made in connection with the deliverables of the group; 121 | that page also includes instructions for disclosing a patent. 122 | An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) 123 | must disclose the information in accordance with section 6 of the W3C Patent Policy. 124 | 125 |

126 |

127 | This document is governed by the 1 August 2014 W3C Process Document. 128 |

129 | 130 |
131 | 132 | 133 |

Table of Contents

134 | 135 |
136 |
197 | 198 |
199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 |
209 | 210 |

1. Introduction

211 | 212 | 213 |

This section is not normative.

214 | 215 | 216 |

Increasingly, we encourage authors to transition their sites and applications 217 | away from insecure transport, and onto encrypted and authenticated connections 218 | [WEB-HTTPS]. While this migration has significant advantages for both 219 | authors and users, it isn’t without negative side-effects.

220 | 221 | 222 |

Most notably, mixed content checking [MIX] has the potential to cause real 223 | headache for administrators tasked with moving substantial amounts of legacy 224 | content onto HTTPS. In particular, going through old content and rewriting 225 | subresource URLs manually is a huge undertaking. Moreover, it’s often the case 226 | that truly legacy content is difficult or impossible to update. Consider the 227 | BBC’s archived websites [BBC-ARCHIVE], or the New York Times' hard-coded 228 | URLs [NYT-HTTPS].

229 | 230 | 231 |

We should remove this burden from site authors by allowing them to assert to a 232 | user agent that they intend a site to load only secure resources, and that 233 | insecure URLs ought to be treated as though they had been replaced with equivalent secure 234 | URLs.

235 | 236 | 237 |

This document defines a new Content Security Policy directive, 238 | upgrade-insecure-requests, through which authors can make 239 | this assertion. 240 | Note: Delivering the policy as a header allows an administrator to easily 241 | opt a set of pages into the upgrade mechanism without touching their source 242 | code individually. The legacy content examples above would not be feasible 243 | with an approach that inlined the policy into HTML, for example.

244 | 245 | 246 |

1.1. Goals

247 | 248 | 249 |

The overarching goal is to reduce the burden of migrating websites from 250 | a priori insecure origins by reducing the negative 251 | side effects of mixed content blocking [MIX].

252 | 253 | 254 |

If we assume that authors do the server-side legwork (obtaining a certificate, 255 | configuring the server, setting up redirects), and that authors also ensure 256 | that content is accessible at the same host and path 257 | on a secure scheme, then the following statements ought to hold after 258 | implementing this feature:

259 | 260 | 261 |
    262 | 263 |
  1. 264 | Authors should be able to ensure that all content requested by a given 265 | page loads successfully, and securely. Mixed content blocking should not 266 | break pages as a result of migrating to a secure origin. 267 | 268 | 269 |

    Note: This requirement is not met by Mixed Content’s strict 270 | mode, which makes something like the opposite assertion.

    271 | 272 | 273 | 274 | 275 |
  2. 276 | As a result of #1, the user agent should not degrade any security 277 | indicators related to requesting mixed content, as no insecure content 278 | should be requested. 279 | 280 | 281 | 282 |
  3. 283 | Authors should be able to ensure that all internal links correctly send 284 | users to the site’s secure address, and not to its pre-migration insecure 285 | address. 286 | 287 | 288 | 289 |
  4. 290 | Authors should be able to achieve all these goals without editing a site’s 291 | content. This is particularly important for archived content and legacy 292 | systems for which maintenance is difficult enough, never mind upgrades. 293 | 294 | 295 | 296 |
  5. 297 | Authors should be able to pursue a gradual transition from insecure to 298 | secure, serving secure resources to clients that support upgrades, while 299 | retaining insecure resources for clients that don’t. 300 | 301 | 302 | 303 |
304 | 305 | 306 |

Note: The mechanism defined here does not intend to supplant Strict 307 | Transport Security [RFC6797]. See §7.2 Relation to HSTS for details.

308 | 309 | 310 |

1.2. Examples

311 | 312 | 313 |
314 | Megacorp, Inc. wishes to migrate http://example.com/ to 315 | https://example.com. They set up the server-side requirements 316 | to make their own resources available over HTTPS, and work with partners in 317 | order to make third-party widgets available as well. 318 | 319 | 320 |

They quickly realize, however, that the majority of their long-tail content 321 | is locked up in a database tied to an old content management system that 322 | they’ve been avoiding for years ("If it ain’t broke..."). They’ll need to 323 | spend quite a bit of time either migrating the content to their new system, 324 | or modifying it in-place in the old system. Either way, it ends up being a 325 | substantial amount of work, and though they put top programmers on the task, 326 | it clearly won’t be done any time soon.

327 | 328 | 329 | 330 |

As a stopgap measure, Megacorp injects the following header into every 331 | response that goes out through their servers:

332 | 333 | 334 | 335 |
Content-Security-Policy: upgrade-insecure-requests
 336 | 
337 | 338 | 339 | 340 |

This automatically upgrades all insecure resource requests for their pages 341 | to secure variants, allowing a user agent to treat the following HTML code:

342 | 343 | 344 | 345 |
<img src="http://example.com/image.png">
 346 | 
347 | 348 | 349 | 350 |

as though it had been delivered as:

351 | 352 | 353 | 354 |
<img src="https://example.com/image.png">
 355 | 
356 | 357 | 358 | 359 |

The URL will be rewritten before the request is made, meaning that no 360 | insecure requests will hit the network. Users will be safer, and Megacorp’s 361 | administrators will be happier.

362 | 363 | 364 |
365 |
366 | 367 | 368 | 369 |
370 | 371 |

2. Key Concepts and Terminology

372 | 373 | 374 |
375 |
376 |

upgrade

377 | 378 | 379 |
380 |

A Request is said to be upgraded if it is rewritten 381 | to contain a URL with a scheme of https or 382 | wss.

383 | 384 |
385 | 386 |

The Augmented Backus-Naur Form (ABNF) notation used in §3.1 Upgrade Policy Delivery is 387 | specified in RFC5234. [ABNF]

388 |
389 | 390 | 391 | 392 |
393 | 394 |

3. Upgrading Insecure Resource Requests

395 | 396 | 397 |

In order to allow authors to mitigate the negative side-effects of migration 398 | away from a priori insecure origins, authors may 399 | instruct the user agent to transparently upgrade resource requests to 400 | potentially secure variants of the original request’s URL.

401 | 402 | 403 |

To support this instruction, environment settings objects and 404 | browsing contexts have an upgrade insecure resource requests 405 | flag which is set to No Upgrade unless otherwise specified. 406 | This flag is checked in §4.1 407 | Upgrade request to a potentially secure URL, if appropriate 408 | in order to determine whether or 409 | not resource requests should be upgraded during Fetching.

410 | 411 | 412 |

3.1. Upgrade Policy Delivery

413 | 414 | 415 |

A server MAY instruct a user agent to upgrade insecure resource requests for 416 | a particular protected resource by sending a 417 | Content-Security-Policy header [CSP] that contains a 418 | upgrade-insecure-requests directive, defined via the following ABNF 419 | grammar:

420 | 421 | 422 |
directive-name  = "upgrade-insecure-requests"
 423 | directive-value = ""
 424 | 
425 | 426 | 427 |

When enforcing the upgrade-insecure-requests directive, 428 | set the protected resource’s incumbent settings object’s 429 | upgrade insecure resource requests flag to Enforced 430 | Upgrade.

431 | 432 | 433 |

When monitoring the upgrade-insecure-requests directive, 434 | set the protected resource’s incumbent settings object’s 435 | upgrade insecure resource requests flag to Monitored 436 | Upgrade.

437 | 438 | 439 |

In a thread on public-webappsec@, 440 | Peter Eckersley suggested modifying this to allow whitelisting specific hosts, 441 | rather than upgrading everything: "That way, if you have N third parties 442 | on a site, and (say) two of them provide images only, and don’t support 443 | HTTPS at all, you can use the upgrade mechanism for scripts on the other 444 | N - 2 origins."

445 | 446 | 447 |
448 | For example, sending the following header with a document will ensure that 449 | subresource requests are upgraded, and that reports are sent out for each 450 | upgrade: 451 | 452 | 453 |
Content-Security-Policy: upgrade-insecure-requests;
 454 |                          report-uri /upgrade-endpoint
 455 | 
456 | 457 | 458 | 459 |

Sending the following header will not upgrade requests, but will send 460 | reports:

461 | 462 | 463 | 464 |
Content-Security-Policy-Report-Only: upgrade-insecure-requests;
 465 |                                      report-uri /upgrade-endpoint
 466 | 
467 | 468 | 469 |
470 | 471 | 472 |

3.2. Feature Detecting Clients Capable of Upgrading

473 | 474 | 475 |

If a site requires the upgrade mechanism described in this document in order 476 | to provide users with a reasonable experience over secure transit, then 477 | authors need to determine whether or not it is safe to redirect a client to 478 | the secure version of a site. Rather than relying on user-agent sniffing to 479 | make this decision, user agents MUST advertise their capabilities when 480 | making insecure navigational requests by sending a Prefer HTTP 481 | request header expressing the desire for a secure representation [RFC7240] 482 | as described in §3.2.1 483 | The return=secure-representation Preference 484 | .

485 | 486 | 487 |

3.2.1. 488 | The return=secure-representation Preference 489 |

490 | 491 | 492 |

The "return=secure-representation" preference 493 | indicates that the client prefers that the server redirect from an insecure 494 | resource representation to a secure one, and that it can successfully handle 495 | the upgrade-insecure-requests directive in order to make 496 | that redirection as seamless as possible.

497 | 498 | 499 |

This new preference changes the return ABNF defined in 500 | RFC7240 Section 4.2 to the following:

501 | 502 | 503 |
return = "return" BWS "=" BWS ( "secure-representation" / "representation" / "minimal" )
 504 | 
505 | 506 | 507 |

When a server encounters this preference in an HTTP request’s headers, it 508 | SHOULD redirect the user to a secure version of the resource being requested.

509 | 510 | 511 |

User agent implementation details are described in step #2 of the the 512 | §4.1 513 | Upgrade request to a potentially secure URL, if appropriate 514 | algorithm. Note in particular that to mitigate the risk 515 | that this header will become a vestigial part of the platform, user agents 516 | SHOULD omit the preference when making requests to potentially secure 517 | origins.

518 | 519 | 520 |
521 | A client that supports this document’s upgrade mechanism requests 522 | http://example.com/ as follows: 523 | 524 | 525 |
GET / HTTP/1.1
 526 | Host: example.com
 527 | Connection: keep-alive
 528 | ...
 529 | Prefer: return=secure-representation
 530 | 
531 | 532 | 533 | 534 |

The server parses the preference, notices that the user’s client can deal 535 | well with upgrade requests, and therefore responds to the request by 536 | redirecting the user to a secure version of the resource she’s requesting:

537 | 538 | 539 | 540 |
HTTP/1.1 302 Moved Temporarily
 541 | Location: https://example.com/
 542 | 
543 | 544 | 545 |
546 | 547 | 548 |

3.3. Policy Inheritance

549 | 550 | 551 |

If a Document's incumbent settings object’s upgrade insecure 552 | resource requests flag is set to true, the user agent MUST 553 | ensure that all nested browsing contexts inherit the setting in the 554 | following ways:

555 | 556 | 557 |
    558 | 559 |
  1. 560 | When a nested browsing context context is created, set 561 | its upgrade insecure resource requests flag to true if 562 | context’s embedding document’s upgrade insecure 563 | resource requests flag is set to true. 564 | 565 | 566 | 567 |
  2. 568 | When creating a new Document object, set its 569 | incumbent settings object’s upgrade insecure resource requests 570 | flag to true if its browsing context’s upgrade 571 | insecure resource requests flag is true. 572 | 573 | 574 | 575 |
576 |
577 | 578 | 579 | 580 |
581 | 582 |

4. Processing Algorithms

583 | 584 | 585 |

4.1. 586 | Upgrade request to a potentially secure URL, if appropriate 587 |

588 | 589 | 590 |

Given a Request request, this algorithm will rewrite its 591 | url if the client from which the request originates 592 | has opted-in to upgrades. It will also inject a 593 | return=secure-representation preference for insecure 594 | navigational requests in order to improve a server’s ability to feature-detect 595 | a client’s upgrade capabilities.

596 | 597 | 598 |

We will not upgrade cross-origin navigational requests, with the exception of 599 | form submissions. Form submissions will be upgraded to mitigate the risk of 600 | data leakage via plaintext submissions.

601 | 602 | 603 |

This should be called from Fetch, probably after the existing step #3.

604 | 605 | 606 |
    607 | 608 |
  1. 609 | If request’s url is potentially secure: 610 | return without modifying request. 611 | 612 | 613 | 614 |
  2. 615 | If request’s context-frame-type is 616 | top-level, nested, or auxiliary, 617 | then append a header named Prefer with a value 618 | of return=secure-representation to 619 | request’s header-list. 620 | 621 | 622 | 623 |
  3. 624 | If request’s context-frame-type is 625 | top-level or auxiliary, then: 626 | 627 | 628 |
      629 | 630 |
    1. 631 | If request’s context is form, 632 | skip the remaining substeps, and continue upgrading 633 | request. 634 | 635 | 636 | 637 |
    2. 638 | If request’s url's host is the same 639 | as request’s client's origin’s host, 640 | skip the remaining substeps, and continue upgrading 641 | request. 642 | 643 | 644 |

      Note: We allow only same-origin upgrades in order to ensure that 645 | navigations between pages of a single site that has opted-into 646 | the upgrade behavior remain on HTTPS, regardless of the hard-coded 647 | values in <a> tags. Performing upgrades for navigations to 648 | third-party resources brings a significantly higher potential for 649 | breakage, so we’re avoiding it for the moment.

      650 | 651 | 652 | 653 |

      This isn’t correct for nested documents. We need to pass the 654 | policy-setting document’s host down to ensure that we’re only 655 | attempting "first-party" upgrades.

      656 | 657 | 658 | 659 | 660 |
    3. 661 | Return without further modifying request. 662 | 663 | 664 | 665 |
    666 | 667 | 668 | 669 | 670 |
  4. 671 | Let upgrade state be the result of executing 672 | §4.2 673 | Should insecure Requests be upgraded for client? 674 | upon request’s client. 675 | 676 | 677 | 678 |
  5. 679 | If upgrade state is No Upgrade, return without 680 | modifying request. 681 | 682 | 683 | 684 |
  6. 685 | Execute §4.3 686 | Report an upgrade for request 687 | on request. 688 | 689 | 690 | 691 |
  7. 692 | If upgrade state is Monitored Upgrade, return 693 | without modifying request. 694 | 695 | 696 | 697 |
  8. 698 | If request’s url's scheme is 699 | http, set request’s url's 700 | scheme to https, and return. 701 | 702 | 703 | 704 |
  9. 705 | If request’s urls port is 706 | 80, set request’s urls port 707 | to 443. 708 | 709 | 710 |

    Note: This will only change the URL’s port if the port is 711 | explicitly set to 80. If the port is not set, or if 712 | it is set to some non-standard value, the user agent will not 713 | modify that value. This implementation makes the same tradeoffs as 714 | HSTS (see [RFC6797], and specifically step #5 of 715 | Section 716 | 8.3, and item #6 in 717 | Appendix 718 | A).

    719 | 720 | 721 | 722 | 723 |
724 | 725 | 726 |

Note: Due to Fetch’s recursive nature, this algorithm will upgrade 727 | insecurely-redirected requests as well as insecure initial requests.

728 | 729 | 730 |

4.2. 731 | Should insecure Requests be upgraded for client? 732 |

733 | 734 | 735 |

Given an Request's client client (an environment 736 | settings object), this algorithm returns Enforced Upgrade if 737 | a priori insecure requests associated with that client 738 | should be upgraded, Monitored Upgrade if requests should be 739 | reported (via §4.3 740 | Report an upgrade for request 741 | ) but not actually upgraded, and No 742 | Upgrade otherwise. In short, this will check the client and return the 743 | appropriate upgrade insecure resource requests flag set on it or its 744 | browsing context.

745 | 746 | 747 |
    748 | 749 |
  1. 750 | If client has a responsible document, return the value 751 | of its upgrade insecure resource requests flag. 752 | 753 | 754 |

    Note: This catches Documents or Workers whose flag is set directly 755 | by the upgrade-insecure-requests directive, or which 756 | have inherited the flag from an embedding document.

    757 | 758 | 759 | 760 | 761 |
  2. 762 | If client has a responsible browsing context, return the 763 | value of its upgrade insecure resource requests flag. 764 | 765 | 766 |

    Note: This catches requests triggered from detached clients. 767 | Not sure this is necessary, really, given the inheritance structure 768 | defined in §3.3 Policy Inheritance.

    769 | 770 | 771 | 772 | 773 |
  3. 774 | Return No Upgrade. 775 | 776 | 777 | 778 |
779 | 780 | 781 |

4.3. 782 | Report an upgrade for request 783 |

784 | 785 | 786 |

When a Request is upgraded, a CSP violation is triggered with the intent 787 | of informing authors that resources on their sites will fail to load in 788 | user agents that do not support this upgrade mechanism.

789 | 790 | 791 |

Note: This violation report will be triggered for the Document or 792 | Worker that triggers the request. This might or might not be the same 793 | protected resource that set the 794 | upgrade-insecure-requests directive, due to §3.3 Policy Inheritance. 795 | See §6.2 CSP Violation Reports for detail.

796 | 797 | 798 |
    799 | 800 |
  1. 801 | Report a violation for request’s client's 802 | responsible document, using 803 | upgrade-insecure-requests as the 804 | violated-directive and effective-directive, 805 | and request’s url as the blocked-uri. 806 | 807 | 808 | 809 |
810 |
811 | 812 | 813 | 814 |
815 | 816 |

5. Modifications to WebSockets

817 | 818 | 819 |

WebSockets do not use the Fetching algorithm, so we need to handle 820 | those requests separately.

821 | 822 | 823 |

The establish a WebSocket connection algorithm [RFC6455] is modified 824 | as follows:

825 | 826 | 827 | 905 |
906 | 907 | 908 |
909 | 910 |

6. Security Considerations

911 | 912 | 913 |

6.1. Interaction with HSTS

914 | 915 | 916 |

The upgrade-insecure-requests directive does not replace 917 | the Strict-Transport-Security HTTP response header [RFC6797]. 918 | Authors who serve their site over secure transport SHOULD send that header 919 | with an appropriate max-age in order to ensure that users are 920 | not subject to SSL stripping attacks by maliciously active network attackers.

921 | 922 | 923 |

6.2. CSP Violation Reports

924 | 925 | 926 |

When sending a violation report for an upgraded resource, user agents MUST 927 | target the Document or Worker that triggered the request, rather 928 | than the Document or Worker on which the 929 | upgrade-insecure-requests directive was set. Due to 930 | §3.3 Policy Inheritance, the latter might be a cross-origin ancestor of the former, and 931 | sending violation reports to that set of reporting endpoints could leak data 932 | in unexpected ways.

933 | 934 | 935 |

Likewise, the SecurityPolicyViolationEvent MUST NOT target any 936 | Document other than the one which triggered the request, for the same 937 | reasons.

938 |
939 | 940 | 941 |
942 | 943 |

7. Authoring Considerations

944 | 945 | 946 |

7.1. Legacy Clients

947 | 948 | 949 |

Legacy clients which do support mixed content blocking [MIX], but do not 950 | support the upgrade-insecure-requests directive will 951 | continue to have a suboptimal experience on pages containing 952 | a priori insecure URLs. Authors SHOULD ensure that 953 | they collect violation reports in order 954 | to determine which resources are most problematic for their users, and SHOULD 955 | use that information to prioritize fixes for URLs in legacy content that 956 | users will most likely request.

957 | 958 | 959 |

7.2. Relation to HSTS

960 | 961 | 962 |

The mechanism specified here deals only with the security policy for a 963 | specific protected resource. It does not deprecate, replace, or in any 964 | way reduce the value of the Strict-Transport-Security HTTP 965 | response header [RFC6797]. Authors can and should continue to use that 966 | header to ensure that their users are not subject to SSL stripping downgrade 967 | attacks, as the upgrade-insecure-requests directive will 968 | not ensure that users visiting your site via links on third-party sites will 969 | be upgraded to HTTPS for the top-level navigation.

970 | 971 | 972 |

Likewise, the Strict-Transport-Security header does not imply 973 | the behavior that upgrade-insecure-requests activates. 974 | It only ensures that resources requested from an origin will never hit the 975 | network insecurely.

976 | 977 | 978 |

Therefore, we recommend that authors who wish to ensure that their users have 979 | a secure experience do the following:

980 | 981 | 982 |
    983 | 984 |
  1. 985 | Redirect incoming traffic from HTTP to HTTPS by serving a 986 | Location header along with a 302 status code. 987 | 988 | 989 | 990 |
  2. 991 | Respond to HTTPS requests with a Strict-Transport-Security 992 | header with a reasonable max-age. 993 | 994 | 995 | 996 |
  3. 997 | Work with user agent vendors to add their sites to those user agent’s 998 | HSTS Preload Lists (for example, by visiting 999 | hstspreload.appspot.com). 1000 | 1001 | 1002 | 1003 |
  4. 1004 | Opt-into either this document’s 1005 | upgrade-insecure-requests mechanism, or into Mixed 1006 | Content’s strict mode in order to ensure that insecure content is 1007 | never loaded. 1008 | 1009 | 1010 | 1011 |
1012 |
1013 | 1014 | 1015 |
1016 | 1017 |

8. IANA Considerations

1018 | 1019 | 1020 |

The "HTTP Preferences" registry should be updated with the following 1021 | alteration to the existing registration for the return 1022 | preference [RFC7240]:

1023 | 1024 | 1025 |
1026 |
1027 |

Preference

1028 | 1029 | 1030 |
1031 |

return

1032 | 1033 | 1034 | 1035 |
1036 |

Value

1037 | 1038 | 1039 |
1040 |

One of "minimal", "representation", or 1041 | "secure-representation".

1042 | 1043 | 1044 | 1045 |
1046 |

Description

1047 | 1048 | 1049 |
1050 |

When the value is "minimal", it indicates that the client 1051 | prefers that the server return a minimal response to a request. When the 1052 | value is "representation", it indicates that the client 1053 | prefers that the server include a representation of the current state of 1054 | the resource in response to a request. When the value is 1055 | "secure-representation" it indicates that the client prefers 1056 | to be redirected to a secure version of the resource (and that the client 1057 | supports the upgrade-insecure-requests mechanism).

1058 | 1059 | 1060 | 1061 |
1062 |

Reference

1063 | 1064 | 1065 |
1066 |

Section 4.2 of RFC7240 defines the 1067 | "minimal" and "representation" values. This 1068 | specification (see §3.2.1 1069 | The return=secure-representation Preference 1070 | ) defines the 1071 | secure-representation value.

1072 | 1073 |
1074 |
1075 | 1076 | 1077 |
1078 | 1079 |

9. Acknowledgements

1080 | 1081 | 1082 |

Anne van Kesteren helped ensure that the initial draft of this document was 1083 | sane. Peter Eckersley and Daniel Kahn Gillmor clarified the problem space, and 1084 | helped point out the impact.

1085 |
1086 | 1087 |
1088 | 1089 |

Conformance

1090 | 1091 | 1092 |

Document conventions

1093 | 1094 | 1095 |

Conformance requirements are expressed with a combination of 1096 | descriptive assertions and RFC 2119 terminology. The key words "MUST", 1097 | "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", 1098 | "RECOMMENDED", "MAY", and "OPTIONAL" in the normative parts of this 1099 | document are to be interpreted as described in RFC 2119. 1100 | However, for readability, these words do not appear in all uppercase 1101 | letters in this specification. 1102 | 1103 |

1104 |

All of the text of this specification is normative except sections 1105 | explicitly marked as non-normative, examples, and notes. [RFC2119]

1106 | 1107 | 1108 |

Examples in this specification are introduced with the words "for example" 1109 | or are set apart from the normative text with class="example", 1110 | like this: 1111 | 1112 |

1113 |
1114 | 1115 |

This is an example of an informative example.

1116 | 1117 | 1118 |
1119 | 1120 | 1121 |

Informative notes begin with the word "Note" and are set apart from the 1122 | normative text with class="note", like this: 1123 | 1124 |

1125 |

Note, this is an informative note.

1126 | 1127 | 1128 |

Conformant Algorithms

1129 | 1130 | 1131 |

Requirements phrased in the imperative as part of algorithms (such as 1132 | "strip any leading space characters" or "return false and abort these 1133 | steps") are to be interpreted with the meaning of the key word ("must", 1134 | "should", "may", etc) used in introducing the algorithm.

1135 | 1136 | 1137 |

Conformance requirements phrased as algorithms or specific steps can be 1138 | implemented in any manner, so long as the end result is equivalent. In 1139 | particular, the algorithms defined in this specification are intended to 1140 | be easy to understand and are not intended to be performant. Implementers 1141 | are encouraged to optimize.

1142 | 1143 | 1144 |

Conformance Classes

1145 | 1146 | 1147 |

A conformant user agent must implement all the requirements 1148 | listed in this specification that are applicable to user agents.

1149 | 1150 | 1151 |

A conformant server must implement all the requirements listed 1152 | in this specification that are applicable to servers.

1153 | 1154 | 1155 | 1156 | 1157 |

Index

1158 |

Terms defined by this specification

1159 | 1168 |

Terms defined by reference

1169 | 1236 |

References

1237 |

Normative References

1238 |
1239 |
[ABNF] 1240 |
Dave Crocker; Paul Overell. Augmented BNF for Syntax Specifications: ABNF. RFC. URL: http://www.ietf.org/rfc/rfc5234.txt 1241 |
[CSP] 1242 |
Mike West; Dan Veditz. Content Security Policy. WD. URL: https://w3c.github.io/webappsec/specs/content-security-policy/ 1243 |
[FETCH] 1244 |
Anne van Kesteren. Fetch. Living Standard. URL: https://fetch.spec.whatwg.org/ 1245 |
[MIX] 1246 |
Mike West. Mixed Content. ED. URL: https://w3c.github.io/webappsec/specs/mixedcontent/ 1247 |
[RFC6455] 1248 |
Ian Fette; Alexey Melnikov. The WebSocket Protocol. RFC. URL: http://www.ietf.org/rfc/rfc6455.txt 1249 |
[URL] 1250 |
Anne van Kesteren. URL. Living Standard. URL: https://url.spec.whatwg.org/ 1251 |
[dom] 1252 |
Anne van Kesteren; et al. W3C DOM4. 10 July 2014. LCWD. URL: http://www.w3.org/TR/dom/ 1253 |
[html5] 1254 |
Robin Berjon; et al. HTML5. 28 October 2014. REC. URL: http://www.w3.org/TR/html5/ 1255 |
[rfc2119] 1256 |
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: http://www.ietf.org/rfc/rfc2119.txt 1257 |
[rfc7240] 1258 |
J. Snell. Prefer Header for HTTP. June 2014. Proposed Standard. URL: http://www.ietf.org/rfc/rfc7240.txt 1259 |
[workers] 1260 |
Ian Hickson. Web Workers. 1 May 2012. CR. URL: http://www.w3.org/TR/workers/
1261 |

Informative References

1262 |
1263 |
[BBC-ARCHIVE] 1264 |
Neil McIntosh. Labelling BBC Online's archived websites. URL: http://www.bbc.co.uk/blogs/internet/entries/f7126d19-2afa-3231-9c4e-0f7198c468ab 1265 |
[NYT-HTTPS] 1266 |
Eitan Konigsburg; Rajiv Pant; Elena Kvochko. Embracing HTTPS. URL: http://open.blogs.nytimes.com/2014/11/13/embracing-https/ 1267 |
[RFC6797] 1268 |
Jeff Hodges; Collin Jackson; Adam Barth. HTTP Strict Transport Security (HSTS). RFC. URL: http://www.ietf.org/rfc/rfc6797.txt 1269 |
[WEB-HTTPS] 1270 |
Mark Nottingham. Securing the Web. TAG Finding. URL: http://www.w3.org/2001/tag/doc/web-https
1271 |

Issues Index

1272 |
1273 |
In a thread on public-webappsec@, 1274 | Peter Eckersley suggested modifying this to allow whitelisting specific hosts, 1275 | rather than upgrading everything: "That way, if you have N third parties 1276 | on a site, and (say) two of them provide images only, and don’t support 1277 | HTTPS at all, you can use the upgrade mechanism for scripts on the other 1278 | N - 2 origins."
1279 |
This should be called from Fetch, probably after the existing step #3.
1280 |
This isn’t correct for nested documents. We need to pass the 1281 | policy-setting document’s host down to ensure that we’re only 1282 | attempting "first-party" upgrades.
1283 | 1284 | -------------------------------------------------------------------------------- /published/ECHIDNA: -------------------------------------------------------------------------------- 1 | # ECHIDNA config for UPGRADE's WD. 2 | WD.html 3 | default.css 4 | -------------------------------------------------------------------------------- /published/default.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Style sheet for WebAppSec specifications (stolen wholesale from the CSSWG), 3 | * to be used in addition to http://www.w3.org/StyleSheets/TR/W3C-{WD,PR,REC} 4 | */ 5 | 6 | @media print { 7 | html { margin: 0 !important } 8 | body { font-family: serif } 9 | th, td { font-family: inherit } 10 | a { color: inherit !important } 11 | .example:before { font-family: serif !important } 12 | a:link, a:visited { text-decoration: none !important } 13 | a:link:after, a:visited:after { /* create a cross-ref "see..." */ } 14 | } 15 | @page { 16 | margin: 1.5cm 1.1cm; 17 | } 18 | 19 | body { 20 | counter-reset: exampleno figure issue; 21 | max-width: 50em; 22 | margin: 0 auto !important; 23 | } 24 | 25 | /* Pagination */ 26 | h1, h2, h3, h4, h5, h6 { page-break-after: avoid } 27 | figure, div.figure, div.sidefigure, pre, table.propdef, table.propdef-extra, 28 | .example { page-break-inside: avoid } 29 | dt { page-break-after: avoid } 30 | 31 | span.id {float: right; font-weight: bold} 32 | 33 | /* General Structural Markup */ 34 | h2, h3, h5, h6 { margin-top: 3em; } 35 | 36 | /* #subtitle is a subtitle in an H2 under the H1 */ 37 | h1 + h2, #subtitle + h2 { margin-top: 0; } 38 | 39 | h4 { margin-top: 4em; } 40 | 41 | h2 + h3, h3 + h4, h4 + h5, h5 + h6 { margin-top: 1.2em } 42 | 43 | hr:not([title]) { 44 | font-size: 1.5em; 45 | text-align: center; 46 | margin: 1em auto; 47 | border: transparent solid; 48 | background: transparent; 49 | } 50 | hr:not([title])::before { 51 | content: "\1F411\2003\2003\1F411\2003\2003\1F411"; 52 | } 53 | 54 | p, div.note, div.issue, details.why { 55 | margin-top: 1em; 56 | margin-bottom: 1em; 57 | } 58 | 59 | dd > p:first-child, li > p:first-child, .note > p:first-child, .issue > p:first-child { 60 | margin-top: 0 61 | } 62 | 63 | pre { 64 | margin-top: 1em; 65 | margin-bottom: 1em; 66 | } 67 | 68 | pre, code { 69 | font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace; 70 | font-size: .9em; 71 | } 72 | 73 | img { 74 | border-style: none; 75 | color: white; 76 | } 77 | .toc { 78 | } 79 | 80 | body { 81 | line-height: 1.5; 82 | } 83 | 84 | a.logo:link, a.logo:visited { 85 | padding: 0; 86 | border-style: none; 87 | } 88 | 89 | dl dd { margin: 0 0 1em 2em } 90 | .head dd { margin-bottom: 0; } 91 | ul, ol { margin-left: 0; padding-left: 2em; } 92 | li { margin: 0.25em 2em 0.5em 0; padding-left: 0 } 93 | 94 | ul.indexlist { margin-left: 0; columns: 13em; } 95 | ul.indexlist li { margin-left: 0; list-style: none } 96 | ul.indexlist li li { margin-left: 1em } 97 | ul.indexlist a { font-weight: bold; } 98 | ul.indexlist ul, ul.indexlist dl { font-size: smaller; } 99 | ul.indexlist dl { margin-top: 0; } 100 | ul.indexlist dt { margin: .2em 0 .2em 20px;} 101 | ul.indexlist dd { margin: .2em 0 .2em 40px;} 102 | 103 | /* .self-link is a link to the element */ 104 | .heading, .issue, .note, .example, li, dt { position: relative; } 105 | a.self-link { 106 | position: absolute; 107 | top: 0; 108 | left: -2.5em; 109 | width: 2em; 110 | height: 2em; 111 | text-align: center; 112 | border: none; 113 | transition: opacity .2s; 114 | opacity: .5; 115 | } 116 | a.self-link:hover { 117 | opacity: 1; 118 | } 119 | .heading > a.self-link { 120 | font-size: 83%; 121 | } 122 | li > a.self-link { 123 | left: -3.5em; 124 | } 125 | dfn > a.self-link { 126 | top: auto; 127 | left: auto; 128 | opacity: 0; 129 | width: 1.5em; 130 | height: 1.5em; 131 | background: gray; 132 | color: white; 133 | font-style: normal; 134 | transition: opacity .2s, background-color .2s, color .2s; 135 | } 136 | dfn:hover > a.self-link { 137 | opacity: 1; 138 | } 139 | dfn > a.self-link:hover { 140 | color: black; 141 | } 142 | 143 | a.self-link::before { content: "¶"; } 144 | .heading > a.self-link::before { content: "§"; } 145 | dfn > a.self-link::before { content: "#"; } 146 | 147 | /* Examples */ 148 | 149 | .example { 150 | counter-increment: exampleno; 151 | } 152 | .example:before { 153 | content: "Example"; 154 | content: "Example " counter(exampleno); 155 | min-width: 7.5em; 156 | text-transform: uppercase; 157 | display: block; 158 | } 159 | div.illegal-example:before, pre.illegal-example:before { 160 | content: "Invalid Example"; 161 | content: "Invalid Example" counter(exampleno); 162 | } 163 | .example, .illegal-example, div.html, div.illegal-html, div.xml, 164 | div.illegal-xml, pre.html, 165 | pre.illegal-html, pre.xml, pre.illegal-xml { 166 | padding: 0.5em; 167 | margin: 1em 0; 168 | position: relative; 169 | clear: both; 170 | } 171 | pre.example, pre.illegal-example, pre.html, 172 | pre.illegal-html, pre.xml, pre.illegal-xml { 173 | padding-top: 1.5em; 174 | } 175 | pre.illegal-example { color: red } 176 | div.illegal-example { color: red } 177 | div.illegal-example p { color: black } 178 | 179 | div.html { color: #600 } 180 | pre.html { color: #600 } 181 | pre.illegal-html { color: red } 182 | div.illegal-html { color: red } 183 | div.illegal-html p { color: black } 184 | pre.deprecated-html { color: red } 185 | div.deprecated-html { color: red } 186 | div.deprecated-html p { color: black } 187 | 188 | div.xml { color: #600 } 189 | pre.xml { color: #600 } 190 | pre.illegal-xml { color: red } 191 | div.illegal-xml { color: red } 192 | div.illegal-xml p { color: black } 193 | 194 | .css, .property { color: #005a9c } /* inline CSS code (SPAN/CODE) */ 195 | code.css { font-family: inherit; font-size: 100% } 196 | code.html { color: #600 } /* inline HTML */ 197 | code.xml { color: #600 } /* inline XML */ 198 | .property { font: inherit; white-space: nowrap; } /* name of a CSS property (SPAN) */ 199 | .descriptor { } /* name of a CSS descriptor (SPAN) */ 200 | .type { font-style: italic } /* A value for a property */ 201 | 202 | /* Autolinks produced using Bikeshed. */ 203 | [data-link-type="property"]::before, 204 | [data-link-type="propdesc"]::before, 205 | [data-link-type="descriptor"]::before, 206 | [data-link-type="value"]::before, 207 | [data-link-type="function"]::before, 208 | [data-link-type="at-rule"]::before, 209 | [data-link-type="selector"]::before, 210 | [data-link-type="maybe"]::before {content: "\2018";} 211 | [data-link-type="property"]::after, 212 | [data-link-type="propdesc"]::after, 213 | [data-link-type="descriptor"]::after, 214 | [data-link-type="value"]::after, 215 | [data-link-type="function"]::after, 216 | [data-link-type="at-rule"]::after, 217 | [data-link-type="selector"]::after, 218 | [data-link-type="maybe"]::after {content: "\2019";} 219 | [data-link-type].production::before, 220 | [data-link-type].production::after, 221 | .prod [data-link-type]::before, 222 | .prod [data-link-type]::after { content: ""; } 223 | 224 | 225 | /* Element-type link styling */ 226 | [data-link-type=element] { font-family: monospace; } 227 | [data-link-type=element]::before { content: "<" } 228 | [data-link-type=element]::after { content: ">" } 229 | 230 | dfn { font-weight: bolder; } 231 | 232 | .issue, .note, .example, .why { 233 | padding: .5em; 234 | /* padding: .5rem; /* proposed unit in css3-values */ 235 | border-left-width: .5em; 236 | /* border-left-width: .5rem; /* proposed unit in css3-values */ 237 | border-left-style: solid; 238 | } 239 | span.note, span.issue { 240 | padding: .1em .5em .15em; 241 | border-right-width: .5em; 242 | border-right-style: solid; 243 | } 244 | 245 | /* Open issue / editorial remark; not intended for a final publication */ 246 | .issue { 247 | border-color: #E05252; 248 | background: #FBE9E9; 249 | counter-increment: issue; 250 | overflow: auto; 251 | } 252 | 253 | .issue:before { 254 | content: "Issue " counter(issue); 255 | padding-right: 1em; 256 | text-transform: uppercase; 257 | color: #E05252; 258 | } 259 | 260 | /* Class note is a non-normative note. May be inline or a P or DIV */ 261 | .note, .why { 262 | border-color: #52E052; 263 | background: #E9FBE9; 264 | overflow: auto; 265 | } 266 | 267 | .normref { color: red } 268 | .informref { color: green } 269 | 270 | /* Example box */ 271 | .example { 272 | border-color: #E0CB52; 273 | background: #FCFAEE; 274 | overflow: auto; 275 | } 276 | 277 | .example:before { 278 | color: #B9AB2D; 279 | font-family: sans-serif; 280 | } 281 | 282 | details.why { 283 | border-color: #52E052; 284 | background: #E9FBE9; 285 | display: block; 286 | } 287 | 288 | details.why > summary { 289 | font-style: italic; 290 | display: block; 291 | } 292 | 293 | details.why[open] > summary { 294 | border-bottom: 1px silver solid; 295 | } 296 | 297 | /* ToC not indented, but font style shows hierarchy */ 298 | ul.toc {margin: 1em 0; padding: 0; line-height: 1.3; font-weight: bold; /*text-transform: uppercase;*/ } 299 | ul.toc ul {margin: 0; padding: 0; font-weight: normal; text-transform: none; } 300 | ul.toc ul ul {margin: 0 0 0 2em; font-style: italic; } 301 | ul.toc ul ul ul {margin: 0} 302 | ul.toc > li {margin: 1.5em 0; padding: 0; } 303 | ul.toc ul.toc li { margin: 0.3em 0 0 0; } 304 | ul.toc a { text-decoration: none; border-bottom-style: none; } 305 | ul.toc a:hover, ul.toc a:focus { border-bottom-style: solid; } 306 | /* 307 | ul.toc li li li, ul.toc li li li ul {margin-left: 0; display: inline} 308 | ul.toc li li li ul, ul.toc li li li ul li {margin-left: 0; display: inline} 309 | */ 310 | 311 | /* Section numbers in a column of their own */ 312 | ul.toc span.secno {float: left; width: 4em; margin-left: -5em} 313 | ul.toc ul ul span.secno { margin-left: -7em; } 314 | /*ul.toc span.secno {text-align: right}*/ 315 | ul.toc li {clear: both} 316 | ul.toc {margin-left: 5em} 317 | /* If we had 'tab', floats would not be needed here: 318 | ul.toc span.secno {tab: 5em right; margin-right: 1em} 319 | ul.toc li {text-indent: 5em hanging} 320 | The second line in case items wrap 321 | */ 322 | 323 | ul.index { 324 | list-style: none; 325 | } 326 | 327 | s, del {text-decoration: line-through; color: red} 328 | u, ins {text-decoration: underline; color: #080} 329 | 330 | div.figure, p.figure, div.sidefigure, figure { 331 | text-align: center; 332 | margin: 2.5em 0; 333 | } 334 | div.figure pre, div.sidefigure pre, figure pre { 335 | text-align: left; 336 | display: table; 337 | margin: 1em auto; 338 | } 339 | .figure table, figure table { 340 | margin: auto; 341 | } 342 | div.sidefigure, figure.sidefigure { 343 | float: right; 344 | width: 50%; 345 | margin: 0 0 0.5em 0.5em 346 | } 347 | div.figure img, div.sidefigure img, figure img, 348 | div.figure object, div.sidefigure object, figure object { 349 | display: block; 350 | margin: auto; 351 | max-width: 100% 352 | } 353 | p.caption, figcaption, caption { 354 | text-align: center; 355 | font-style: italic; 356 | font-size: 90%; 357 | } 358 | p.caption:before, figcaption:before { 359 | content: "Figure " counter(figure) ". "; 360 | font-weight: bold; 361 | } 362 | p.caption, figcaption { 363 | counter-increment: figure; 364 | } 365 | 366 | /* DL list is indented, but figure inside it is not */ 367 | dd { margin-left: 2em } 368 | dd div.figure, dd figure { margin-left: -2em } 369 | 370 | sup { 371 | vertical-align: super; 372 | font-size: 80% 373 | } 374 | 375 | /* "Equations" (not real MathML, but simple HTML) are put in a 376 | blockquote and may have an equation number. We make sure the 377 | blockquote has enough margin on the right and then put the equation 378 | number there. */ 379 | 380 | blockquote { 381 | margin: 0.5em 4em 0.5em 2em; 382 | text-indent: 0; 383 | } 384 | .eqno { 385 | text-align: right; 386 | float: right; 387 | width: 3em; 388 | margin: 0 -4em 0 0; 389 | font-weight: bold; 390 | /* background: silver; color: black; padding: 0.1em */ 391 | } 392 | 393 | table.equiv-table { border-spacing: 0; margin: 0.5em 0 } 394 | table.equiv-table th, table.equiv-table td { padding: 0.3em } 395 | table.equiv-table th { text-align: left } 396 | /* table.equiv-table th:first-child { text-align: right } */ 397 | table.equiv-table td, table.equiv-table th { border-bottom: thin solid #666 } 398 | table.equiv-table { border-bottom: hidden } 399 | table.equiv-table { empty-cells: show } 400 | table.equiv-table caption { margin: 0.5em 0 0 0 } 401 | 402 | /* Style for table of properties */ 403 | table.proptable { 404 | font-size: small; 405 | border-collapse: collapse; 406 | border-spacing: 0; 407 | text-align: left; 408 | margin: 1em 0; 409 | } 410 | 411 | table.proptable td, table.proptable th { 412 | padding: 0.4em; 413 | text-align: center; 414 | } 415 | 416 | table.proptable tr:hover td { 417 | background: #DEF; 418 | } 419 | 420 | 421 | /* Style for table that defines a property or a descriptor */ 422 | table.propdef, table.propdef-extra, table.descdef, table.definition-table { 423 | border-spacing: 0; 424 | padding: 0 1em 0.5em; 425 | width: 100%; 426 | table-layout: fixed; 427 | background: #DEF; 428 | margin: 1.2em 0; 429 | border-left: 0.5em solid #8CCBF2; 430 | } 431 | 432 | table.propdef td, table.propdef-extra td, table.descdef td, table.definition-table td, 433 | table.propdef th, table.propdef-extra th, table.descdef th, table.definition-table th { 434 | padding: 0.5em; 435 | vertical-align: baseline; 436 | border-bottom: 1px solid #bbd7e9; 437 | } 438 | /* 439 | table.propdef dfn, table.propdef-extra dfn, table.descdef dfn { 440 | font-weight: bold; 441 | font-style: normal 442 | } 443 | */ 444 | 445 | table.propdef td:first-child, 446 | table.propdef-extra td:first-child, 447 | table.descdef td:first-child, 448 | table.definition-table td:first-child, 449 | table.propdef th:first-child, 450 | table.propdef-extra th:first-child, 451 | table.descdef th:first-child, 452 | table.definition-table th:first-child { 453 | font-style: italic; 454 | font-weight: normal; 455 | width: 8.3em; 456 | padding-left: 1em; 457 | } 458 | table.propdef td[colspan]:first-child, 459 | table.propdef-extra td[colspan]:first-child, 460 | table.descdef td[colspan]:first-child, 461 | table.definition-table td[colspan]:first-child, 462 | table.propdef th[colspan]:first-child, 463 | table.propdef-extra th[colspan]:first-child, 464 | table.descdef th[colspan]:first-child, 465 | table.definition-table th[colspan]:first-child { 466 | font-style: inherit 467 | } 468 | table.propdef tr:first-child, 469 | table.propdef-extra tr:first-child, 470 | table.descdef tr:first-child, 471 | table.definition-table tr:first-child { 472 | 473 | } 474 | 475 | table.propdef > tbody > tr:last-child th, 476 | table.propdef-extra > tbody > tr:last-child th, 477 | table.descdef > tbody > tr:last-child th, 478 | table.definition-table > tbody > tr:last-child th, 479 | table.propdef > tbody > tr:last-child td, 480 | table.propdef-extra > tbody > tr:last-child td, 481 | table.descdef > tbody > tr:last-child td, 482 | table.definition-table > tbody > tr:last-child td { 483 | border-bottom: 0; 484 | } 485 | 486 | table.propdef tr:first-child th, 487 | table.propdef-extra tr:first-child th, 488 | table.descdef tr:first-child th, 489 | table.definition-table tr:first-child th, 490 | table.propdef tr:first-child td, 491 | table.propdef-extra tr:first-child td, 492 | table.descdef tr:first-child td, 493 | table.definition-table tr:first-child td { 494 | padding-top: 1em; 495 | } 496 | 497 | /* For when values are extra-complex and need formatting for readability */ 498 | table td.pre { 499 | white-space: pre-wrap; 500 | } 501 | 502 | /* A footnote at the bottom of a propdef */ 503 | table.propdef td.footnote, 504 | table.propdef-extra td.footnote, 505 | table.descdef td.footnote, 506 | table.definition-table td.footnote { 507 | padding-top: 0.6em; 508 | width: auto 509 | } 510 | table.propdef td.footnote:before, 511 | table.propdef-extra td.footnote:before, 512 | table.descdef td.footnote:before, 513 | table.definition-table td.footnote:before { 514 | content: " "; 515 | display: block; 516 | height: 0.6em; 517 | width: 4em; 518 | border-top: thin solid; 519 | } 520 | 521 | /* The link in the first column in the property table (formerly a TD) */ 522 | table.proptable td .property, 523 | table.proptable th .property { 524 | display: block; 525 | text-align: left; 526 | font-weight: bold; 527 | } 528 | 529 | 530 | /* Styling for IDL fragments */ 531 | 532 | pre.idl { 533 | padding: .5em 1em; 534 | background: #DEF; 535 | margin: 1.2em 0; 536 | border-left: 0.5em solid #8CCBF2; 537 | } 538 | pre.idl :link, pre.idl :visited { 539 | color:inherit; 540 | background:transparent; 541 | } 542 | 543 | 544 | /* CSS modules typically don't use MUST, SHOULD etc. from RFC 2119, 545 | or, if they do, they don't put them in uppercase. But the following 546 | class is provided in case a spec wants to use RFC 2119 terms in 547 | uppercase in the source. */ 548 | 549 | em.rfc2119 { 550 | text-transform: lowercase; 551 | font-variant: small-caps; 552 | font-style: normal 553 | } 554 | 555 | /* In Profile specs, a table of required features: */ 556 | 557 | table.features th { 558 | background: #00589f; 559 | color: #fff; 560 | text-align: left; 561 | padding: 0.2em 0.2em 0.2em 0.5em; 562 | } 563 | table.features td { 564 | vertical-align: top; 565 | border-bottom: 1px solid #ccc; 566 | padding: 0.3em 0.3em 0.3em 0.7em; 567 | } 568 | 569 | 570 | /* Style for data tables (and properly marked-up proptables) */ 571 | 572 | .data, .proptable { 573 | margin: 1em auto; 574 | border-collapse: collapse; 575 | width: 100%; 576 | border: hidden; 577 | } 578 | .data { 579 | text-align: center; 580 | width: auto; 581 | } 582 | .data caption { 583 | width: 100%; 584 | } 585 | 586 | .data td, .data th, 587 | .proptable td, .proptable th { 588 | padding: 0.5em; 589 | border-width: 1px; 590 | border-color: silver; 591 | border-top-style: solid; 592 | } 593 | 594 | .data thead td:empty { 595 | padding: 0; 596 | border: 0; 597 | } 598 | 599 | .data thead th[scope="row"], 600 | .proptable thead th[scope="row"] { 601 | text-align: right; 602 | color: inherit; 603 | } 604 | 605 | .data thead, 606 | .proptable thead, 607 | .data tbody, 608 | .proptable tbody { 609 | color: inherit; 610 | border-bottom: 2px solid; 611 | } 612 | 613 | .data colgroup { 614 | border-left: 2px solid; 615 | } 616 | 617 | .data tbody th:first-child, 618 | .proptable tbody th:first-child , 619 | .data tbody td[scope="row"]:first-child, 620 | .proptable tbody td[scope="row"]:first-child { 621 | text-align: right; 622 | color: inherit; 623 | border-right: 2px solid; 624 | border-top: 1px solid silver; 625 | padding-right: 1em; 626 | } 627 | .data.define td:last-child { 628 | text-align: left; 629 | } 630 | 631 | .data tbody th[rowspan], 632 | .proptable tbody th[rowspan], 633 | .data tbody td[rowspan], 634 | .proptable tbody td[rowspan]{ 635 | border-left: 1px solid silver; 636 | } 637 | 638 | .data tbody th[rowspan]:first-child, 639 | .proptable tbody th[rowspan]:first-child, 640 | .data tbody td[rowspan]:first-child, 641 | .proptable tbody td[rowspan]:first-child{ 642 | border-left: 0; 643 | border-right: 1px solid silver; 644 | } 645 | 646 | .complex.data th, 647 | .complex.data td { 648 | border: 1px solid silver; 649 | } 650 | 651 | .data td.long { 652 | vertical-align: baseline; 653 | text-align: left; 654 | } 655 | 656 | .data img { 657 | vertical-align: middle; 658 | } 659 | 660 | table.propdef { 661 | table-layout: auto; 662 | } 663 | .propdef th { 664 | font-style: italic; 665 | font-weight: normal; 666 | text-align: left; 667 | width: 3em; 668 | } 669 | dt dfn code { 670 | font-size: inherit; 671 | } 672 | 673 | /* Style for switch/case
s */ 674 | dl.switch { 675 | padding-left: 2em; 676 | } 677 | dl.switch > dt { 678 | text-indent: -1.5em; 679 | } 680 | dl.switch > dt:before { 681 | content: '\21AA'; 682 | padding: 0 0.5em 0 0; 683 | display: inline-block; 684 | width: 1em; 685 | text-align: right; 686 | line-height: 0.5em; 687 | } 688 | 689 | 690 | /* Style for At Risk features (intended as editorial aid, not intended for publishing) */ 691 | .atrisk::before { 692 | position: absolute; 693 | margin-left: -5em; 694 | margin-top: -2px; 695 | padding: 4px; 696 | border: 1px solid; 697 | content: 'At risk'; 698 | font-size: small; 699 | background-color: white; 700 | color: gray; 701 | border-radius: 1em; 702 | text-align: center; 703 | } 704 | 705 | .toc .atrisk::before { content:none } 706 | 707 | 708 | /* This is mostly to make the list inside the CR exit criteria more compact. */ 709 | ol.inline, ol.inline li {display: inline; padding: 0; margin: 0} 710 | ol.inline {counter-reset: list-item} 711 | ol.inline li {counter-increment: list-item} 712 | ol.inline li:before {content: "(" counter(list-item) ") "; font-weight: bold} 713 | 714 | /* This styles the obsoletion notice on some of our older/abandoned specs. */ 715 | details.annoying-warning[open] { 716 | background: #fdd; 717 | color: red; 718 | font-weight: bold; 719 | text-align: center; 720 | padding: .5em; 721 | border: thick solid red; 722 | border-radius: 1em; 723 | position: fixed; 724 | left: 1em; 725 | right: 1em; 726 | bottom: 1em; 727 | z-index: 1000; 728 | } 729 | 730 | details.annoying-warning:not([open]) > summary { 731 | background: #fdd; 732 | color: red; 733 | font-weight: bold; 734 | text-align: center; 735 | padding: .5em; 736 | } 737 | -------------------------------------------------------------------------------- /w3c.json: -------------------------------------------------------------------------------- 1 | { 2 | "group": [ 3 | "49309" 4 | ], 5 | "contacts": [ 6 | "wseltzer" 7 | ], 8 | "shortName": "upgrade-insecure-requests", 9 | "repo-type": "rec-track" 10 | } --------------------------------------------------------------------------------