Local Network Access Permission

We provide software that our customers deploy on their employee work computers to secure sensitive data. We have a daemon which could connect to an on-premise web-server for certain functionality. In Mac OS 15 beta we see that there is a local network access permission dialog that comes up sometimes, and it requires a permission to be provided under the Privacy & Security section of the system preferences.

We have seen the local network access permission would pop up only when both Server and Client are residing in the same private network range (eg 172.16.x.x. in our case.)

When the same server is accessed from a Sequoia machine over a VPN from external network, the local network access permission does NOT pop up. But note in this case, the Sequoia machine has an IP in the 10.x.y.z range, whereas the server is at 172.16.x.y.

We have the following questions:

  • In our setup with Macs connecting to a web-server, what conditions can trigger the local network prompt?
  • In particular, do both the client and server need to be in the same private subnet range for the prompt to be shown?
  • Is it possible that a user at home, working on a Sequoia machine, connecting over VPN to an on-prem server, would trigger this prompt?
  • If so, we would submit this is not expected, as a VPN is not really a local network.
  • Is there an MDM way of automatically providing the permission, so that the prompt is suppressed?
  • In general, is there a programmatic way of providing this permission during installation ? if yes how can we do it.
  • How do we stop users from disabling the permission incase the user has admin rights?
Answered by DTS Engineer in 799081022
during address resolution we end up getting the LNP

If you follow the links through my QSockets code, you’ll see that it calls getaddrinfo under the covers. So that’s not the critical factor.

You’re passing in a hints value, but you’ve set that up in a very vanilla fashion so I don’t see how it’d be relevant.

At this point I’m out of ideas. Clearly this is related to the environment in which your code is running, and that’s hard for me to investigate here on the forums. My recommendation is that you file a bug about this. Make sure to include a sysdiagnose log taken shortly after you see the issue.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

How do we stop users from disabling the permission incase the user has admin rights?

Usually, any admin user should be able to change these kind of settings, so if you want an user to be unable to do that, they shouldn't have admin rights. Perhaps you can do something with the MDM APIs for that.

Regarding your other questions, I'm unsure, but:

In particular, do both the client and server need to be in the same private subnet range for the prompt to be shown?

My guess is they shouldn't be on the same private network range (not necessarily subnet), but I haven't tested that.

a VPN is not really a local network

Perhaps the machine should still see it as a local network, especially if your machine is residing on a private network range through the VPN.

Regarding the circumstances under which LNP applies — that is, the definition of a local network — that’s something that macOS inherits from iOS. I have an entry in the Local Network Privacy FAQ that describes it.

We have a daemon …

Is this an actual daemon? That is, one that’s started as root by launchd? Or are you using “dameon” to be “some code that runs in the background”?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi,

We have also recently hit a problem where our application was unable to connect to a local network TCP socket on a remote host and was hitting EHOSTUNREACH. This appeared to be the permission blocking it as we were running the application under XCODE (whilst a previous version was installed in APPLICATIONS).

Is there a concept of adding this permission to the application under XCODE and/or programatically querying the permission and requesting from user?

Thanks

Chris

I’m sorry, but I need more context here. What platform is this? And what version of that platform?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi @DTS Engineer (Quinn)

I'm a colleague of @apodila. Like he mentioned in a subsequent comment, yes, it is a regular daemon, launched by launchd. Curious why this would matter though?

And thanks for the FAQ: Going by the below from the What is a local network FAQ (bolding mine), can we assume that a user connecting over VPN to an on-prem server, would NOT see the local network prompt:

A local network is an IP network associated with a broadcast-capable network interface. These interfaces include Wi-Fi and Ethernet (1), but not WWAN or VPN. Any address on a local network is considered to be a local network address.

Finally, is there a way to set this local network permission using MDM or programatically?

Thanks

-Vivek

Curious why this would matter though?

A big difference between macOS and iOS is that, on iOS, all third-party programs are apps or app extensions, which mean they run in a user context. Thus, all privacy settings are effectively per user.

macOS supports daemons, which run outside of the user context, so the difference between per-user and system-wide privacy settings is important.

My understanding, based on my conversations with the networking team about 6 months ago, is that:

  • The LNP setting is per user.

  • The system does not apply LNP to code running as root.

So your daemon should be fine. However, I haven’t had a chance to personally verify that on the macOS 15 beta seeds.

Finally, is there a way to set this local network permission using MDM or programatically?

Not that I’ve seen. Many privacy settings can be configured via the com.apple.TCC.configuration-profile-policy payload, but that doesn’t list any options for LNP.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

My understanding, based on my conversations with the networking team about 6 months ago, is that:

  • The LNP setting is per user.

  • The system does not apply LNP to code running as root.

@DTS Engineer Quinn “The Eskimo!” @ Developer Technical Support @ Apple

what we have observed is that, we do see the pop up for the LNP settings. Which is some thing which would like to solve and have not found any thing the apple documentation.

what we have observed is that, we do see the pop up for the LNP settings.

I’m presuming that the above sentence ends with “for our daemon”. Lemme know if that presumption is wrong.

