com.apple.vm.networking for helper binary

Hi everyone & DTS engineers,

I am developing a macOS application that uses Apple's Virtualization framework and vmnet APIs.

In my main application bundle, I have requested and received approval for the restricted entitlement com.apple.vm.networking. The main app works as expected with bridging/vmnet features.

Now, I have embedded a command-line helper binary inside the app bundle (Contents/MacOS/). The helper is configured as follows:

  • Set up with com.apple.security.app-sandbox = true
  • Inherits App Sandbox rules (com.apple.security.inherit = true)
  • Signed with com.apple.vm.networking = true in its entitlements file.

However, when launching or invoking networking features from this helper binary, it fails to execute the expected vmnet functions / gets blocked at runtime.

My questions for DTS / Apple Engineers:

  1. Since com.apple.vm.networking is a restricted entitlement tied to a specific App ID / Provisioning Profile, does an embedded CLI helper tool with its own Bundle ID need to be explicitly registered and granted this entitlement separately in the Developer Portal?
  2. If the helper uses com.apple.security.inherit, does AMFI still strictly evaluate the helper's own provisioning profile signature against com.apple.vm.networking independently of the main app bundle?
  3. What is the recommended architectural pattern for vmnet access when using helper tools—should network creation stay strictly in the main app process and communicate via XPC, or should the helper tool be granted its own matching profile and entitlement?

Thanks in advance for any insight!

Answered by DTS Engineer in 909194022

So this is a potential minefield [1], but I think you can make it work. The trick is to put the tool in an app-like wrapper [2], with its own bundle ID, and hence its own App ID, and then enable the VM Networking capability on that App ID. The tool then claims the required entitlements, with com.apple.vm.networking being a restricted entitlement that’s authorised by the tool’s provisioning profile.

I tried this in my office today (on macOS 26.7.1) and it seems to work a treat. Consider this:

% codesign -d --entitlements - EntitlementInheritanceExplorer.app/Contents/MacOS/EntitlementInheritanceChild.app 
…
[Dict]
    [Key] com.apple.application-identifier
    [Value]
        [String] SKMME9E2Y8.com.example.apple-samplecode.Child
    [Key] com.apple.developer.team-identifier
    [Value]
        [String] SKMME9E2Y8
    [Key] com.apple.security.app-sandbox
    [Value]
        [Bool] true
    [Key] com.apple.security.get-task-allow
    [Value]
        [Bool] true
    [Key] com.apple.security.inherit
    [Value]
        [Bool] true
    [Key] com.apple.vm.networking
    [Value]
        [Bool] true
% security cms -D -i EntitlementInheritanceExplorer.app/Contents/MacOS/EntitlementInheritanceChild.app/Contents/embedded.provisionprofile | plutil -p -
{
  …
  "Entitlements" => {
    "com.apple.application-identifier" => "SKMME9E2Y8.com.example.apple-samplecode.Child"
    "com.apple.developer.team-identifier" => "SKMME9E2Y8"
    "com.apple.vm.networking" => true
    "keychain-access-groups" => [
      0 => "SKMME9E2Y8.*"
    ]
  }
  …
}

When I have the parent spawn the child, it logs confirmation that it ran with the right entitlements and with the entitlements-validated flag set (the full log entries are at the end of this reply).

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

[1] Due to the combination of sandbox inheritance (see Resolving App Sandbox Inheritance Problems) and the entitlements-validated flag (see App Groups: macOS vs iOS: Working Towards Harmony).

[2] See Signing a daemon with a restricted entitlement.


…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: first light

…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: is validated: true

…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: entitlement: com.apple.application-identifier = SKMME9E2Y8.com.example.apple-samplecode.Child

…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: entitlement: com.apple.developer.team-identifier = SKMME9E2Y8

…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: entitlement: com.apple.security.app-sandbox = 1

…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: entitlement: com.apple.security.get-task-allow = 1

…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: entitlement: com.apple.security.inherit = 1

…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: entitlement: com.apple.vm.networking = 1

