Skip to content

Conversation

@i2h3
Copy link
Collaborator

@i2h3 i2h3 commented Nov 5, 2025

Originally, I set out to avoid the appearance of a system prompt of our app wanting to access data from other apps when it actually just tried to create a local socket file in its own group container for interprocess communication.

⚠️ Key Changes

  • Our app and its contained extensions now use an unprovisioned app group which complies with the conventional naming scheme. Instead of reusing the main bundle identifier as an app group identifier, the used app group identifier now has a prefix based on the development team. This is the option to have "unprovisioned" group containers at the cost of restricting compatibility to macOS and not being abled to use entitlements like keychain sharing. It simplifies the identity management and signing a lot in which we are also stuck with legacy hurdles impossible to overcome smoothly. See "Accessing app group containers in your existing macOS app" by Apple for further information.
  • The build settings of the NextcloudIntegration.xcodeproj were updated to use a new common base identifier based on Nextcloud instead of ownCloud. Also, redundant build settings around signing were removed.
  • Code signing was disabled for project-wide in the Xcode project. The main app is not build by Xcode but its extensions are. The signing of the whole app bundle including its extensions now is done consistently through Mac Crafter in a later step in the build process. This is also necessary to keep the build job in the CI running without a development certificate.
  • Added app sandbox entitlement to the main app. The other relevant targets already had this as it is imposed on extensions as a requirement by the platform. This is an important step for the long term goal of enabling Mac App Store distribution. ✨ See "App Sandbox" by Apple for further information.
  • Added network client entitlement to the main app for obvious reasons.
  • Added entitlement for read-write access to files selected by users. This is required for features like the debug archive export which enables saving files outside the sandbox.
  • The socket files created for interprocess communication now are located within the sandboxed containers for the app. The previous location in the root of the container were still breaking the sandbox.
  • A container migration manifest was added which lets the macOS container service automatically migrate application data from legacy locations into the sandbox container specifically set up for it. See "Migrating your app’s files to its App Sandbox container" by Apple for further information.
  • Added Objective-C++ bridging code for security scoped URL handling because Qt does not take care of it. This is required to access files outside of the sandbox, in example when writing a ZIP archive during the debug archive export.
  • The file provider extension must place its logs and databases inside the new group container (group. prefix) so the main app can access it for creation of a debug archive. This renders the shared legacy account database migration code obsolete because it could not be accessed anyway.
  • The synchronization folder setup was changed to force the user to select the local target through a system dialog. This is necessary for the system to grant access to the location outside the sandbox.
  • File provider configuration was consolidated. File provider settings now are integrated consistently in the main configuration file. They are no more odd mapping groups between accounts and domains but simple properties. NSUserDefaults no longer is used for storing file provider enabled accounts in other facilities.
  • Removed macOS 11 code switches because they are obsolete because we only support macOS 12 anyway.

😵 Caveats

Breaking File Provider Change

This is a breaking change for our file provider extension. Currently, I do not see a way to enable the app sandbox without setting up file provider domains for accounts from scratch. The compliance with the app sandbox requires to use a proper group container identifier and app sandbox migration manifests only support containers (not group containers), to my knowledge.

Should a 4.1 build look for the file provider extension data, it will look in the new group container initially and not find anything. This is equal to a complete reset.

UNIX Sockets

Long identifiers may break the UNIX socket-based IPC. The app sandbox makes long path prefixes inevitable. In example:

/Users/<redacted>/Library/Group Containers/NKUJUXUJ3B.com.nextcloud.desktopclient/Library/Application Support/.fileprovidersocket

It is about 122 characters long and there is a problem with that:

The issue is that the socket path is too long for QLocalServer on macOS. Unix domain sockets have a maximum path length of typically 104 characters, and your path exceeds this limit.

Apple XNU kernel source code for reference.

The solution for now is to keep it as short as possible but this may break with branded identifiers which are significantly longer than this reference case.

/Users/<redacted>/Library/Group Containers/NKUJUXUJ3B.com.nextcloud.desktopclient/fps

⚡️ Impact

This is not a simple bug fix but foundational changes to how security is implemented by our client on macOS. It requires extensive testing and cannot be delivered or ported back as a patch release. This is not just flipping a switch in some settings. The debug archive creation feature is an example how the technical debt of a missing app sandbox requires code refactoring.

🔗 Dependencies

🔬 Testing

When upgrading from a previous release:

  • The accounts having their file provider domain enabled should still have it enabled
  • The file provider domain should be set up from scratch for those accounts, though
  • The configuration file no longer contains mappings between accounts and file provider domain identifiers but has individual properties on the namespaced account configurations
  • The UserDefaults are no longer used by the file provider extension
  • The configuration file contains a fileProviderDomainsAppSandboxMigrationCompleted=true
  • Classic synchronization still works with the preexisting synchronization folders
  • Classic synchronization works with newly set up synchronization folders