If it’s right, the key thing to consider is how your daemon is launched. Please confirm:

  • That it’s a launchd daemon, not an agent. That is, it starts based on a configuration file in /Library/LaunchDaemons [1].

  • Also, that it’s not using UserName to run as a role account.

  • And that you don’t launch it any other way, for example, via sudo, even during testing or upgrades.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Or it’s registered with SMAppService.daemon(plistName:).

We are hitting this as well, when our CI agent running as a Launch Agent on macOS 15 VMs tries to connect to the CI scheduler on the same network.

I haven't tested it yet, but I assume that using launchctrl to load/start the agent as part of manual provisioning of the macOS 15 CI VM will trigger the permission dialog (as long as the VM is running in the same network conditions as it will be when part of the CI pool and handling jobs), and that this permission will persist for later.

Ideally there would be a programatic way to provision this.

@DTS Engineer Answering your question : That it’s a launchd daemon, not an agent. That is, it starts based on a configuration file in /Library/LaunchDaemons

Yes its a launchd daemon and not an agent Its started based on the configuration file based in /Library/LaunchDaemons folder

Also, that it’s not using UserName to run as a role account.

We are not using any UserName to run as role account

And that you don’t launch it any other way, for example, via sudo, even during testing or upgrades.

We are not launch in any other way , we are also not using sudo during debug testing or upgrades.

Using launchctl load to load the launch agent successfully brings up the permission dialog.

And accepting the permission is reflected in the Settings app for the executable.

However there doesn't seem to be any change recorded in the global or user-specific TCC database (TCC.db).

And the CI agent complains about not having a route to the host it's trying to reach.

With Console.app reporting:

runningboardd   _executablePath = /Users/qt/ci-agent
runningboardd   Resolved pid 811 to [osservice<org.qt.io.ci-agent(501)>:811]
runningboardd   [osservice<org.qt.io.ci-agent(501)>:811] is not RunningBoard jetsam managed.
runningboardd   [osservice<org.qt.io.ci-agent(501)>:811] This process will not be managed.
runningboardd   [osservice<com.apple.nehelper>:179] query resolved to [osservice<org.qt.io.ci-agent(501)>:811]
nehelper    No team ID found for (bundleID: a.out, name: ci-agent)
nehelper    Got message for: ci-agent (TEAMID.a.out PID 811)
nehelper    Path /Users/qt/ci-agent for PID 811 matches existing rule
nehelper    Local network allowed by preference for ci-agent (a.out)
nehelper    Local network allowed by preference for ci-agent (a.out), but received prompt. Clearing cached UUIDs and restarting session.
nehelper    +[NEProcessInfo copyUUIDsForExecutable:]_block_invoke: failed to get UUIDs for /Users/qt/ci-agent

I've tried to reproduce this using the minimal sample from the Triggering the Local Network Privacy Alert, but launctrl load ~/Library/LaunchAgents/foo.plist doesn't bring up any privacy dialog.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple/DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>Label</key>
        <string>org.foo.test</string>
        <key>ProgramArguments</key>
        <array>
            <string>/Users/admin/foo</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>KeepAlive</key>
        <false/>
    </dict>
</plist>

foo.m: https://gist.github.com/torarnv/7db4278860d06dce49179322031f8cea

@torarnv, A launchd agent runs in a user context and thus should prompt for and get the Local Network privilege. I suspect that you’re seeing weird problems because your agent has no bundle ID. I recommend that you repeat your test but with your agent wrapped in an app-like bundle. See Signing a daemon with a restricted entitlement for instructions on how to set that up.

IMPORTANT You can ignore the entitlement and provisioning profile aspects of those instructions. Those factors shouldn’t be relevant in this case.

Regardless of the results, I’d appreciate you starting a new thread about this. This thread is about daemons, which shouldn’t need the Local Network privilege. Your issue is about an agent, and those do need it.

Use the same topics and tags as this thread, so I see your new thread go by.


Yes its a launchd daemon and not an agent Its started based on the configuration file based in /Library/LaunchDaemons folder

We are not using any UserName to run as role account

We are not launch in any other way , we are also not using sudo during debug testing or upgrades.

Hmmm, that makes your results hard to explain.

To be clear, your daemon is triggering this alert when it makes an outgoing network connection, right? You mentioned that this is to a web server. Does that mean you’re using the URLSession API? Or something more low-level?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks Quinn! Sorry for hijacking the thread 😬

@DTS Engineer

Yes its triggering the alert when the daemon is communicating to the web serverWe use low level api for communicating to the server.

These are the calls which are made in the daemon

+       ! :         18550 getaddrinfo  (in libsystem_info.dylib) + 168  [0x19c7cbae8]
+       ! :           18550 si_addrinfo  (in libsystem_info.dylib) + 1368  [0x19c7cc0e8]
+       ! :             18550 search_addrinfo  (in libsystem_info.dylib) + 176  [0x19c7d30bc]
+       ! :               18550 mdns_addrinfo  (in libsystem_info.dylib) + 404  [0x19c7d32a0]
+       ! :                 18550 _mdns_search_ex  (in libsystem_info.dylib) + 1076  [0x19c7d0a2c]
+       ! :                   18550 kevent  (in libsystem_kernel.dylib) + 8  [0x19c750edc]
Local Network Access Permission
 
 
Q