So this is a potential minefield [1], but I think you can make it work. The trick is to put the tool in an app-like wrapper [2], with its own bundle ID, and hence its own App ID, and then enable the VM Networking capability on that App ID. The tool then claims the required entitlements, with com.apple.vm.networking being a restricted entitlement that’s authorised by the tool’s provisioning profile.

I tried this in my office today (on macOS 26.7.1) and it seems to work a treat. Consider this:

% codesign -d --entitlements - EntitlementInheritanceExplorer.app/Contents/MacOS/EntitlementInheritanceChild.app 
…
[Dict]
    [Key] com.apple.application-identifier
    [Value]
        [String] SKMME9E2Y8.com.example.apple-samplecode.Child
    [Key] com.apple.developer.team-identifier
    [Value]
        [String] SKMME9E2Y8
    [Key] com.apple.security.app-sandbox
    [Value]
        [Bool] true
    [Key] com.apple.security.get-task-allow
    [Value]
        [Bool] true
    [Key] com.apple.security.inherit
    [Value]
        [Bool] true
    [Key] com.apple.vm.networking
    [Value]
        [Bool] true
% security cms -D -i EntitlementInheritanceExplorer.app/Contents/MacOS/EntitlementInheritanceChild.app/Contents/embedded.provisionprofile | plutil -p -
{
  …
  "Entitlements" => {
    "com.apple.application-identifier" => "SKMME9E2Y8.com.example.apple-samplecode.Child"
    "com.apple.developer.team-identifier" => "SKMME9E2Y8"
    "com.apple.vm.networking" => true
    "keychain-access-groups" => [
      0 => "SKMME9E2Y8.*"
    ]
  }
  …
}

When I have the parent spawn the child, it logs confirmation that it ran with the right entitlements and with the entitlements-validated flag set (the full log entries are at the end of this reply).

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

[1] Due to the combination of sandbox inheritance (see Resolving App Sandbox Inheritance Problems) and the entitlements-validated flag (see App Groups: macOS vs iOS: Working Towards Harmony).

[2] See Signing a daemon with a restricted entitlement.


…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: first light

…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: is validated: true

…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: entitlement: com.apple.application-identifier = SKMME9E2Y8.com.example.apple-samplecode.Child

…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: entitlement: com.apple.developer.team-identifier = SKMME9E2Y8

…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: entitlement: com.apple.security.app-sandbox = 1

…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: entitlement: com.apple.security.get-task-allow = 1

…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: entitlement: com.apple.security.inherit = 1

…
process: EntitlementInheritanceChild
subsystem: com.example.apple-samplecode.EntitlementInheritanceExplorer
category: child
message: entitlement: com.apple.vm.networking = 1

I got this working as you said i need to create a app wrapper and from dts support i came to know that the restricted entitlement is approved for team id and not for bundle id. so the the helper worked perfectly after wrapping it in app.

Thank You

Now i have one more problme i need to add microphone cabaility to helper app when i enable the audio input the helper application does not start it exit with code 5. How can i add audio input to the helper app.

thanks in advance

You mean com.apple.security.device.microphone, right?

Because there’s the confusingly similar com.apple.security.device.audio-input |-:

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

I mean both i tried enabling it in xcode when i enable microphone the other enabled automatically. when i run the helper binary with this entitlement it crashes with exit code 5. Do we really need this in helper binary. What the helper binary does in the sense it runs virtual machine in a separate process using hypervisor framework they are sandboxed and inherit secuirty and i have hypervisor and vm.networking in the entitlements. the vm records audio from mac mic. so the helper needs microphone permission technically speaking. but however withtout the microphone entitilements the recoding works. is there something i am missing to understand.

I mean both

OK.

I think you’re being bitten by the com.apple.security.inherit oddity that I discuss here.

but however withtout the microphone entitilements the recoding works.

Do you have these entitlements on the app itself, that is, the parent that spawned the helper child?

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

Do you have these entitlements on the app itself, that is, the parent that spawned the helper child?

Yes I have it in the parent. i have two way of running the vms. one using virtualization framework for macos and linux vms ie in process and helper worker binary for running windows vm with hypervisor framework.

com.apple.vm.networking for helper binary
 
 
Q