packet-tunnel-provider-systemextension doesn't work

I am currently creating a MacOS app that uses NetworkExtension and SystemExtension without going through the Store.

Using entitlements, I manually codesign and create a pkg Installer, but when I run it I get an error message saying "No matching profile found."

Below is the log

/Applications/Runetale.app/Contents/MacOS/Runetale not valid: Error Domain=AppleMobileFileIntegrityError Code=-413 "No matching profile found" UserInfo={NSURL=file:///Applications/Runetale.app/, unsatisfiedEntitlements=<CFArray 0x71c040fa0 [0x1f7bec120]>{type = immutable, count = 3, values ​​= (
0 : <CFString 0x71c04f340 [0x1f7bec120]>{contents = "com.apple.developer.system-extension.install"}
1 : <CFString 0x71c1ccaf0 [0x1f7bec120]>{contents = "com.apple.developer.networking.networkextension"}
2 : <CFString 0x71c04fc00 [0x1f7bec120]>{contents = "com.apple.developer.team-identifier"}
)}, NSLocalizedDescription=No matching profile found}

I looked into it myself and found that if you want to install the app without going through the Store, you need to use packet-tunnel-provider-systemextension instead of packet-tunnel-provider. here

However, simply changing to packet-tunnel-provider-systemextension does not allow the build to pass.

I use a build method that changes the value of entitlements only during codesign in order to pass the build.

SYSEXT="$APP_BUNDLE/Contents/Library/SystemExtensions/com.runetale.desktop.PacketTunnel.systemextension"
if [ -d "$SYSEXT" ]; then
echo "Signing PacketTunnel system extension with entitlements..."
cp macos/PacketTunnel/PacketTunnelRelease.entitlements macos/PacketTunnel/PacketTunnelRelease-sign.entitlements
sed -i '' 's/packet-tunnel-provider/packet-tunnel-provider-systemextension/' macos/PacketTunnel/PacketTunnelRelease-sign.entitlements
codesign --force --options runtime --timestamp --entitlements "$ENTITLEMENTS_FILE" --sign "$DEV_ID_APP_CERT" "$SYSEXT"
fi
# 3. Sign the entire .app bundle (deep sign by signing the outer app after inner ones)
echo "Signing Runetale App with entitlements..."
cp macos/Runner/Release.entitlements macos/PacketTunnel/Release-sign.entitlements
sed -i '' 's/packet-tunnel-provider/packet-tunnel-provider-systemextension/' macos/PacketTunnel/Release-sign.entitlementsmacos/PacketTunnel/Release-sign.entitlements
codesign --force --options runtime --timestamp --entitlements "$APP_ENTITLEMENTS_FILE" --sign "$DEV_ID_APP_CERT" "$APP_BUNDLE"

Is this build method wrong? The next solution I'm thinking of is as follows.

  • Is there a way to write packet-tunnel-provider-systemextension directly to entitlments and pass the build? (provisioning profile?)
  • Apply to forum and get permission to use packet-tunnel-provider-systemextension

Thank you.

Answered by DTS Engineer in 835181022

To be clear, this:

Written by flekystyley in 781048021
get permission to use packet-tunnel-provider-systemextension

is unnecessary. Assuming you have the necessary privileges to sign and notarise a directly distributed app — that is, you’re a member of a paid team — then you have the necessary privileges to ship an Network Extension provider that way.

However, due to an Xcode limitation it does require some faffing around )-: I talk about that in some detail in Exporting a Developer ID Network Extension. I recommend that you read that through, apply its advice, and post back here if you get stuck.

Share and Enjoy

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

Accepted Answer

To be clear, this:

Written by flekystyley in 781048021
get permission to use packet-tunnel-provider-systemextension

is unnecessary. Assuming you have the necessary privileges to sign and notarise a directly distributed app — that is, you’re a member of a paid team — then you have the necessary privileges to ship an Network Extension provider that way.

However, due to an Xcode limitation it does require some faffing around )-: I talk about that in some detail in Exporting a Developer ID Network Extension. I recommend that you read that through, apply its advice, and post back here if you get stuck.

Share and Enjoy

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

@DTS Engineer thank you.

I'll read the article you posted and give it a try. I'll post again if I have any questions.

@DTS Engineer Thank you. I read the documentation provided by Apple engineers. I was able to create the installer successfully and launch the application.

However, when I try to connect to the VPN, I get the following error:

