3.7 KiB
Rsync Manager — Direct Distribution Release
Rsync Manager is designed for direct macOS distribution rather than the Mac App Store because it intentionally launches rsync/ssh and accesses user-selected arbitrary paths.
Release security baseline
- Developer ID Application signing.
- Hardened Runtime enabled.
- App Sandbox intentionally disabled for this product architecture.
- No Hardened Runtime exception entitlements.
- SSH host-key verification is never disabled.
- SSH uses BatchMode, connection timeout and keepalive limits.
- Password storage/authentication is not supported; use a private key or the macOS SSH agent.
- Advanced rsync arguments that can replace the SSH transport, run remote commands, load passwords, read/write arbitrary option/list/log/batch files or bypass controlled delete handling are rejected.
- Scheduled/file-watch
--deleterequires explicit per-job authorisation. - Run logs are sanitised and capped before storage and expire according to Settings.
PrivacyInfo.xcprivacydeclares no tracking/no collected data and the UserDefaults required-reason API.
Mandatory preflight
Before every release archive, run on the release Mac:
./Scripts/release-preflight.sh
This performs the static security policy checks, validates the privacy manifest, and performs a clean unsigned Release build with the installed macOS SDK so compiler/typecheck warnings or SDK incompatibilities are caught before signing.
Archive
In Xcode select Any Mac (Apple Silicon, Intel), choose Product > Archive, then distribute using Developer ID.
Alternatively:
xcodebuild -project RsyncManager.xcodeproj -scheme RsyncManager -configuration Release -archivePath build/RsyncManager.xcarchive archive
Choose your Developer ID Application certificate/team in Xcode signing settings before archiving.
Verify signature
codesign --verify --deep --strict --verbose=2 /path/to/RsyncManager.app
codesign -d --entitlements :- /path/to/RsyncManager.app
The Release build should show Hardened Runtime and should not contain com.apple.security.get-task-allow.
Notarise
Store notarisation credentials in a Keychain profile once:
xcrun notarytool store-credentials "RsyncManagerNotary"
Submit a signed ZIP/DMG/PKG:
ditto -c -k --keepParent /path/to/RsyncManager.app RsyncManager.zip
xcrun notarytool submit RsyncManager.zip --keychain-profile "RsyncManagerNotary" --wait
Staple and validate:
xcrun stapler staple /path/to/RsyncManager.app
xcrun stapler validate /path/to/RsyncManager.app
spctl --assess --type execute --verbose=4 /path/to/RsyncManager.app
Pre-release functional security tests
- Local source nested inside destination is rejected.
- Local destination nested inside source is rejected.
- SSH host beginning with
-is rejected. - SSH username containing spaces/control characters is rejected.
- A
.pubkey cannot be selected as the effective private key. - Advanced arguments
-e,--rsh,--rsync-path,--password-file,--files-from,--log-file,--write-batch,--remove-source-files,--delete*and-Mare rejected, and malformed quoting is rejected. - Remote destination shell metacharacters are rejected before rsync is launched.
- Scheduled/watch job using
--deletecannot run until Allow unattended delete is explicitly enabled. - SSH to a previously unknown host does not silently bypass host-key checking.
- Scheduled SSH job with unavailable authentication fails rather than prompting indefinitely.
- History expiry removes old completed runs according to Settings.
- A failed persistent SwiftData store opens Recovery Mode instead of immediately crashing.
Scripts/security-check.shpasses before every signed build.