Menu

Security model

Sotto is a single-user, offline-first app with no server, no account and no telemetry. The assets are your conversations, personas and model files, on your own device.

Reporting a vulnerability. Email contact@eonix.lk with steps to reproduce. Please do not open a public issue for a vulnerability. You will get an acknowledgement within three working days.

What is in place

Network
Four paths can reach the network, all user-initiated: catalog downloads, the optional weekly catalog check (off by default), the Google search tool (off until you add your own credentials), and any HTTPS tool you create. Every byte sent is counted and shown in Settings › Privacy. Apple's FoundationModels framework runs on-device and offers no off-device route to third-party apps.
Tool credentials
An API key typed into a tool is written to the keychain (kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, no iCloud sync), never to the database, an export or the log. The approval card for a search shows the query, not the key. Erase all data removes the keychain items too.
Tools
Tools are off for a model unless enabled, and a master switch disables the feature outright. A new tool defaults to disabled and to “ask every time”. HTTPS tools are restricted to https and their argument values are percent-encoded so a model cannot append parameters or change the path. Shell tools are compiled out of App Store builds entirely, and the executor refuses a persisted one rather than trusting the UI to hide it. Results are truncated to 4,000 characters and a reply may make at most four calls, so a model cannot loop.
Sandbox
macOS: App Sandbox with user-selected read-only file access and the network client only. iOS: standard container. No app groups, no iCloud, no push — the Xcode template's unused CloudKit and push entitlements file has been deleted.
Storage
SwiftData store in the app container. iOS: NSFileProtectionCompleteUntilFirstUserAuthentication on the store and its WAL/SHM files. macOS: relies on FileVault. Model weights are excluded from backups.
App lock
Optional LAContext device-owner authentication gate; locks on backgrounding.
Input validation
GGUF files are validated by magic bytes before copy and by header parse before registration. Attachments are size-capped (25 MB) and character-capped (60k). Catalog URLs are pinned in the bundle and enforced at decode time to be huggingface.co over HTTPS, so a tampered catalog cannot redirect a download. Tool arguments chosen by a model are checked against the declared parameters before the tool runs.
Logging
os.Logger with no prompt, completion or file contents. Only lifecycle events, counts, durations and error descriptions.
Supply chain
llama.cpp is pinned to tag b10759 and the release archive's SHA-256 is verified by the vendoring script. Fonts are pinned copies from the google/fonts repository under OFL. No other third-party code.

Out of scope

Naming what a security model does not cover is part of the model.

  • Protection against a compromised OS or an attacker with physical access to an unlocked device.
  • Judging whether a tool you create is itself safe. A shell tool runs with your own privileges: Sotto blocks argument injection, not a command you chose to add.
  • Reviewing, filtering or fact-checking what a model writes. Sotto does not do this and says so in the app.
  • Confidentiality of model weights — they are public files.

For what Sotto stores and the four ways anything reaches the network, see the privacy policy. For how tool approval and argument encoding work in practice, see the tools reference.