Hey all,
I am working on my self updater and I am hitting an error replacing my binaries. Basically, when there is a new release my self updater checks and prompts the user to update. When the user accepts to update my applicaiton will download the .zip for the specified version and for the operating system, which is darwin in this case. Then, once the .zip has been download I use ditto to replace the existing binaries, but I am hitting the error "Operation not permitted" on darwin.
Here is my code for updating:
// Download zip of latest version (Works)
homeDir, _ := os.UserHomeDir()
downloadPath := filepath.Join(homeDir, "Downloads", "tooler.zip")
err := exec.Command("curl", "-L", "-H", "Accept: application/octet-stream", "-H", "Authorization: Bearer REMOVED_TOKEN", "-H", "X-GitHub-Api-Version: 2022-11-28", release.AssetURL, "-o", downloadPath).Run()
if err != nil {
return fmt.Errorf("binary update failed during curl: %v", err)
}
// get executable path for where we need to replace (Works)
cmdPath, err := os.Executable()
appPath := strings.TrimSuffix(cmdPath, "tooler.app/Contents/MacOS/tooler")
if err != nil {
appPath = "/Applications/"
}
// Cleanup zip after everything executes
defer func() {
err = exec.Command("rm", downloadPath).Run()
if err != nil {
// return fmt.Errorf("binary update failed during removal: %v", err)
}
}()
// Replace .app contents, but hits "operation not permitted" (Does not work)
cmd := exec.Command("ditto", "-xk", downloadPath, appPath)
var out bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &stderr
err = cmd.Run()
if err != nil {
return fmt.Errorf("binary update failed during ditto: %v \n Args: %v \n CmdPath: %v \n AppPath %v", stderr.String(), cmd.Args, cmdPath, appPath)
}
return nil
The first message before the line break is my application logging where the failure was and the rest of "ditto:" messages are the errors output by ditto.
Update failed: binary update failed during ditto:
ditto: /Applications//tooler.app/Contents/_CodeSignature/CodeResources: Operation not permitted
ditto: /Applications//tooler.app/Contents/MacOS/tooler: Operation not permitted
ditto: /Applications//tooler.app/Contents/Resources/icons.icns: Operation not permitted
ditto: /Applications//tooler.app/Contents/Info.plist: Operation not permitted
Here are my 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.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.files.downloads.read-write</key>
<true/>
</dict>
</plist>
Could this ditto error that the operation is not permitted be related to my entitlements? My .app is signed and notarized before distribution. I am able to download the zip, unzip and run the application without problems other than when I try to run the self update and it fails due to "operation not permitted".