default 16:53:58.419606+0900 Runetale Saving configuration Runetale with existing signature (null)
error 16:53:58.420440+0900 Runetale Failed to save configuration Runetale: Error Domain=NEConfigurationErrorDomain Code=10 "permission denied" UserInfo={NSLocalizedDescription=permission denied}
error 16:53:58.420474+0900 Runetale Failed to save configuration: Error Domain=NEVPNErrorDomain Code=5 "permission denied" UserInfo={NSLocalizedDescription=permission denied}
error 16:53:58.420407+0900 nehelper Runetale Failed to obtain authorization right for 3: no authorization provided

Is there any possible reason for this?

The entitlements look like this:

App entitlements

<?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>com.apple.application-identifier</key>
<string>myteamid.com.runetale.desktop</string>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider</string>
</array>
<key>com.apple.developer.system-extension.install</key>
<true/>
<key>com.apple.developer.team-identifier</key>
<string>myteamid</string>
<key>com.apple.security.app-sandbox</key>
<false/>
<key>com.apple.security.application-groups</key>
<array>
<string>myteamid.com.runetale.desktop</string>
</array>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
</dict>
</plist>

NetworkExtension entitlements

<?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>com.apple.application-identifier</key>
<string>VH5RTVGP6D.com.runetale.desktop.PacketTunnel</string>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider-systemextension</string>
</array>
<key>com.apple.developer.team-identifier</key>
<string>VH5RTVGP6D</string>
<key>com.apple.security.app-sandbox</key>
<false/>
<key>com.apple.security.application-groups</key>
<array>
<string>VH5RTVGP6D.com.runetale.desktop</string>
</array>
</dict>
</plist>

And the automation script I'm using looks like this:

Due to character limit, I will paste it in the next comment. Sorry.

What I am careful about

  • Do not use codesign force
  • Include -systemextension in entitlements
  • Sign other frameworks, resources, etc.
  • Copy the provisionprofile created from the Developer Account

Since I am able to install and start the package installer the way it is currently made, I think the cause might be that the provisionprofile isn't set up properly. any idea?

automation package installer script I'm using looks like this:

