Major update for stability
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
# Rsync Manager — Security / Release Audit
|
||||
|
||||
This project targets direct macOS distribution using Developer ID signing and Apple notarisation. App Sandbox is intentionally disabled because the product launches `rsync`/SSH and operates on arbitrary user-configured filesystem paths.
|
||||
|
||||
## Security controls present
|
||||
|
||||
- Hardened Runtime enabled for Debug and Release target configurations.
|
||||
- No shell (`/bin/sh -c`) command construction; `Process` uses an absolute executable path and argument array.
|
||||
- SSH host-key checking is not disabled.
|
||||
- Automated SSH uses BatchMode, timeout and keepalive limits.
|
||||
- SSH password authentication/storage is not supported; legacy stored password data is deleted.
|
||||
- Remote host, username, port, key path and remote destination are validated.
|
||||
- Remote paths reject shell metacharacters before rsync can invoke the remote shell.
|
||||
- Advanced arguments reject transport replacement, remote-command, credential, arbitrary list/log/batch path and destructive overrides.
|
||||
- Malformed Advanced argument quoting/trailing escapes are rejected.
|
||||
- `--` terminates rsync option parsing before source/destination operands.
|
||||
- Local source/destination overlap is rejected.
|
||||
- File-watch and exclusion values reject control characters.
|
||||
- Scheduled/watch delete requires explicit per-job authorisation.
|
||||
- Run logs are ANSI-cleaned, likely credentials redacted and size-capped before persistence.
|
||||
- Run history has bounded retention.
|
||||
- Privacy manifest declares no tracking/no collected data and the app-specific UserDefaults required reason.
|
||||
- Launch at login uses `SMAppService` and remains user-controlled.
|
||||
- No analytics/telemetry or application HTTP client code is present.
|
||||
|
||||
## Required release verification on a Mac
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
./Scripts/release-preflight.sh
|
||||
```
|
||||
|
||||
Then archive with Developer ID, submit with Apple `notarytool` (or Xcode Organizer), staple the ticket and run the signature/Gatekeeper checks in `Docs/RELEASE.md`.
|
||||
|
||||
A Linux source audit cannot substitute for Xcode's macOS SDK typecheck, code signing, notarisation or Gatekeeper assessment.
|
||||
@@ -0,0 +1,87 @@
|
||||
# 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 `--delete` requires explicit per-job authorisation.
|
||||
- Run logs are sanitised and capped before storage and expire according to Settings.
|
||||
- `PrivacyInfo.xcprivacy` declares no tracking/no collected data and the UserDefaults required-reason API.
|
||||
|
||||
## Mandatory preflight
|
||||
|
||||
Before every release archive, run on the release Mac:
|
||||
|
||||
```bash
|
||||
./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:
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
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:
|
||||
|
||||
```bash
|
||||
xcrun notarytool store-credentials "RsyncManagerNotary"
|
||||
```
|
||||
|
||||
Submit a signed ZIP/DMG/PKG:
|
||||
|
||||
```bash
|
||||
ditto -c -k --keepParent /path/to/RsyncManager.app RsyncManager.zip
|
||||
xcrun notarytool submit RsyncManager.zip --keychain-profile "RsyncManagerNotary" --wait
|
||||
```
|
||||
|
||||
Staple and validate:
|
||||
|
||||
```bash
|
||||
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
|
||||
|
||||
1. Local source nested inside destination is rejected.
|
||||
2. Local destination nested inside source is rejected.
|
||||
3. SSH host beginning with `-` is rejected.
|
||||
4. SSH username containing spaces/control characters is rejected.
|
||||
5. A `.pub` key cannot be selected as the effective private key.
|
||||
6. Advanced arguments `-e`, `--rsh`, `--rsync-path`, `--password-file`, `--files-from`, `--log-file`, `--write-batch`, `--remove-source-files`, `--delete*` and `-M` are rejected, and malformed quoting is rejected.
|
||||
7. Remote destination shell metacharacters are rejected before rsync is launched.
|
||||
8. Scheduled/watch job using `--delete` cannot run until **Allow unattended delete** is explicitly enabled.
|
||||
9. SSH to a previously unknown host does not silently bypass host-key checking.
|
||||
10. Scheduled SSH job with unavailable authentication fails rather than prompting indefinitely.
|
||||
11. History expiry removes old completed runs according to Settings.
|
||||
12. A failed persistent SwiftData store opens Recovery Mode instead of immediately crashing.
|
||||
13. `Scripts/security-check.sh` passes before every signed build.
|
||||
Reference in New Issue
Block a user