RESOLVED FIXED 271700
REGRESSION (Safari 17): Infinite reloading iframes on MDN and other websites, when using a combination of lazy loading, Cache-Control and Clear-Site-Data
https://bugs.webkit.org/show_bug.cgi?id=271700
Summary REGRESSION (Safari 17): Infinite reloading iframes on MDN and other websites,...
Florian Dieminger
Reported 2024-03-26 02:53:27 PDT
Created attachment 470604 [details] NodeJS http-server for a minimal repro Most live examples on MDN (https://developer.mozilla.org) are broken in Safari. They keep reloading and become unusable. I reduced the issue down to simple repro. The issue seems to be the combination of lazy loading iframes and the two headers: 'Cache-Control: no-store' and 'Clear-Site-Data: "*"'. I've attached a small example using a NodeJS http-server.
Attachments
NodeJS http-server for a minimal repro (1.35 KB, application/x-gzip)
2024-03-26 02:53 PDT, Florian Dieminger
no flags
video of the iframe glitching (4.66 MB, video/quicktime)
2024-03-26 08:56 PDT, Florian Dieminger
no flags
web inspector network tab (762.66 KB, image/jpeg)
2024-05-22 19:29 PDT, Karl Dubost
no flags
NodeJS http-server for a minimal repro (1.74 KB, application/x-gzip)
2024-05-23 04:07 PDT, Florian Dieminger
no flags
Alexey Proskuryakov
Comment 1 2024-03-26 08:48:29 PDT
Thank you for the report, and for the reduced test. Could you please post a link to a specific broken example for verification? I tried the live example at https://developer.mozilla.org/ru/docs/Web/CSS/mix-blend-mode, and don't see any problem with it.
Florian Dieminger
Comment 2 2024-03-26 08:56:19 PDT
Created attachment 470606 [details] video of the iframe glitching For me even that page has the bug. It seems racy sometimes on MDN. I used https://developer.mozilla.org/en-US/docs/Web/CSS/color_value to track it down. `Disable caches` in the dev tools help to reproduce it easier. Here's the bug report on MDN: https://github.com/mdn/yari/issues/10764
Florian Dieminger
Comment 3 2024-03-26 08:57:21 PDT
I also reproduced the issue in https://apps.gnome.org/Epiphany/.
Alexey Proskuryakov
Comment 4 2024-03-27 08:50:43 PDT
I can reproduce on MDN with caches disabled. I can reproduce with the attached node.js test, and didn't disable caches for that (I needed to create a blank favicon.ico, as otherwise node.js was exiting with an exception). Haven't been able to reproduce with any of the actual web pages though. Clear-Site-Data support is new in Safari 17.
Radar WebKit Bug Importer
Comment 5 2024-03-27 08:51:24 PDT
Simon Fraser (smfr)
Comment 6 2024-04-16 08:28:26 PDT
Simon Fraser (smfr)
Comment 7 2024-04-27 08:54:46 PDT
*** Bug 273343 has been marked as a duplicate of this bug. ***
Karl Dubost
Comment 8 2024-05-22 19:29:12 PDT
Created attachment 471476 [details] web inspector network tab I could reproduce on https://developer.mozilla.org/ru/docs/Web/CSS/mix-blend-mode with Safari Version 17.5 (19618.2.12.11.6) There is a constant reload of runner.
Karl Dubost
Comment 9 2024-05-22 19:31:42 PDT
Maybe Related Bug 272677
Karl Dubost
Comment 10 2024-05-22 19:45:02 PDT
I was wondering if lazy loading iframe would have an influence. So I deactivated it and after restarting and browsing a while WITH lazy loading iframe OFF I have been able to reproduce once. Sometimes it takes a while. That definitely feels like a race issue, and something related with caching. Because it's very random when it is triggered. AND it doesn't seem to reproduce once the frame is in the cache.
Karl Dubost
Comment 11 2024-05-22 20:10:59 PDT
Also while the inspector screenshot shows the same URI, this is not fully true. For me it was oscillating in between multiple requests. Testing this page where the last example iframe exhibited the issue. https://developer.mozilla.org/en-US/docs/Web/CSS/gap I let it go until it stopped by itself, and around 6154 HTTP requests were done. Including: 2254 to multi-column_layout 1620 to flex_layout 2210 to grid_layout the requests are exactly all the same: which is basically :method: GET :scheme: https :authority: live.mdnplay.dev :path: /en-US/docs/Web/CSS/gap/runner.html?id=flex_layout Sec-Fetch-Site: same-origin Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Referer: https://live.mdnplay.dev/ Sec-Fetch-Dest: iframe Cache-Control: max-age=0 Sec-Fetch-Mode: navigate Host: live.mdnplay.dev Accept-Language: en-US,en;q=0.9 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Safari/605.1.15 Accept-Encoding: gzip, deflate, br Connection: keep-alive The only difference in between them is the path :path: /en-US/docs/Web/CSS/gap/runner.html?id=multi-column_layout :path: /en-US/docs/Web/CSS/gap/runner.html?id=flex_layout :path: /en-US/docs/Web/CSS/gap/runner.html?id=grid_layout I can't reproduce on internal builds. Another which I found interesting, is the HTTP response, which was identical no matter the path. and the ETag was exactly the same. This is not logical. The runner.html?id=blah should have unique ETag Example of an HTTP response :status: 200 Content-Encoding: br Content-Security-Policy: default-src 'self' https:; script-src 'self' https: 'unsafe-eval' 'unsafe-inline' 'wasm-unsafe-eval'; script-src-elem 'self' https: 'unsafe-eval' 'unsafe-inline' 'wasm-unsafe-eval'; style-src 'report-sample' 'self' https: 'unsafe-inline' 'unsafe-eval'; img-src 'self' blob: https: data:; base-uri 'self'; worker-src 'self'; manifest-src 'self'; Cache-Control: public, max-age=3600 Accept-Ranges: none Content-Length: 1380 Via: 1.1 google Vary: Accept-Encoding Date: Thu, 23 May 2024 02:47:20 GMT Clear-Site-Data: "*" Expires: Thu, 23 May 2024 03:08:39 GMT Age: 2321 ETag: W/"96d8671a40e5b38c01f24f21e8523bda" Content-Type: text/html X-Content-Type-Options: nosniff Last-Modified: Thu, 09 May 2024 00:41:19 GMT x-goog-stored-content-encoding: identity Server: Google Frontend Strict-Transport-Security: max-age=63072000 x-goog-generation: 1715215279532479 x-cloud-trace-context: 1198abd3b805dfde87f5bf0f25be8b55 Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000, clear x-goog-meta-goog-reserved-file-mtime: 1715213586 x-goog-storage-class: STANDARD x-guploader-uploadid: ABPtcPq8V_OqBAUwIxaSCSHK11F9xdmfJVYgA72WF7vpq8kHCwTvuHYEwfPDB18F-eoF4B1tqWI x-goog-hash: crc32c=GcPUyA==, md5=lthnGkDls4wB8k8h6FI72g== x-goog-stored-content-length: 4664 x-goog-metageneration: 1 x-cache: hit
Karl Dubost
Comment 12 2024-05-22 20:14:26 PDT
About Clear-Site-Data there is also Bug 264852
Florian Dieminger
Comment 13 2024-05-23 04:07:16 PDT
Created attachment 471480 [details] NodeJS http-server for a minimal repro Added an empty favicon.ico
Florian Dieminger
Comment 14 2024-05-23 04:12:09 PDT
Thanks for looking into it. I'll see how I can fix the etag issue on MDN. However, for me (and Alexey) the nodejs example in the attachment reproduces the issue, too. It's much more basic than what happens on MDN. The multiple URLs seem key to this, but it only needs two like in the repro.
Karl Dubost
Comment 15 2024-05-23 05:12:51 PDT
Yes there is definitely an issue to dig more. This should not happen.
Karl Dubost
Comment 16 2024-08-14 16:58:48 PDT
Florian, did you have a chance to fix the ETAG?
Florian Dieminger
Comment 17 2024-08-16 06:55:35 PDT
Thanks for reminding me of this again. The ETag comment fell through the cracks. I have a version on our staging system that generates an ETag per path / search query. https://developer.allizom.org/en-US/docs/Web/CSS/mix-blend-mode I see the same issue in Safari there. However, can you elaborate why we should not send the same ETag in these cases? The response body is identical as it's all the same "runner.html". As far as I understand sending the same ETag should be okay.
Karl Dubost
Comment 18 2024-08-18 17:58:28 PDT
hmm indeed runner.html is the same resources being sent and the parameters is not really used for a server side generated HTTP response. I wonder if it has influences on the behavior. Going into diagnosis and exploration mode. Trying again https://developer.mozilla.org/en-US/docs/Web/CSS/color_value and looking at the HTTP headers in Safari. ``` :status: 200 Content-Encoding: br Content-Security-Policy: default-src 'self' https:; script-src 'self' https: 'unsafe-eval' 'unsafe-inline' 'wasm-unsafe-eval'; script-src-elem 'self' https: 'unsafe-eval' 'unsafe-inline' 'wasm-unsafe-eval'; style-src 'report-sample' 'self' https: 'unsafe-inline' 'unsafe-eval'; img-src 'self' blob: https: data:; base-uri 'self'; worker-src 'self'; manifest-src 'self'; Cache-Control: public, max-age=3600 Accept-Ranges: none Content-Length: 1399 Via: 1.1 google Vary: Accept-Encoding Date: Mon, 19 Aug 2024 00:16:24 GMT Clear-Site-Data: "*" Expires: Mon, 19 Aug 2024 01:16:24 GMT Age: 288 ETag: W/"8238077df3182df1632f0f540f37537f" Content-Type: text/html X-Content-Type-Options: nosniff Last-Modified: Fri, 05 Jul 2024 00:55:18 GMT x-goog-stored-content-encoding: identity Server: Google Frontend Strict-Transport-Security: max-age=63072000 x-goog-generation: 1720140918046816 x-cloud-trace-context: b1042df4c12adf51c4b6265ebd9c71b9 Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000, clear x-cache: hit ``` I also noticed ``` Clear-Site-Data: "*" ``` Reading again the spec https://w3c.github.io/webappsec-clear-site-data/ It clears everything, even the cache. I wonder if it could be a source of the issue between MDN and Safari, but then why Firefox and Chrome would not be affected. Currently, the server for runner.html is just generating HTTP 200 Responses. In Firefox ``` HTTP/2 200 x-goog-generation: 1720140918046816 x-goog-metageneration: 1 x-goog-stored-content-encoding: identity x-goog-stored-content-length: 4829 x-goog-meta-goog-reserved-file-mtime: 1720138416 x-goog-hash: crc32c=WXcl1w==, md5=gjgHffMYLfFjLw9UDzdTfw== x-goog-storage-class: STANDARD accept-ranges: none x-guploader-uploadid: AHxI1nOjhXxfwexauXKtiam0jvnXqvE287AOt1-x-6Gip3PO0HiU4ORta6p6kSoTbBxbsrY_jQY72zVU7Q expires: Mon, 19 Aug 2024 00:42:46 GMT cache-control: public, max-age=3600 last-modified: Fri, 05 Jul 2024 00:55:18 GMT etag: W/"8238077df3182df1632f0f540f37537f" content-type: text/html age: 3329 alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000, clear x-content-type-options: nosniff clear-site-data: "*" strict-transport-security: max-age=63072000 content-security-policy: default-src 'self' https:; script-src 'self' https: 'unsafe-eval' 'unsafe-inline' 'wasm-unsafe-eval'; script-src-elem 'self' https: 'unsafe-eval' 'unsafe-inline' 'wasm-unsafe-eval'; style-src 'report-sample' 'self' https: 'unsafe-inline' 'unsafe-eval'; img-src 'self' blob: https: data:; base-uri 'self'; worker-src 'self'; manifest-src 'self'; x-cloud-trace-context: 46ae97c41a55912e9ea651c5b861b602 date: Mon, 19 Aug 2024 00:38:15 GMT server: Google Frontend via: 1.1 google vary: Accept-Encoding content-encoding: br x-cache: miss X-Firefox-Spdy: h2 ``` which is a bit weird to download again the same resource again and again for all examples (but at least logical based on the id parameters as said above), but at least in Firefox it doesn't enter in a loop. Let's look at the HTTP request https://live.mdnplay.dev/en-US/docs/Web/CSS/color_value/runner.html?id=currentcolor_keyword Safari ``` :method: GET :scheme: https :authority: live.mdnplay.dev :path: /en-US/docs/Web/CSS/color_value/runner.html?id=currentcolor_keyword Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Sec-Fetch-Site: same-origin Referer: https://live.mdnplay.dev/ Sec-Fetch-Dest: iframe Cache-Control: max-age=0 Sec-Fetch-Mode: navigate Accept-Language: en-US,en;q=0.9 Accept-Encoding: gzip, deflate, br User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Safari/605.1.15 Priority: u=0, i ``` And Firefox ``` GET /en-US/docs/Web/CSS/color_value/runner.html?id=currentcolor_keyword HTTP/2 Host: live.mdnplay.dev User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:131.0) Gecko/20100101 Firefox/131.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8 Accept-Language: en-US,en;q=0.8,fr-FR;q=0.5,ja;q=0.3 Accept-Encoding: gzip, deflate, br, zstd Connection: keep-alive Referer: https://developer.mozilla.org/ Upgrade-Insecure-Requests: 1 Sec-Fetch-Dest: iframe Sec-Fetch-Mode: navigate Sec-Fetch-Site: cross-site Priority: u=4 ``` Interesting the referer is different for Safari and Firefox. Also Safari has a `max-age=0` in the request that Firefox doesn't have. And Chrome ``` :authority: live.mdnplay.dev method: GET path: /en-US/docs/Web/CSS/color_value/runner.html?id=currentcolor_keyword scheme: https Accept: text/html, application/xhtml+xml,application/xmI;q=0.9, image/avif,image/webp, image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Accept-Encoding: gzip, deflate, br, zstd Accept-Language: en-US, en;q=0.9 Cache-Control: no-cache Pragma: no-cache Priority: u=0, i Referer: https://developer.mozilla.org/ Sec-Ch-Ua: "Google Chrome":;v="129", "Not=A?Brand";v="g", "Chromium";="129" Sec-Ch-Ua-Mobile: ?0 Sec-Ch-Ua-Platform: "macOS" Sec-Fetch-Dest: iframe Sec-Fetch-Mode: navigate Sec-Fetch-Site: cross-site Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 ```` Cache-Control is no-cache in chrome, but it's not reloading in loop. So maybe this is something else.
Chris Dumez
Comment 19 2024-10-25 09:33:35 PDT
As far as I can tell, we're doing what the website is asking us to? The website has several frames (or the same origin) which serve the `Clear-Site-Data: *` HTTP header. As per the specification, '*' includes 'executionContexts`, which asks the user agent to reload all frames from this origin. So you have frame A and frame B from the same origin, they each serve `Clear-Site-Data: *` HTTP header, causing each other to get reloaded. Upon reload, they serve the exact same header, rinse and repeat. I'm looking at the specification but it's not clear to me yet what we're supposed to do to avoid infinite reloads in this case.
Chris Dumez
Comment 20 2024-10-25 09:39:44 PDT
(In reply to Chris Dumez from comment #19) > As far as I can tell, we're doing what the website is asking us to? > > The website has several frames (or the same origin) which serve the > `Clear-Site-Data: *` HTTP header. As per the specification, '*' includes > 'executionContexts`, which asks the user agent to reload all frames from > this origin. > > So you have frame A and frame B from the same origin, they each serve > `Clear-Site-Data: *` HTTP header, causing each other to get reloaded. Upon > reload, they serve the exact same header, rinse and repeat. > > I'm looking at the specification but it's not clear to me yet what we're > supposed to do to avoid infinite reloads in this case. According to MDN, Safari is the only browser supporting "executionContexts" for Clear-Site-Data, which would explain why it wouldn't impact other browsers. I suggest we unship support for "executionContexts" given how risky it is currently.
Chris Dumez
Comment 21 2024-10-25 09:56:05 PDT
EWS
Comment 22 2024-10-25 14:03:27 PDT
Committed 285712@main (bd98a6494eff): <https://commits.webkit.org/285712@main> Reviewed commits have been landed. Closing PR #35724 and removing active labels.
EWS
Comment 23 2024-11-07 12:00:40 PST
Committed 283286.448@safari-7620-branch (555db26d34df): <https://commits.webkit.org/283286.448@safari-7620-branch> Reviewed commits have been landed. Closing PR #2239 and removing active labels.
Note You need to log in before you can comment on or make changes to this bug.