Bug 234249

Summary: Downloading DMG using WKDownload errors with "You do not have permission"
Product: WebKit Reporter: Saurav Mitra <mitrasaurav97>
Component: New BugsAssignee: Alex Christensen <achristensen>
Status: REOPENED ---    
Severity: Normal CC: achristensen, cdumez, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: Safari 14   
Hardware: Mac (Apple Silicon)   
OS: macOS 11   
Attachments:
Description Flags
Xcode project that replicates bug
none
Patch
none
Patch none

Description Saurav Mitra 2021-12-13 09:34:56 PST
Created attachment 447017 [details]
Xcode project that replicates bug

Overview: If you download a DMG using WKNavigationResponsePolicy.download and WKDownload and try to open the app inside, you get either the error "You do not have permission to open the application" (macOS 11) or "This application can't be opened" (macOS 12)

Steps to Reproduce: I've included an Xcode project that will automatically open a page that downloads the DMG for Slack.
1. Run the project
2. Wait for the file to complete downloading (It will print "DOWNLOAD COMPLETE")
3. Open the dmg and try to open the Slack app.

Actual Results: An error prompt appears, not allowing the user to open the app at all.

Expected Results: The Slack app will open (with a quarantine dialog first to confirm opening the app)

Build & Hardware: Build 16611.2.7.1.4 on macOS 11.4
Comment 1 Saurav Mitra 2021-12-13 11:17:52 PST
The GateKeeper score (i.e. the first number in the com.apple.quarantine extended attribute found through xattr -l /path/to/file.dmg) is 0086. If I change that to 0083 (like Safari) or 0081 (like Chrome), the app opens as expected.

Any ideas why the GateKeeper score of the downloaded file is set to 0086?
Comment 2 Alexey Proskuryakov 2021-12-13 17:40:40 PST
No, Gatekeeper score is not implemented by WebKit.
Comment 3 Saurav Mitra 2021-12-14 01:23:23 PST
WebKit must be using something which is causing this issue though. As seen in the attached Xcode project, I'm not using anything apart from the built-in WKDownload. If I download it myself using URLSession, then the GateKeeper score is 0082, and it opens correctly.
Comment 4 Radar WebKit Bug Importer 2021-12-20 09:35:19 PST
<rdar://problem/86727858>
Comment 5 Alex Christensen 2022-06-10 14:57:53 PDT
This is a legitimate WebKit bug that we need to fix.
Comment 6 Alex Christensen 2022-06-13 14:15:16 PDT
I just verified we do the same thing as NSURLSession, which makes me less sure that this is something we should change.
Comment 7 Saurav Mitra 2022-06-14 02:43:33 PDT
The intent is for all valid files downloaded off a web page is to be openable. Currently, that isn't the case. If you use WKDownloads and force open the file (right-click -> Open instead of double-click, but no user really knows about this), the system tells the user that the file was downloaded by com.apple.WebKit.Networking. Not the biggest problem for me, but still a sign that the quarantine extended attribute needs to be modified, one way or the other.

Not using WKDownloads means downloading the files with a URLSessionDownloadTask myself. This works, except for the case where the file needs specific cookies before it will serve it, which is quite a bit more complicated than the case of a simple download. (An extra slight caveat with this method: It will say "This file was downloaded from APP_NAME" when opening instead of "This file was downloaded from the internet". My best guess is because the Gatekeeper score with this method is 0082, and the least significant bit isn't set)
Comment 8 Alex Christensen 2022-06-14 08:42:22 PDT
Are you using URLSessionDownloadTask in an app that is code signed?  I verified that doing that makes a file that is also unable to be opened.

The com.apple.WebKit.Networking attribute should probably be changed to match the app, but maybe I should clarify that I'm not sure the ability to open is something we (WebKit) should change without coordinating with CFNetwork.
Comment 9 Saurav Mitra 2022-06-14 09:14:21 PDT
Yes, I'm using it in an app that is code-signed and already deployed to users! I'll try and create a sample project perhaps and attach it in a bit.
Comment 10 Alex Christensen 2022-06-21 19:08:01 PDT
Created attachment 460399 [details]
Patch
Comment 11 Alex Christensen 2022-06-22 00:24:10 PDT
Created attachment 460408 [details]
Patch
Comment 12 Alex Christensen 2022-06-22 01:07:04 PDT
Saurav, is your app sandboxed?
Comment 13 Saurav Mitra 2022-06-22 01:18:33 PDT
Yes, it's sandboxed.
Comment 14 EWS 2022-06-22 08:57:03 PDT
Committed r295731 (251736@main): <https://commits.webkit.org/251736@main>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 460408 [details].
Comment 15 Saurav Mitra 2022-06-22 09:29:27 PDT
Thanks for looking into this!
Just checked out the commit and if I understand correctly, you're only clearing the QTN_FLAG_HARD flag if the app is not sandboxed? What about sandboxed apps using WKDownloads? 
(Can confirm that a sandobxed app using URLSessionDownloadTask does not have this quarantine issue)
Comment 16 Saurav Mitra 2022-06-22 09:30:31 PDT
Just marking as Reopened if that's needed to notify people
Comment 17 Alex Christensen 2022-06-22 09:30:56 PDT
I can confirm that this fixes non-sandboxed apps.  I think it might depend on your sandbox, but I know there are some sandboxes that don't allow removing QTN_FLAG_HARD.
Comment 18 Saurav Mitra 2022-06-22 09:36:47 PDT
Hmm, I'm not very familiar with sandboxes. Ours is just enabled by the "App Sandbox" entitlement being set to "YES". I understand why the app shouldn't be able to modify quarantine attributes (or extended file attributes in general) for files, but I don't see why that should apply to the file it's creating internally (especially since that's through WebKit, and a warning shows up before you open anyways).
Comment 19 Alex Christensen 2022-06-22 10:11:43 PDT
I have a theory that if URLSessionDownloadTask can make a downloaded application openable then this code ought to be able to remove QTN_FLAG_HARD but I haven't verified that theory yet.