CCullapse
Features Privacy CLI AI Support Download
Trust

Security and architecture

A technical companion to the privacy policy. This page describes how Cullapse is built, what it talks to, and where the safety rails are. Cullapse is provided as is by one developer; see §14 for what that means for security reports.

Updated 2026-05-13·Application version 1.0

Contents

  1. Shape of the system
  2. IMAP behavior
  3. Credential storage
  4. OAuth status
  5. Local cache
  6. iCloud sync paths
  7. AI request boundary
  8. Destructive-action safety
  9. Automation safeguards
  10. Network egress
  11. Logging
  12. Sandbox and entitlements
  13. CLI signing
  14. Responsible disclosure

1. Shape of the system

Cullapse is a native SwiftUI application with three runtime surfaces: the macOS app, the iOS app, and a bundled command-line tool. There are no Cullapse-operated servers in the picture. The application makes outbound connections only to:

  • your IMAP mail servers, over TLS, using credentials you supply;
  • Apple system services (Foundation Models, iCloud Keychain, iCloud KV-Store, StoreKit) when you opt in;
  • a third-party AI provider's API, if and only if you configure one and supply a key.

There is no inbound listener. There is no analytics endpoint. There is no crash-reporter operated by Cullapse — crashes are routed through Apple's system reporter, which you control.

2. IMAP behavior

Cullapse speaks IMAP4rev1 (RFC 3501) over TLS, with selective use of the IDLE, MOVE, CONDSTORE, and LIST-EXTENDED extensions where the server advertises them. The client is built on a vendored SwiftMail implementation. The relevant guarantees:

  • Only FETCH requests for ENVELOPE, FLAGS, BODYSTRUCTURE, RFC822.SIZE, UID, and the named header set (List-Unsubscribe, List-Id, Message-ID) are issued.
  • No BODY[], no BODY[1], no RFC822 fetch is ever issued. The client has no code path that would.
  • External URLs found in headers are not dereferenced. Tracking pixels and remote images do not load — Cullapse never has the body that would reference them.
  • Reconnection backs off on transient errors and respects the server's stated rate limits.
  • UID validity is re-checked on every reconnect; if the server's UIDVALIDITY changes, the local cache for that mailbox is invalidated.

3. Credential storage

IMAP passwords, app-specific passwords, and AI provider API keys are stored in the system Keychain. Every keychain call site is routed through a single internal store (KeychainStore) so that the iCloud-sync flag is applied uniformly across items.

By default, items use kSecAttrAccessibleWhenUnlockedThisDeviceOnly and do not leave the device. Enabling “Sync passwords with iCloud Keychain” in Settings → General triggers a one-time migration: existing items are deleted and re-added with kSecAttrAccessibleWhenUnlocked, because kSecAttrSynchronizable is part of an item's primary key and cannot be flipped via SecItemUpdate. Reads and deletes always use kSecAttrSynchronizableAny so stale items in either mode are handled cleanly.

4. OAuth — scaffolding, no providers wired

The codebase contains XOAUTH2 routing, an OAuth2 client, token refresh, and an iCloud-Keychain token migrator, but no provider is currently enabled. The reasons are practical:

  • Gmail's mail.google.com/ scope requires an annual CASA security audit.
  • Microsoft's Publisher Verification requires a paid work/school tenant; basic-auth IMAP for personal outlook.com / hotmail.com / live.com was retired in September 2024.
  • iCloud Mail has no IMAP OAuth at all and requires app-specific passwords.
  • Yahoo / AOL's third-party OAuth program is effectively closed.

Every account today authenticates with a password or app-specific password. The OAuth scaffolding is kept so the switch can be flipped when a provider becomes viable for direct distribution.

5. Local cache

Cached headers are persisted with SwiftData inside the application's sandboxed container. The store is configured with ModelConfiguration(url:) — the local-only form. ModelConfiguration(... cloudKitDatabase:) is not used. Cached headers therefore do not sync via CloudKit and are not accessible to any other app.

The cache holds the same fields described in §3 of the privacy policy and nothing else. Bodies are not present because they are never fetched.

6. iCloud sync paths

Cullapse uses Apple's iCloud Key-Value Store (NSUbiquitousKeyValueStore) to sync a narrow allowlist of preferences across your devices, only when you turn it on. The allowlist is enforced in code in a single module. Anything not on the allowlist will not sync, regardless of where it is stored.

On the allowlist:

  • Accounts list — addresses, hosts, ports, display names, without passwords.
  • Rules, AI preferences (no API keys), sender categories, VIPs, suggestion dismissals, replied-message IDs, UI preferences.

