Bug 204109 - REGRESSION (iOS 13.3): WKWebView does not include cookies in cross-origin images
Summary: REGRESSION (iOS 13.3): WKWebView does not include cookies in cross-origin images
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: Safari Technology Preview
Hardware: iPhone / iPad iOS 13
: P2 Normal
Assignee: John Wilander
URL: https://niklas.merz.dev/corstest/
Keywords: InRadar
: 206295 (view as bug list)
Depends on:
Blocks:
 
Reported: 2019-11-12 04:36 PST by Niklas Merz
Modified: 2020-10-19 04:28 PDT (History)
11 users (show)

See Also:


Attachments
Example project with test page (43.62 KB, application/zip)
2019-11-12 04:36 PST, Niklas Merz
no flags Details
Proposed patch (14.16 KB, patch)
2019-11-16 14:38 PST, John Wilander
ap: review+
Details | Formatted Diff | Diff
Proposed patch addressing Chris's comments (14.16 KB, patch)
2019-11-16 16:00 PST, John Wilander
no flags Details | Formatted Diff | Diff
Proposed patch addressing Chris's comments (17.79 KB, patch)
2019-11-16 16:03 PST, John Wilander
cdumez: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Niklas Merz 2019-11-12 04:36:09 PST
Created attachment 383348 [details]
Example project with test page

We found a bug in our app (using WKWebView) that images that are loaded from another origin don't load because the necessary cookie is not sent.

I added a small sample project which opens a test page in WKWebview. This page has two img tags. One of the loads the image from the same origin, one from another one. Both images need a cookie, otherwhise an error is thrown. The cookies for thesse images are set in Swift code before opening the WebView.

If I run this project with two devices and iOS version, I get different result:

* iOS 13.2: Both images are displayed at app launch
* iOS 13.3 Developer Beta 2: Only the same origin image is displayed