set -euo pipefail
APP_NAME="Runetale.app"
APP_BUNDLE="build/macos/Build/Products/Release/${APP_NAME}"
DEV_ID_APP_CERT="Developer ID Application: MYTEAMID"
DEV_ID_INSTALLER_CERT="Developer ID Installer: MYTEAMID"
APP_VERSION="1.0.0"
APP_BUNDLE_ID="com.runetale.desktop"
# Apple credentials for notarization
APPLE_ID=""
TEAM_ID=""
APP_SPECIFIC_PW=""
# clean and build
rm -rf build
flutter clean
flutter build macos --release
# Ensure the app exists
if [ ! -d "$APP_BUNDLE" ]; then
echo "Error: $APP_BUNDLE not found. Make sure the app bundle is present."
exit 1
fi
echo "Starting code signing for $APP_BUNDLE..."
# copy Runetale.app
codesign -d -vvv build/macos/Build/Products/Release/Runetale.app
ditto $APP_BUNDLE $APP_NAME
# copy entitlements
codesign -d --entitlements Release.entitlements --xml Runetale.app
codesign -d --entitlements PacketTunnelRelease.entitlements --xml Runetale.app/Contents/Library/SystemExtensions/com.runetale.desktop.PacketTunnel.systemextension
plutil -convert xml1 PacketTunnelRelease.entitlements
plutil -convert xml1 Release.entitlements
cat PacketTunnelRelease.entitlements
cat Release.entitlements
## IMPORTANT: https://developer.apple.com/forums/thread/737894
# added -systemextension prefix for network extension
echo "Adding both entitlements to -systemextension..."
update_entitlement_file() {
local file="$1"
local target="packet-tunnel-provider-systemextension"
local original="packet-tunnel-provider"
echo "Checking $file..."
if grep -q "$target" "$file"; then
echo " -> $file already contains $target, skipping replacement."
elif grep -q "$original" "$file"; then
echo " -> Replacing $original with $target in $file..."
sed -i '' "s/$original/$target/g" "$file"
echo " -> Replaced $original with $target"
else
echo " -> No network extension value to update."
fi
if grep -q "<key>com.apple.security.get-task-allow</key>" "$file"; then
echo " -> Removing com.apple.security.get-task-allow block..."
sed -i '' '/<key>com.apple.security.get-task-allow<\/key>/{
N
/<true\/>/d
}' "$file"
sed -i '' '/^[[:space:]]*$/d' "$file"
echo " -> Removed com.apple.security.get-task-allow"
else
echo " -> get-task-allow not found."
fi
}
update_entitlement_file "Release.entitlements"
update_entitlement_file "PacketTunnelRelease.entitlements"
echo "Moving provisionprofile..."
# copy provisioning profile
cp Runetale_Release.provisionprofile Runetale.app/Contents/embedded.provisionprofile
cp Runetale_Desktop_PacketTunnel_Profile.provisionprofile Runetale.app/Contents/Library/SystemExtensions/com.runetale.desktop.PacketTunnel.systemextension/Contents/embedded.provisionprofile
# signing PacketTunnel and App
echo "CodeSigning Runetale App with entitlements..."
codesign -s "$DEV_ID_APP_CERT" -f --entitlements Release.entitlements --timestamp -o runtime Runetale.app/
codesign -s "$DEV_ID_APP_CERT" -f --entitlements PacketTunnelRelease.entitlements --timestamp -o runtime Runetale.app/Contents/Library/SystemExtensions/com.runetale.desktop.PacketTunnel.systemextension
echo "CodeSigning $APP_NAME with Contents, Resources and Frameworks..."
# Contents
if compgen -G "$APP_NAME/Contents/MacOS/*" > /dev/null; then
for bin in "$APP_NAME/Contents/MacOS/"*; do
if [ -f "$bin" ]; then
echo " -> Signing $bin"
codesign --force --options runtime --timestamp --sign "$DEV_ID_APP_CERT" "$bin"
fi
done
fi
# Frameworks
find "$APP_NAME/Contents/Frameworks" -type f -perm +111 -print0 | while IFS= read -r -d '' bin; do
echo "Signing: $bin"
codesign --force --timestamp --options runtime --sign "$DEV_ID_APP_CERT" "$bin"
done
# Resources
if [ -f "$APP_NAME/Contents/Resources/runetale" ]; then
echo " -> Signing Resources/runetale"
codesign --force --options runtime --timestamp --sign "$DEV_ID_APP_CERT" "$APP_NAME/Contents/Resources/runetale"
fi
if [ -f "$APP_NAME/Contents/Resources/runetaled" ]; then
echo " -> Signing Resources/runetaled"
codesign --force --options runtime --timestamp --sign "$DEV_ID_APP_CERT" "$APP_NAME/Contents/Resources/runetaled"
fi
# Runetale
codesign --force --options runtime --timestamp --sign "$DEV_ID_APP_CERT" Runetale.app/Contents/MacOS/Runetale
echo "Building signed installer package..."
# Prepare package root and build the installer .pkg
echo "Preparing pkg root for $APP_BUNDLE..."
PKG_ROOT="pkg-root"
rm -rf "$PKG_ROOT" 2>/dev/null || true
mkdir -p "$PKG_ROOT/Applications"
# Copy the app into the package root
cp -R "$APP_NAME" "$PKG_ROOT/Applications/$APP_NAME"
# Create CimponentPlist and set BundleIsRelocatable to false
pkgbuild --analyze --root $PKG_ROOT RunetaleComponent.plist
/usr/libexec/PlistBuddy -c "Set :0:BundleIsRelocatable false" RunetaleComponent.plist
PKG_NAME="Runetale-"$APP_VERSION"-Installer.pkg"
# Create package installer
pkgbuild --root $PKG_ROOT \
--component-plist RunetaleComponent.plist \
--identifier "$APP_BUNDLE_ID" \
--version "$APP_VERSION" \
--install-location "/" \
--sign "$DEV_ID_INSTALLER_CERT" \
"$PKG_NAME"
# Sign the package
INSTALLER_NAME=Installer.pkg
productsign --sign "$DEV_ID_INSTALLER_CERT" $PKG_NAME $INSTALLER_NAME
# Notarize the package
xcrun notarytool submit "$INSTALLER_NAME" \
--apple-id "$APPLE_ID" \
--team-id "$TEAM_ID" \
--password "$APP_SPECIFIC_PW" \
--wait
xcrun stapler staple "$INSTALLER_NAME"
echo "Notarized package built at: $INSTALLER_NAME"

Consecutive posts are not permitted. I noticed something strange. I noticed that a while after creating a provisionprofile used in NetworkExtension, the status was displayed as invalid.

I don't know if the provisionprofile was invalidated, but after installation, when I checked /Applications.Runetale.app, I found that entitlements were not included correctly. The cause seems to be that the priority order of my custom scripts was wrong. Thank you and Apple's engineers for your support.

packet-tunnel-provider-systemextension doesn't work
 
 
Q