Security
Terminality's security model treats the React/React Native layers as untrusted presentation clients. Secrets never cross the Rust–JavaScript boundary.
Trust Boundaries
┌─ Untrusted ─────────────────────┐ ┌─ Trusted (Rust) ────────────┐
│ React / React Native │ │ │
│ - Renders UI from ViewModels │ │ - Cryptography │
│ - Invokes typed Commands │ │ - Credential resolution │
│ - Never sees private keys │ │ - Host-key decisions │
│ - Never sees passwords │ │ - File operations │
│ - Never constructs shell exec │ │ - PTY / ConPTY management │
└─────────────────────────────────┘ └─────────────────────────────┘- Tauri WebView: packaged assets only, restrictive CSP,
core:defaultcapability only. Filesystem and shell plugins intentionally absent. - Custom Tauri commands expose domain operations, not arbitrary paths or process execution.
- The public Session binding has no
openLocal(program, arguments)escape hatch.
Vault Cryptography
Record Encryption (at rest)
- Algorithm: XChaCha20-Poly1305
- Nonce: random 24-byte per record
- AAD: record ID, record type, schema version, revision, tombstone
- Zeroization: plaintext buffers and derived keys are zeroized after use
Export Archives (.sztvault)
- KDF: Argon2id — 64 MiB memory, 3 passes, 4 lanes → 32-byte key
- Salt: random 16-byte
- Header: versioned, AEAD-authenticated
- Import: rejects unsupported parameters before derivation (prevents DoS via attacker-selected KDF costs)
Key Storage
- Desktop: random 256-bit device key → macOS Keychain / Windows Credential Manager / Linux Secret Service
- Debug builds: isolated
development/app-data directory with local key — never touches OS credential store - Mobile: iOS Keychain / Android Keystore (required native work, release blocker)
Repository
One shared EncryptedVaultRepository (Arc-injected) for Hosts, QCS history, Settings, and Quick Commands. Only authenticated encrypted envelopes touch SQLite. Schema migration is monotonic — future versions are rejected, never downgraded.
Host & Credential Protections
- Host profiles encrypt metadata (hostnames, tags, directories, RDP options) together with the opaque credential reference.
- Passwords, private-key bytes, and passphrases are never fields of
HostProfile,CreateHostArgs, orUpdateHostArgs. - RDP passwords go through a dedicated command: zeroizing buffer, seal as separate Credential record, return opaque reference only.
- SSH Hosts are shared by SSH/SFTP/Omini. FTP and RDP are independent families — cannot borrow another family's endpoint or credentials.
Terminal Protections
| Protection | Mechanism |
|---|---|
| No silent clipboard write | OSC 52 disabled |
| No clickable links (yet) | Link addon not installed; external-link confirmation required before enabling |
| Multi-line paste | Confirmation dialog in terminal surface |
| Command Composer | 64 KiB cap, explicit per-tab confirmation, running sessions only, per-Pane results |
| Quick Commands | Fill draft only — never execute, never persist draft |
| Output bounded | Queue depth 64 × 8 KiB, backpressure on PTY reader |
| Close guard | Unix: foreground process group check. Windows: conservative live-session confirmation |
| tmux safety | Parsed $id + generation; rejects restarted-server reuse; names length/character validated |
RDP Protections
- Independent Host family — cannot borrow SSH/SFTP/FTP credentials.
- NLA default; legacy TLS requires explicit opt-in.
- Certificate pinning: first-use SHA-256 leaf review → pin → changed leaf re-triggers review.
- Separate target and gateway credentials with different opaque IDs.
- Clipboard/drive channels not compiled.
- Connection generations reject stale completions, input, and frames.
Local File Protections
See Local Files for the complete safety design: descriptor-relative traversal, generation-scoped references, triple-verified identity, trash-only deletion, bounded batches.
Platform Discovery
- Runtime-only, never persisted, never imported as Hosts.
- Requested only when QCS opens — not at startup.
- Platform tools invoked as executable + fixed argument vector, never through a shell string.
- Hard deadlines, bounded stdout/stderr, machine-count limit.
- Discovered actions disabled until native endpoint resolver and production backend are connected.
Logging & Telemetry
- No telemetry or crash upload configured.
- New diagnostics must be opt-in.
- Must never include: commands, terminal output, paths, hostnames, secrets, raw vault errors.
- DTO logging from session, file, host, and vault commands is avoided.
Dependency Policy
- Commercially compatible licenses only (MIT, Apache-2.0, BSD, ISC, etc.) — enforced by
cargo deny. - CI blocks high/critical npm advisories.
- Bundled fonts: audited, pinned, content-addressed — never downloaded at runtime. Attribution recorded in third-party notices.