I have a macOS app in production, supporting all macOS versions since 10.15 (Catalina) thru Sequoia. One aspect of the app's functionality is to screen capture the entire screen, including all windows.
Starting with Sequoia, my users are receiving a scary system alert saying:
"SomeApp" is requesting to bypass the system private window picker and directly access your screen and audio. This will allow SomeApp to record your screen and system audio, including personal or sensitive information that may be visible or audible.
I have several questions and concerns about this alert. First of all, as a developer, this is frustrating, as I am using documented, long-standing system APIs, and made no change to my code to cause this warning. Second, nothing in my app records audio in any fashion, and yet the user is made to think I am trying to furtively bypass security controls to record audio, which is absolutely false. The alert seems to be due to the screen capture feature, which is one of the main features of the app, which the user explicitly requests and grants permission for.
But to get to the point of the question: is there any definitive documentation anywhere describing exactly which API's trigger this alert? I can't find first-party information from Apple, so I'm kind of guessing in the dark.
Searching the internet for all the info I can find (mostly from blog posts of developers and beta-testers), it seemed like the culprit in my code was probably a call to CGWindowListCreateImage, so I spent some time forking the code paths in my app (since I still support back to 10.15) to use the more modern ScreenCaptureKit APIs on systems that support it. But the alert is still appearing, despite not calling into that API at all.
Is there a way of calling the modern ScreenCaptureKit APIs that also triggers this alert? As an example, I'm using a snippet like this to get the shareable displays I need
do {
try await SCShareableContent.excludingDesktopWindows(
false,
onScreenWindowsOnly: false
)
return true
} catch {
return false
}
is it possible that this code is triggering the alert because I'm not excluding desktop windows and asking for all windows?
to sum up, I (and I'm guessing others) could really use some definitive guidelines on exactly which APIs trigger this alert, so that we can migrate and avoid them if possible. can anyone provide any guidance on this? Thanks in advance!
Post
Replies
Boosts
Views
Activity
About 5 weeks ago, I requested a Family Controls Entitlement using this form:
https://developer.apple.com/contact/request/family-controls-distribution
I have yet to hear anything back. About a week ago, I submitted a support request through my Apple developer account, asking about the entitlement, and have also not heard anything back.
Is it normal to wait this long? Is there a way to check on the status of my request? Is there some other channel I should be using to ask for information about this process?
I know this might not be the exactly correct spot to post this, but I'm hoping to draw attention to a MAJOR REGRESSION in parental controls in iOS 17, in hopes that Apple will quickly release an update fixing it.
In iOS 17.0.0, parents can no longer delete the #images GIF search iMessages app from Apple. This could be removed in prior versions of iOS. Third-party apps can be removed from the Settings app, but not the ones from Apple.
This change is going to expose millions of kids to the possibility of searching for, seeing, and sending ******** graphic images. If you think I'm overstating the case, try searching for "bikini" or "********" in the messages app, and then think about the fact that parents no longer have the ability to prevent their kids from accessing this content.
Please, can someone from Apple respond that hopefully this was an oversight, and will be corrected in a forthcoming release? This represents a huge step backwards for the safety of iOS devices.
Or if there is a better venue to reach out to Apple, could someone point that out to me? Thanks so much!
I'm developing a macOS app that will usually be running in a non-admin user environment. But I have a screen of the app that I would like to secure so as to make it only accessible to admin users (think: parents).
I can't figure out what API I'm supposed to use to prompt for specifically an ADMIN user. I've tried googling a ton, but I must be trying the wrong search terms, because I can't find anything.
The API for LAContext() is almost what I want, I can get it to prompt for a password, but it seems to ONLY work for the current logged in user. I can't find a policy type that allows me to specify something like .adminUserAuthentication. It seems like LAContext() was not meant for this use case. But then, what is the right API to call to do this?
Can someone point me in the right direction?
I don't want to limit myself to this only working for supervised users, or users with parental controls turned on, I would like a generic solution. I've seen apps that prompt for admin credentials on regular non-admin users, so it must be possible, right?
The problem
I have a MacOS app that hosts a content filtering system extension, like SimpleFirewall.
The app has been in production for a couple years.
I'm working on a new version, and in testing the release candidate, I'm getting a
consistent crash that I believe is related to swift concurrency back deployment. Here are
the key details:
building using Xcode 14.2, from a machine running Monterrey, Swift 5.7.2
crash does not happen when building and testing from Xcode, locally
crash does not happen on test machine running Ventura
crash DOES happen always on a test machine running Big Sur
only the root-user system extension crashes, not the host application
the new version introduced async/await into the system extension
crash report shows identical stack trace to well-known issue that had to do with concurrency back deployment
Is there a known issue/limitation with concurrency back deployment in the context of a system extension? Is there any reason why async/await shouldn't work in that context when deployed to Big Sur?
More details, context
The key lines of the crash stack trace are:
0 libswiftCore.dylib 0x00007fff2cdacdc7 swift::ResolveAsSymbolicReference::operator()(swift::Demangle::__runtime::SymbolicReferenceKind, swift::Demangle::__runtime::Directness, int, void const*) + 55
1 libswiftCore.dylib 0x00007fff2cdcf2dd swift::Demangle::__runtime::Demangler::demangleSymbolicReference(unsigned char) + 141
2 libswiftCore.dylib 0x00007fff2cdcc2a8 swift::Demangle::__runtime::Demangler::demangleType(__swift::__runtime::llvm::StringRef, std::__1::function<swift::Demangle::__runtime::Node* (swift::Demangle::__runtime::SymbolicReferenceKind, swift::Demangle::__runtime::Directness, int, void const*)>) + 168
3 libswiftCore.dylib 0x00007fff2cdb25a4 swift_getTypeByMangledNameImpl(swift::MetadataRequest, __swift::__runtime::llvm::StringRef, void const* const*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 516
4 libswiftCore.dylib 0x00007fff2cdafd6d swift::swift_getTypeByMangledName(swift::MetadataRequest, __swift::__runtime::llvm::StringRef, void const* const*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 477
5 libswiftCore.dylib 0x00007fff2cdaff9b swift_getTypeByMangledNameInContext + 171
6 com.myorg.app.filter-extension 0x000000010db2b8b7 0x10db02000 + 170167
7 libdispatch.dylib 0x00007fff20516806 _dispatch_client_callout + 8
8 libdispatch.dylib 0x00007fff2051798c _dispatch_once_callout + 20
9 libswiftCore.dylib 0x00007fff2cdbe16a swift_once + 26
10 com.myorg.app.filter-extension 0x000000010db2c5e3 0x10db02000 + 173539
11 com.myorg.app.filter-extension 0x000000010dbbd708 0x10db02000 + 767752
12 com.myorg.app.filter-extension 0x000000010db073cc 0x10db02000 + 21452
13 com.apple.NetworkExtension 0x00007fff2dfdd4d8 -[NEExtensionProviderContext createWithCompletionHandler:] + 377
14 com.apple.Foundation 0x00007fff215a7c96 __NSXPCCONNECTION_IS_CALLING_OUT_TO_EXPORTED_OBJECT_S1__ + 10
15 com.apple.Foundation 0x00007fff21552b98 -[NSXPCConnection _decodeAndInvokeMessageWithEvent:flags:] + 2271
16 com.apple.Foundation 0x00007fff2150a049 message_handler + 206
17 libxpc.dylib 0x00007fff20406c24 _xpc_connection_call_event_handler + 56
18 libxpc.dylib 0x00007fff20405a9b _xpc_connection_mach_event + 938
The first five lines are identical to an issue from Xcode 13.2.1, discussed in depth on the swift forums:
https://forums.swift.org/t/async-await-crash-on-ios14-with-xcode-13-2-1/54541
...except I'm using Xcode 14.2. Which makes me think that it's not exactly the same bug, but another manifestation of a failure to link against the back-deployed currency lib, possibly having to do with the fact that the system extension isn't able to access the back-deployed lib.
The archived app does have libswift_Concurrency.dylib at MyApp.app/Contents/Frameworks/libswift_Concurrency.dylib.
What I've Tried
I tested the workaround in the above mentioned thread, using lipo to remove arm64 arch, but it didn't work.
I also tested adding -Xllvm -sil-disable-pass=alloc-stack-hoisting to Other Swift settings, as suggested in https://developer.apple.com/forums/thread/697070.
I would greatly appreciate any assistance.
I'm experiencing a really strange crash, so I spent some time making the absolute minimal reproduction possible, and I'm hoping someone can look into it.
(The reproduction repo is here, but note that you need to switch to the test-available branch to test the crash)
Suppose I have some multi-platform SwiftUI code, and I want to conditionally add a view modifier for platforms that support an api. Here's some code that calls out to fullScreenCover(isPresented:onDismiss:content:), which is not available at all for macOS:
public extension View {
@available(iOS 14, tvOS 14, watchOS 7, *)
@available(macOS, unavailable) // <-- NB: guard macOS 👍
func myModifier() -> some View {
self.fullScreenCover(isPresented: .constant(true)) {
Text("Hello fullscreen cover!")
}
}
}
Take note that the function is guarded with an @available(macOS, unavailable) atttribute.
Now, with this code in my project, without even CALLING that function anywhere, I'm immediately getting a crash on macOS 10.15 Catalina, for a missing symbol. The core line of the crash is below, and if helpful, the entire crash report is here.
Symbol not found: _$s7SwiftUI4ViewPAAE15fullScreenCover11isPresented9onDismiss7contentQrAA7BindingVySbG_yycSgqd__yctAaBRd__lFQOMQ
This shouldn't be, right? That code path should never be taken on 10.15, if I'm understanding correctly? Is this a bug? Is there some sort of alternative compiler directive that would prevent this crash?
Again, I have a super simple git repo reproducing this crash, just checkout the test-available branch, archive, sign, and it will crash on Catalina.
Any help would be greatly appreciated! 🙏
I'm wondering how to deal with a TSI that seems to have gone totally silent.
I opened the TSI on June 1 (bad timing with WWDC, I know).
I got one reply during WWDC asking if I could attend a Swift Lab (I couldn't for schedule reasons, and it was the last day).
I then got a reply on Monday, June 12, asking to attempt a repro with the most recent version of Xcode. I attempted the repro and replied back on June 15.
Since then, I've sent 2 or 3 additional replies, and have heard nothing. It's been a total of 17 days since I've heard from Apple on the TSI (June 12).
Is this normal? Is there some channel I could use to look into the lack of reply?
If any Apple engineer/staff is reading, the case ID is 2793633. I would be very grateful for any help getting this moving again.
I'm not sure I'm even using the right terminology to describe the question, but I'll try to explain.
I have a macOS utility application (LSUIElement=true) that does various things, some on a repeated schedule in the background. If there are multiple accounts on the computer, and "Fast User Switching" is enabled, then my application runs these background tasks for multiple users at a time -- fast switching to another user doesn't stop the application from doing things on a timer in the background (which I guess makes sense).
One of the background repeating tasks is expensive and makes no sense to do if the user isn't the "current" or "foreground", or "active" (terminology?) user. So I found myself wanting to ask the question programatically "does my user have the screen?"
I've done a lot of googling and exploring partially undocumented Swift and Objective-C APIs trying to figure this out, and I'm not sure if I'm on the right track, but was hoping someone could correct me or point me to some better concepts/resources/APIs, if possible.
The best I've been able to come up with is querying who the "Console User" is -- which seems almost always to map to the user "with the screen". But I honestly don't even know what the Console User really indicates, and if it's an accurate proxy for the question I'm trying to ask, or if it's some vestigial unix red-herring. Here's some working Swift code that sort-of seems to answer the question I'm asking:
import Foundation
import SystemConfiguration
func currentUserHasScreen() -> Bool {
var uid: uid_t = 0
SCDynamicStoreCopyConsoleUser(nil, &uid, nil)
return uid == getuid()
}
All that said, I'm hoping someone could share their knowledge on some specific questions related to this issue:
What exactly is the ConsoleUser, and what information is it meant to convey?
Does the Swift function shown above seem like an appropriate/correct/safe way to figure out if the current user has the screen?
Is it even correct to ask "who has the screen?" -- could multiple users have the screen? (I experimented and was able to be logged in normally with one user on a machine, and then I screen-shared a different user, both worked at the same time -- who "has the screen" in that scenario?)
Would it be better or more correct to ask "does this user have ANY screen/display?" For my use case, the background task has to do with taking screenshots, I don't want to take screenshots if nobody is logged in or looking at a screen (even though the OS happily will do so).
When running the experiment mentioned in number 3 above, the screen sharing app prompted me saying "harriet" is currently using the display on "mini" -- what core concepts are being leveraged here? -- how does the OS know who "has the display", and is that what I should be querying instead?
Would greatly appreciate any insight on as many of these issues as anyone has knowledge of, and I think future googlers would as well. 🙏
Hi there. I've been working for quite a while prototyping a Content Filter app. I started with the SimpleFirewall code as a base, slowly making changes to it, as my use case is fairly different from the sample code - an internet safety app for kids, not a firewall.
I've spent a long time figuring out some of the intricacies of filtering NEFilterFlow objects, and working out the (fairly difficult) IPC communication between the system extension and the containing app. I have the app in a state now where it is not ready for distribution in the app store, but is ready for validation on a select number of internal test machines.
And here I must confess my almost total ignorance of many of the complexities in this realm. I've never built a macOS app before, and I only have one iOS app in the app store, and that was a much simpler use case (built with React Native, no tricky system extension stuff, and I leveraged TestFlight for testing with that app). So, I fully believe I might be making some total noob mistake here. I can say I've poured over these forums for hours trying lots of things, and I'm really stumped, and would greatly appreciate some detailed help here. 🙏
The problem
Anyway, the problem I'm having is that when I try to get the app to run on another Mac, I can't successfully get the system extension to install. I'll describe the error (as best I can understand it) directly below, and then further down give more information as to how I'm preparing the test application, since the problem might lie there.
When I try to activate the system extension from the containing app on a test machine, the activation requests succeeds far enough to prompt me to grant permission to install the extension, and when granted, it pops up the purple "(Redacted) would like to filter internet content". When I click "allow", however, the system extension shows up orange in the Network pref pane, labeled "not running." Pouring over the console logs, these two seem to be the most likely to shed light:
(neagent) Failed to find a com.apple.networkextension.filter-data extension inside of app com.acmecorp.product
and:
(nesessionmanager) com.acmecorp.product[3656]: Tearing down XPC connection due to setup error: Error Domain=NEAgentErrorDomain Code=2 "(null)"
I've inspected the contents of the app, and the system extension is properly packaged with the app. I built the SimpleFirewall app and compared the packaged app directory, and the file structure seems basically identical -- the system extension executable definitely is there. I put in a bunch of os_logs during the filter activation lifecycle process, logging out the bundle main url of the system extension, and it all seems correct, and seems to be pointing to files on the filesystem that exist. Also, I do get this encouraging log during the failing activation process:
(sysext) Realizing target path: file:///Applications/MyApp.app/Contents/Library/SystemExtensions/com.acmecorp.product.systemextension/
Which has the correct file url, and seems to be indicating that the path to the extension was indeed found. But the extension just stays stuck orange, dead, no IPC communication succeeds, and I have to manually remove it from the Network prefs pane.
I've never had the problem building and running locally on the development machine from the derived data dir from Xcode.
How I'm testing
Since the problem might lie here, I'll describe how I'm getting the app over to the target test machine (which is a physical device, not a VM). Nothing super fancy -- I basically am just going to "Product" "Archive" from within Xcode and creating an .xcarchive file. I then "show package contents", zip up the app file, and send it to the target machine, where I install it in the /Applications dir.
I did spend a long time figuring out how to add the UUID of the target machine to the provisioning profile before I could even get the container app to load. But I got that figured out and (as described above) the container app loads perfectly, it's only the system extension activation request that fails.
So... Can anyone lend me a hand? Am I going about trying to test correctly? Should I be creating the test app package some other way? Or is my (admittedly crude) method OK, and is it likely the problem lies in how I'm archiving or how the build is setup? Can anyone shed any light on the error?
Am I wrong in thinking that if it builds and runs correctly from Xcode on the dev machine, and I drag the app bundle over to another machine, it should run there too, assuming the test machine is in the provisioning profile, which it is? (Both machines are running Catalina, btw).
Thanks in advance!
Working on a macOS app, and I have the Deployment Target set to 11.0 in "General" > "Deployment Info".
However, despite that, I'm still getting compiler errors like:
'preferredColorScheme' is only available in macOS 11.0 or newer
And I'm having to add if #available(macOS 11.0, *) directives. Shouldn't Xcode realize that my deployment target is 11.0 and not force me to do the conditionals?
For a network extension that is doing content-filtering with a NEFilterDataProvider provider class, what is the recommended way of determining the user whose activity initiated the flow being examined to allow or block?
Or in other words, if I'm building an internet safety app on a multi-user device, there might be a parent (admin) user who should not have any of their network traffic blocked, while a non-admin user should be subject to blocked requests. But, because the sysex runs as root (and is active no matter who is logged in), how do I determine what the source user of the flow is?
Or am I thinking about it wrong?
Is there an approved/idiomatic way of building a content filter so that it can be intelligent enough to block traffic for certain users, but not for others?
From the raw flow I can get access to the pid, which seems like should be traceable to the owning user somehow, but I couldn't find a straightforward API to do that.
Any help would be greatly appreciated!
I'm still working on building a network content-filtering app. At this point, I've got the extension lifecycle activation issues working, have got some custom IPC communication working well between the containing app and the extension, and finally got test machine installation figured out - https://developer.apple.com/forums/thread/675164, and now I'm struggling with a different sort of issue.
I have the filtering app installed on two test machines. The installation and IPC communication works fine, and the flow analysis block/allow logic is working really well, which is the core of the app's value proposition.
The problem I'm encountering is this: after the network filter has been installed and running on a machine for 1-3 days, it begins to intermittently hang/fail when after the test machine is woken up from a sleep. To be more precise, the filter works very well, even after multiple sessions, waking/sleeping, shutdown and restart. But then, on both test machines, it seems to occasionally just completely fail. Every time this has happened, it has been after the test machine was idle, or sleeping for at least a few hours (usually overnight). Then, when the machine is woken back up, all network traffic flows fail. Some relevent (I think) facts:
when the failure happens, the network extension still is running, I can find the pid with ps, and it shows green and running in the Network portion of System preferences
I can still see the filter system extension logging things to console via os_log(), although I don't seem to be able to see in realtime the requests that are failing, but I see a lot of activity in console.log, indicating that the process itself doesn't seem to be stuck or hung up, as far as I can tell...
removing the filter extension from the network system prefs panel and re-installing/activating it from the containing app always seems to restore correct behavior
I tried attaching to the pid with lldb, which I was able to do, but I was over my head on what to do next at that point, I’m going to be be doing some research on live debugging running processes with lldb, because I have zero experience with this.
the containing app is not showing any unusual memory or cpu consumption in xcode or activity monitor, and I don't know (yet) how to check similar vital stats for the root system extension, so I can't speak to that
the network connections that fail seem to eventually just time-out, based on watching os logs in console. I can see some requests that I initiate eventually (30 seconds later or so) showiong up as errors in console, with references to timeout exceptions etc. But I don't see logging of those timed out requests in my content-filter system extension -- it's like they're hanging/timing out without ever being allowed to be handled by my extension
i do an os_log for every request that I block, but these requests that just never complete also never show up in my extensions logging.
I guess what I'm hoping is that the description of the problem I'm having triggers some idea in someone more experienced than I am in this domain. I'm struggling to know even where to start trying to debug the issue, especially since it usually takes a day or two to manifest, and then, only after sitting asleep overnight, or for several hours at a time, so it's difficult to repro and troubleshoot. Here are some of the questions I'd love any response to...
what would be your first guess as far as what to troubleshoot/test given the description above?
what would be your gut feeling of what I should do first, to investigate this and hopefully get to the bottom?
could it be a memory issue? if so, can someone point me in the right direction of how to determine this and address it?
has anyone had a similar problem with long-running sysex processes like this? Is it possible there's a known issue, or some undocumented footgun I'm running into having to do with the system extension API, and not so much my own code?
I know these api's are relatively new -- do people have production apps in the wild using the content-filter extension point? Does anyone have any experience with these processes running for a long time on host machines? Or are there not many real deployed use-cases yet out there?
the area of the app I feel the least confident in is the code around my inter-process-communication. Is it possible that some error of mine with overusing or wrongly managing the IPC communication could manifest as the problem above described?
what happens with the content-filter sysex when the machine is asleep? Is it possible that requests queue up in some way that overwhelms the system after waking a long time later?
or is there something else about the sleep/wake cycle that would point to the likely cause of the issue?
Sorry for the super long writeup, I wanted to provide as much context to help trigger any helpful ideas from whomever might read this. I truly appreciate any input on this, thanks so much.