Bug  200857 was a similiar issue in iOS 13, but is fixed since iOS 13.2
Comment 1 Radar WebKit Bug Importer 2019-11-12 10:19:33 PST
<rdar://problem/57120772>
Comment 2 Alexey Proskuryakov 2019-11-15 11:56:39 PST
Is the server up and running now? We are getting question marks for the images.
Comment 3 Niklas Merz 2019-11-15 12:02:59 PST
Yes that is the point. You need a cookie with a Value test. The Native App from the attachment Sets the cookie.
Comment 4 Niklas Merz 2019-11-15 12:40:25 PST
(In reply to Niklas Merz from comment #3)
> Yes that is the point. You need a cookie with a Value test. The Native App
> from the attachment Sets the cookie.

If you open the page in a browser there will be no images. Setting a cookie like corstest=tes will make the image accessible. If you open the test app on iOS 13.3 there will be one image from the same origin, on iOS 13.2 two images from both origins.

The test page is available on Github. I did set a check on cookies for the images via a serverless function for the hosting: https://github.com/NiklasMerz/corstest

Can you reproduce this issue?
Comment 5 John Wilander 2019-11-16 14:38:28 PST
Created attachment 383705 [details]
Proposed patch

Patch for review. Note that it is branch-specific and won't apply to trunk.
Comment 6 Alexey Proskuryakov 2019-11-16 14:54:03 PST
Comment on attachment 383705 [details]
Proposed patch

View in context: https://bugs.webkit.org/attachment.cgi?id=383705&action=review

> LayoutTests/ChangeLog:9
> +        * http/tests/resourceLoadStatistics/no-third-party-cookie-blocking-when-itp-is-off-expected.txt: Added.

Test pieces will need to be landed on trunk too.
Comment 7 Chris Dumez 2019-11-16 14:58:21 PST
Comment on attachment 383705 [details]
Proposed patch

View in context: https://bugs.webkit.org/attachment.cgi?id=383705&action=review

> Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:208
> +        || (session.isResourceLoadStatisticsEnabled() && session.networkStorageSession() && session.networkStorageSession()->shouldBlockCookies(request, frameID, pageID));

There are other call sites that call shouldBlockCookies() without checking if ITP is enabled. Why are those OK?
Why isn't the isITPEnabled check inside shouldBlockCookies()?
Comment 8 John Wilander 2019-11-16 15:04:12 PST
(In reply to Alexey Proskuryakov from comment #6)
> Comment on attachment 383705 [details]
> Proposed patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=383705&action=review
> 
> > LayoutTests/ChangeLog:9
> > +        * http/tests/resourceLoadStatistics/no-third-party-cookie-blocking-when-itp-is-off-expected.txt: Added.
> 
> Test pieces will need to be landed on trunk too.

Absolutely.
Comment 9 John Wilander 2019-11-16 15:07:42 PST
(In reply to Chris Dumez from comment #7)
> Comment on attachment 383705 [details]
> Proposed patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=383705&action=review
> 
> > Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:208
> > +        || (session.isResourceLoadStatisticsEnabled() && session.networkStorageSession() && session.networkStorageSession()->shouldBlockCookies(request, frameID, pageID));
> 
> There are other call sites that call shouldBlockCookies() without checking
> if ITP is enabled. Why are those OK?

I'll have a look.

> Why isn't the isITPEnabled check inside shouldBlockCookies()?

It's the NetworkSession that knows. But maybe I can forward that info to the NetworkStorageSession. But that increases the risk of the change, right?
Comment 10 Chris Dumez 2019-11-16 15:18:30 PST
(In reply to John Wilander from comment #9)
> (In reply to Chris Dumez from comment #7)
> > Comment on attachment 383705 [details]
> > Proposed patch
> > 
> > View in context:
> > https://bugs.webkit.org/attachment.cgi?id=383705&action=review
> > 
> > > Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:208
> > > +        || (session.isResourceLoadStatisticsEnabled() && session.networkStorageSession() && session.networkStorageSession()->shouldBlockCookies(request, frameID, pageID));
> > 
> > There are other call sites that call shouldBlockCookies() without checking
> > if ITP is enabled. Why are those OK?
> 
> I'll have a look.
> 
> > Why isn't the isITPEnabled check inside shouldBlockCookies()?
> 
> It's the NetworkSession that knows. But maybe I can forward that info to the
> NetworkStorageSession. But that increases the risk of the change, right?

Hmm, I see what you mean, NetworkStorageSession is actually in WebCore and does not have access to the NetworkSession and does not know about the NetworkSession.

My alternate proposal then then would be to rename the method name to be less generic (e.g. shouldBlockCookieDueToITP()) and make sure all call sites check that ITP is enabled before calling. This is assuming this function is only used for ITP purposes (I don't actually know that for sure).
Comment 11 John Wilander 2019-11-16 15:58:53 PST
(In reply to Chris Dumez from comment #10)
> (In reply to John Wilander from comment #9)
> > (In reply to Chris Dumez from comment #7)
> > > Comment on attachment 383705 [details]
> > > Proposed patch
> > > 
> > > View in context:
> > > https://bugs.webkit.org/attachment.cgi?id=383705&action=review
> > > 
> > > > Source/WebKit/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:208
> > > > +        || (session.isResourceLoadStatisticsEnabled() && session.networkStorageSession() && session.networkStorageSession()->shouldBlockCookies(request, frameID, pageID));
> > > 
> > > There are other call sites that call shouldBlockCookies() without checking
> > > if ITP is enabled. Why are those OK?
> > 
> > I'll have a look.
> > 
> > > Why isn't the isITPEnabled check inside shouldBlockCookies()?
> > 
> > It's the NetworkSession that knows. But maybe I can forward that info to the
> > NetworkStorageSession. But that increases the risk of the change, right?
> 
> Hmm, I see what you mean, NetworkStorageSession is actually in WebCore and
> does not have access to the NetworkSession and does not know about the
> NetworkSession.
> 
> My alternate proposal then then would be to rename the method name to be
> less generic (e.g. shouldBlockCookieDueToITP()) and make sure all call sites
> check that ITP is enabled before calling. This is assuming this function is
> only used for ITP purposes (I don't actually know that for sure).

Your overall comment was valid - thank you for that! I have another approach.

I will forward the on/off status of ITP to NetworkStorageSession and check it in the shouldBlockCookies() functions.

This increases the patch's complexity slightly but not in a material way since it's just about forwarding a boolean flag and the infrastructure for the ITP setting is already there.

New patch coming.
Comment 12 John Wilander 2019-11-16 16:00:42 PST
Created attachment 383708 [details]
Proposed patch addressing Chris's comments
Comment 13 John Wilander 2019-11-16 16:03:02 PST
Created attachment 383709 [details]
Proposed patch addressing Chris's comments
Comment 14 Chris Dumez 2019-11-16 16:11:25 PST
Comment on attachment 383709 [details]
Proposed patch addressing Chris's comments

View in context: https://bugs.webkit.org/attachment.cgi?id=383709&action=review

> Source/WebKit/NetworkProcess/NetworkSession.cpp:134
> +        if (auto* storageSession = networkStorageSession())

Could this be move to the top of the method to avoid the duplication?

ASSERT(!m_isInvalidated);
if (auto* storageSession = networkStorageSession())
    storageSession->setResourceLoadStatisticsEnabled(enable);
Comment 15 John Wilander 2019-11-16 16:13:09 PST
(In reply to Chris Dumez from comment #14)
> Comment on attachment 383709 [details]
> Proposed patch addressing Chris's comments
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=383709&action=review
> 
> > Source/WebKit/NetworkProcess/NetworkSession.cpp:134
> > +        if (auto* storageSession = networkStorageSession())
> 
> Could this be move to the top of the method to avoid the duplication?
> 
> ASSERT(!m_isInvalidated);
> if (auto* storageSession = networkStorageSession())
>     storageSession->setResourceLoadStatisticsEnabled(enable);

Yes. Will fix before sending to branch integrators. Thanks for the review!
Comment 16 John Wilander 2019-11-16 16:14:49 PST
(In reply to John Wilander from comment #15)
> (In reply to Chris Dumez from comment #14)
> > Comment on attachment 383709 [details]
> > Proposed patch addressing Chris's comments
> > 
> > View in context:
> > https://bugs.webkit.org/attachment.cgi?id=383709&action=review
> > 
> > > Source/WebKit/NetworkProcess/NetworkSession.cpp:134
> > > +        if (auto* storageSession = networkStorageSession())
> > 
> > Could this be move to the top of the method to avoid the duplication?
> > 
> > ASSERT(!m_isInvalidated);
> > if (auto* storageSession = networkStorageSession())
> >     storageSession->setResourceLoadStatisticsEnabled(enable);
> 
> Yes. Will fix before sending to branch integrators. Thanks for the review!

Or wait, now I remember why I had it in two places - to guarantee that the ITP object has been created before I tell the storage session that ITP is on. Do you think that'll cause an issue with your proposed change?
Comment 17 Chris Dumez 2019-11-16 16:23:57 PST
(In reply to John Wilander from comment #16)
> (In reply to John Wilander from comment #15)
> > (In reply to Chris Dumez from comment #14)
> > > Comment on attachment 383709 [details]
> > > Proposed patch addressing Chris's comments
> > > 
> > > View in context:
> > > https://bugs.webkit.org/attachment.cgi?id=383709&action=review
> > > 
> > > > Source/WebKit/NetworkProcess/NetworkSession.cpp:134
> > > > +        if (auto* storageSession = networkStorageSession())
> > > 
> > > Could this be move to the top of the method to avoid the duplication?
> > > 
> > > ASSERT(!m_isInvalidated);
> > > if (auto* storageSession = networkStorageSession())
> > >     storageSession->setResourceLoadStatisticsEnabled(enable);
> > 
> > Yes. Will fix before sending to branch integrators. Thanks for the review!
> 
> Or wait, now I remember why I had it in two places - to guarantee that the
> ITP object has been created before I tell the storage session that ITP is
> on. Do you think that'll cause an issue with your proposed change?

It is just setting a Boolean, the setter does not rely on the ITP object in any way (and cannot really since they live at different layers), so I think it would be fine. Why did you have concerns?
Comment 18 John Wilander 2019-11-16 16:27:04 PST
(In reply to Chris Dumez from comment #17)
> (In reply to John Wilander from comment #16)
> > (In reply to John Wilander from comment #15)
> > > (In reply to Chris Dumez from comment #14)
> > > > Comment on attachment 383709 [details]
> > > > Proposed patch addressing Chris's comments
> > > > 
> > > > View in context:
> > > > https://bugs.webkit.org/attachment.cgi?id=383709&action=review
> > > > 
> > > > > Source/WebKit/NetworkProcess/NetworkSession.cpp:134
> > > > > +        if (auto* storageSession = networkStorageSession())
> > > > 
> > > > Could this be move to the top of the method to avoid the duplication?
> > > > 
> > > > ASSERT(!m_isInvalidated);
> > > > if (auto* storageSession = networkStorageSession())
> > > >     storageSession->setResourceLoadStatisticsEnabled(enable);
> > > 
> > > Yes. Will fix before sending to branch integrators. Thanks for the review!
> > 
> > Or wait, now I remember why I had it in two places - to guarantee that the
> > ITP object has been created before I tell the storage session that ITP is
> > on. Do you think that'll cause an issue with your proposed change?
> 
> It is just setting a Boolean, the setter does not rely on the ITP object in
> any way (and cannot really since they live at different layers), so I think
> it would be fine. Why did you have concerns?

My concern was that the storage session would immediately start acting as if ITP is on.
Comment 19 John Wilander 2019-11-16 16:38:12 PST
I will keep this bug open until we have a revision for the branch patch landing.
Comment 20 Brent Fulgham 2019-11-18 12:28:52 PST
It looks like the patch was landed on the branch here:

https://trac.webkit.org/r252549.

Are you planning on landing this on Trunk (or creating a trunk-compatible patch?)
Comment 21 John Wilander 2019-11-18 12:57:48 PST
Resolved with https://trac.webkit.org/changeset/252549/webkit, as pointed out by Brent. I will land a fix in trunk in another Bugzilla bug.
Comment 22 David M 2019-11-20 09:12:13 PST
John, would you know if this will make it into 13.3 before GA?  Thanks for the fix!
Comment 23 Brent Fulgham 2019-11-20 09:13:59 PST
(In reply to David M from comment #22)
> John, would you know if this will make it into 13.3 before GA?  Thanks for
> the fix!

We cannot comment on when a change will get into a production release. However, we recognize the importance of the change and view this as a regression from 13.2, so are treating it with high priority.
Comment 24 David M 2019-11-20 09:15:54 PST
Understood, thanks for the info and the help!  Much appreciated!
Comment 25 Niklas Merz 2019-12-06 03:42:12 PST
I just did a quick test with iOS 13.3 Beta 4 and it look like the issue is resolved!
Comment 26 David M 2019-12-06 09:19:26 PST
Agreed, thanks to those that fixed this!
Comment 27 David M 2019-12-12 08:05:58 PST
FYI it appears as though this issue exists in the iOS 13.3 Simulator on the Mac with Xcode 11.3 (11C29)
Comment 28 John Wilander 2020-01-16 10:53:29 PST
*** Bug 206295 has been marked as a duplicate of this bug. ***
Comment 29 Niklas Merz 2020-06-23 03:03:42 PDT
I just tested this with iOS 14 developer beta. This is broken again.

If I run the attached test project with Xcode 12 beta on an iPhone with iOS 14 I dpn't see the cors image. The latest iOS 13 still works as expected.
Comment 30 David Kilzer (:ddkilzer) 2020-06-23 05:29:11 PDT
(In reply to Niklas Merz from comment #29)
> I just tested this with iOS 14 developer beta. This is broken again.
> 
> If I run the attached test project with Xcode 12 beta on an iPhone with iOS
> 14 I dpn't see the cors image. The latest iOS 13 still works as expected.

Please file a new bug and relate this one!
Comment 31 David Kilzer (:ddkilzer) 2020-06-23 08:51:07 PDT
(In reply to John Wilander from comment #21)
> Resolved with https://trac.webkit.org/changeset/252549/webkit, as pointed
> out by Brent. I will land a fix in trunk in another Bugzilla bug.

Was this fix ever ported to trunk, or did we forget to do that?


(In reply to David Kilzer (:ddkilzer) from comment #30)
> (In reply to Niklas Merz from comment #29)
> > I just tested this with iOS 14 developer beta. This is broken again.
> > 
> > If I run the attached test project with Xcode 12 beta on an iPhone with iOS
> > 14 I dpn't see the cors image. The latest iOS 13 still works as expected.
> 
> Please file a new bug and relate this one!

Bug 213510: REGRESSION (iOS 14): WKWebView does not include cookies in cross-origin images