@i2h3 i2h3 added this to the 4.1.0 milestone Nov 5, 2025
@i2h3 i2h3 requested a review from Copilot November 5, 2025 10:14
@i2h3 i2h3 self-assigned this Nov 5, 2025
@github-project-automation github-project-automation bot moved this to 🧭 Planning evaluation (don't pick) in 💻 Desktop Clients team Nov 5, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR migrates from using team-identifier-prefixed app groups to the standard group. prefix for macOS app group identifiers, and updates code signing configuration to use automatic signing with a specific development team.

  • Changed app group identifier format from $(TEAM_ID)$(BUNDLE_ID) to group.$(BUNDLE_ID)
  • Updated socket paths to use Library/Application Support/ subdirectories
  • Switched from manual to automatic code signing with NKUJUXUJ3B development team
  • Updated bundle identifiers from com.owncloud.* to com.nextcloud.*

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/gui/socketapi/socketapi_mac.mm Updated socket path to use group prefix and Application Support directory
src/gui/macOS/fileproviderutils_mac.mm Added whitespace formatting improvements
src/gui/macOS/fileprovidersocketserver_mac.mm Updated file provider socket path to use group prefix and Application Support directory
shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj Changed code signing from manual to automatic, updated development team ID, and changed bundle IDs from owncloud to nextcloud
shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSyncExt.entitlements Updated app group identifier to use group prefix
shell_integration/MacOSX/NextcloudIntegration/FinderSyncExt/FinderSync.m Updated socket path to use Application Support subdirectory
shell_integration/MacOSX/NextcloudIntegration/FileProviderUIExt/FileProviderUIExt.entitlements Updated app group identifier to use group prefix
shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Info.plist Updated NCFPKAppGroupIdentifier to use group prefix
shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExt.entitlements Updated app group identifier to use group prefix
cmake/modules/MacOSXBundleInfo.plist.in Updated NCFPKAppGroupIdentifier template to use group prefix
admin/osx/macosx.entitlements.cmake Updated app group identifier template to use group prefix and added sandbox entitlements

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@i2h3 i2h3 force-pushed the i2h3/proper-macos-sandboxing branch from 38661b3 to a7f4af5 Compare November 5, 2025 12:51
@i2h3 i2h3 moved this from 🧭 Planning evaluation (don't pick) to 🏗️ In progress in 💻 Desktop Clients team Nov 5, 2025
@i2h3 i2h3 marked this pull request as ready for review November 5, 2025 13:47
@i2h3 i2h3 force-pushed the i2h3/proper-macos-sandboxing branch from 636553d to e37dada Compare November 5, 2025 14:03
@i2h3 i2h3 marked this pull request as draft November 5, 2025 14:13
@i2h3
Copy link
Collaborator Author

i2h3 commented Nov 5, 2025

I need to fix how the build settings are passed through now before it is ready for review.

@i2h3 i2h3 force-pushed the i2h3/proper-macos-sandboxing branch 2 times, most recently from 38055c2 to a78b990 Compare November 10, 2025 10:12
i2h3 added a commit to nextcloud/nextcloudfileproviderkit that referenced this pull request Nov 10, 2025
- These changes are related to making the main app bundle of the macOS build adopt the app sandbox entitlement which imposes certain restrictions on its file system access (nextcloud/desktop#9023).
- Logs are now written to the app group container because they are not accessible by the main app for creating debug archives otherwise.
- Databases are now written to the app group container because they are not accessible by the main app for creating debug archives otherwise.
- Removed legacy database migration code because it cannot work with the new app group identifier of the now sandboxed app anymore.
- Simplified database location assembly.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
i2h3 added a commit to nextcloud/nextcloudfileproviderkit that referenced this pull request Nov 12, 2025
- These changes are related to making the main app bundle of the macOS build adopt the app sandbox entitlement which imposes certain restrictions on its file system access (nextcloud/desktop#9023).
- Logs are now written to the app group container because they are not accessible by the main app for creating debug archives otherwise.
- Databases are now written to the app group container because they are not accessible by the main app for creating debug archives otherwise.
- Removed legacy database migration code because it cannot work with the new app group identifier of the now sandboxed app anymore.
- Simplified database location assembly.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
@i2h3 i2h3 force-pushed the i2h3/proper-macos-sandboxing branch from 76982cb to 1534ff2 Compare November 12, 2025 09:58
i2h3 added a commit to nextcloud/nextcloudfileproviderkit that referenced this pull request Dec 2, 2025
- These changes are related to making the main app bundle of the macOS build adopt the app sandbox entitlement which imposes certain restrictions on its file system access (nextcloud/desktop#9023).
- Logs are now written to the app group container because they are not accessible by the main app for creating debug archives otherwise.
- Databases are now written to the app group container because they are not accessible by the main app for creating debug archives otherwise.
- Removed legacy database migration code because it cannot work with the new app group identifier of the now sandboxed app anymore.
- Simplified database location assembly.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
i2h3 added a commit to nextcloud/nextcloudfileproviderkit that referenced this pull request Dec 2, 2025
- These changes are related to making the main app bundle of the macOS build adopt the app sandbox entitlement which imposes certain restrictions on its file system access (nextcloud/desktop#9023).
- Logs are now written to the app group container because they are not accessible by the main app for creating debug archives otherwise.
- Databases are now written to the app group container because they are not accessible by the main app for creating debug archives otherwise.
- Removed legacy database migration code because it cannot work with the new app group identifier of the now sandboxed app anymore.
- Simplified database location assembly.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
i2h3 added a commit to nextcloud/nextcloudfileproviderkit that referenced this pull request Dec 2, 2025
- These changes are related to making the main app bundle of the macOS build adopt the app sandbox entitlement which imposes certain restrictions on its file system access (nextcloud/desktop#9023).
- Logs are now written to the app group container because they are not accessible by the main app for creating debug archives otherwise.
- Databases are now written to the app group container because they are not accessible by the main app for creating debug archives otherwise.
- Removed legacy database migration code because it cannot work with the new app group identifier of the now sandboxed app anymore.
- Simplified database location assembly.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
@i2h3 i2h3 force-pushed the i2h3/proper-macos-sandboxing branch from 1534ff2 to 67ab6f5 Compare December 2, 2025 09:15
@i2h3 i2h3 force-pushed the i2h3/proper-macos-sandboxing branch from 67ab6f5 to 4581341 Compare December 4, 2025 09:45
i2h3 added 23 commits December 18, 2025 10:29
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
…ion.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
To have more predictable flow, the removal methods wait for completion of their dispatched and asynchronous methods first.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
…upported macOS 11.

We require at least macOS 12 anyway.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
…eproviderdomainmanager.mm

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
…Domain synchronous.

To avoid race conditions.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
To avoid race conditions.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
- The app sandbox migration of file provider domains now wipes the mapping groups from the configuration file.
- The Account type now has "fileProviderDomainIdentifier" property and appropriate getters and setters in case the file provider module is built.
- The AccountManager is extended accordingly to handle the new "fileProviderDomainIdentifier" property on Account.
- The AccountManager now also provides a lookup method to fetch the account belonging to a file provider domain identifier. This was previously implemented by the FileProviderDomainManager but not within its scope of responsibility.
- The FileProviderSettingsController now provides a method to migrate the enabled accounts from UserDefaults to the configuration file.
- The FileProviderDomainManager contained mapping methods between account identifiers and file provider domain identifiers and UUIDs which were obsolete and removed.
- Refactored FileProviderDomainManager to separate individual steps into smaller methods like the synchronous wrappers for NSFileProviderManager. This simplifies the code a lot by avoiding nested completion handler code.
- Removed FileProviderDomainManager::accountStateFromFileProviderDomainIdentifier() which is redundant with the previously added AccountManager lookup method.
- Removed dead code here and there.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
…ain identifier instead of account identifier.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
…n settings.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
…st Xcode.

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
- Moved some logic (most notably removeOrphanedDomains and restoreMissingDomains) from FileProviderDomainManager into the more appropriate FileProviderSettingsController
- Dissolved updateFileProviderDomains()
- Removed domainSetupComplete signal
- Introduced migrateToAppSandbox() implementation FileProviderSettingsController
- Improved logging messages

Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
Signed-off-by: Iva Horn <iva.horn@nextcloud.com>
@i2h3 i2h3 force-pushed the i2h3/proper-macos-sandboxing branch from ba98f26 to 6dcc1fd Compare December 18, 2025 09:30
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
1 Security Hotspot
0.0% Coverage on New Code (required ≥ 80%)
240 New Code Smells (required ≤ 0)
D Maintainability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@i2h3 i2h3 merged commit d36bacb into master Dec 18, 2025
21 of 23 checks passed
@i2h3 i2h3 deleted the i2h3/proper-macos-sandboxing branch December 18, 2025 11:31
@github-project-automation github-project-automation bot moved this from 🏗️ In progress to ☑️ Done in 💻 Desktop Clients team Dec 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: ☑️ Done

Development

Successfully merging this pull request may close these issues.

3 participants