Explicitly off the allowlist:

  • Cached message headers (MessageCache).
  • IMAP UID validity, fetch progress.
  • All Keychain items, including passwords and API keys.

iCloud Keychain sync is a separate, per-device preference covered in §3.

7. AI request boundary

For Apple Foundation Models — the default — requests are dispatched through Apple's framework, which routes either to the on-device model or to Private Cloud Compute. No data crosses Apple's privacy boundary.

For an external provider you configure (Anthropic, OpenAI, Google, Perplexity), the request goes from your device directly to the provider's API over TLS, authenticated with the key you entered. The payload is constructed from the metadata fields described in §3 of the privacy policy. The provider's privacy policy governs what they do with the request. Cullapse does not log, mirror, or sample these requests.

8. Destructive-action safety

Bulk delete, archive, and move are optimistic and buffered. When you confirm an action, Cullapse mutates the local headers view immediately and schedules a task to commit the change to the server after a configurable undo window (default 5 seconds, adjustable in Settings). Before that window expires, the ⌘Z undo rolls back from a snapshot stored on the pending action.

  • Both VIP protection and transactional-mail protection are evaluated inside the rules engine, not inside the matcher. Manual selections are not filtered — you are explicit.
  • Both protections are settings-toggle gated and visible in the bulk-action confirmation.
  • Suggestion dismissal is fingerprint-based, so the same suggestion does not reappear after you have rejected it.

9. Automation safeguards

Rules and CLI commands operate on the same buffered pipeline. Every destructive CLI verb supports --dry-run and prints the affected message count before the buffer is committed. Rule conditions are header-only; rules cannot read bodies because no caller in the system has bodies to give them.

10. Network egress

The application's outbound destinations are:

  • Your IMAP servers (port 993, TLS, or 143 with STARTTLS where you require it).
  • generativelanguage.googleapis.com, api.anthropic.com, api.openai.com, api.perplexity.ai — only if you have configured the corresponding provider.
  • Apple endpoints used by the system frameworks (StoreKit, iCloud).

No content is sent to any domain operated by Cullapse, because Cullapse operates none.

11. Logging

The application uses Apple's unified logging system (os_log). Logs are at the info level or below and contain structure (IMAP command names, durations, error codes) but not envelope content. Logs stay on your device and are visible to you in Console.app. Cullapse does not ship logs anywhere.

12. Sandbox and entitlements

The macOS application runs under the App Sandbox. Its entitlements are limited to outbound network access (com.apple.security.network.client), an iCloud KV-Store identifier, an application group used to share license state with the CLI, and a keychain access group used to share credentials with the CLI. The application has no entitlement to read the user's files outside its container, no microphone, no camera, no contacts, no location.

13. CLI signing and entitlements

The cullapse binary ships inside Cullapse.app/Contents/Resources/cullapse. It is built from a separate Swift package by a Run-Script build phase and re-signed with the application's identity for notarization. The CLI's entitlements file deliberately differs from the GUI's:

  • No app-sandbox entitlement — the CLI runs from your shell.
  • No network.client entitlement — unsandboxed processes have network access by default.
  • No ubiquity-kvstore-identifier — the CLI does not touch the iCloud KV-Store.
  • Same application-groups and keychain-access-groups as the GUI — so accounts and credentials are shared between the two surfaces without an additional setup step.

14. Security reports

Cullapse does not operate a coordinated-disclosure program. There is no security inbox, no bug-bounty arrangement, no PGP key, no acknowledgement SLA, and no committed remediation timeline. The app is built and maintained by one person and provided as is, with no warranty (see EULA §12).

If you find what looks like a security issue, you are welcome — but not required — to send a note to dev@snxt.ai. Please understand that:

  • I read messages when I can; I make no commitment to reply or to act on a particular schedule.
  • I cannot promise that a reported issue will be fixed, mitigated, or acknowledged in any release.
  • I do not coordinate embargoes, assign CVEs, or run a vulnerability rewards program. Treat any disclosure timing as your own decision.
  • I do not accept reports that require signing an NDA, an indemnity, or any other agreement as a precondition to reading them.

If you intend to publish a finding, do so on whatever timeline seems right to you. Cullapse is small, open about its architecture (this page exists for a reason), and you can inspect what it does without my permission.

CCullapse

An inbox triage instrument. Metadata only, local processing, one-time purchase.

Product

  • Features
  • Command line
  • AI processing
  • Support

Trust

  • Privacy policy
  • Security
  • Acknowledgments

Legal

  • License (EULA)
  • dev@snxt.ai
© 2026 Shawn M. Brown.Mac App Store and the Apple logo are trademarks of Apple Inc.