Files
IronStorage/docs/secure-secret-storage.md
Chili Palmer b93ae852e0
Some checks failed
Dependency security audit / rustsec (push) Has been cancelled
Reuse native macOS Git credentials
2026-08-26 18:53:55 +02:00

3.7 KiB

Secure secret storage

crates/storage owns the complete secret-storage contract. Configuration, password-store repositories, Git configuration, command arguments, and logs contain only opaque identifiers; passphrases, tokens, and HTTPS passwords are stored by the operating system.

SecretReference has three validated forms. OpenPGP passphrases are keyed by the primary fingerprint. HTTPS Git credentials are keyed by purpose, server ID, application ID, and account. The account is kept inside the protected record, so a configured server/application pair can retrieve it without adding an account or secret value to TOML. SSH private-key passphrases are keyed by the key's SHA-256 fingerprint. References, locators, store state, and errors all use redacted Debug output.

Stored values use a small versioned binary envelope containing their reference and secret bytes. Retrieval validates the envelope and exact reference before release. Malformed or ambiguous records produce a typed Corrupted error; asking for another account at the same Git locator produces Missing without altering the stored account. create refuses to overwrite, replace requires an exact existing record, and missing, denied, cancelled, locked, corrupted, unsupported-policy, and unavailable-store results remain distinct. Returned and cached bytes use SecretBytes, which zeroizes its allocation when dropped.

Operating-system adapters

The platform-selection code is isolated in crates/storage/src/secret_store/platform.rs and calls only safe Rust APIs:

  • macOS uses legacy Keychain for command-line-compatible device-unlocked credentials and Protected Data for RequireUserPresence; iOS uses Protected Data. macOS HTTPS synchronization uses only the unique standard Internet-password credential matching the remote endpoint; it does not use an IronStorage-specific Git credential locator. User cancellation is mapped from the native Security Framework status.
  • Windows uses Credential Manager. Store operations are serialized because the upstream adapter documents unreliable same-entry sequencing across threads.
  • Linux uses Secret Service through zbus with the Rust cryptography feature. It does not launch secret-tool, a shell, or any other helper. A missing session service is a typed Unavailable result.

IronStorage contains no direct platform FFI or unsafe Rust. The selected adapter crates own their OS calls, so there is no project-local FFI safety contract beyond providing validated UTF-8 identifiers and bounded byte slices.

Locking and caching

A new store starts logically locked. unlock must succeed before create, retrieve, replace, or delete; lock immediately clears all cached values even if the platform lock operation reports an error. Caching is disabled unless a caller explicitly selects SecretCachePolicy::Timed. Timed policies are capped at 128 entries and 15 minutes, expire lazily, and are always cleared on lock.

The same unlocked store implements the OpenPGP SecretProvider, HTTPS Git GitCredentialProvider, and SSH SshPassphraseProvider. CLI, TUI, and desktop pass one prompted SSH passphrase as zeroizing bytes for one retry. Storage binds that override to the requested key fingerprint, and the authentication handle persists it only after the Git operation succeeds; cancellation, rejection, and other failures never create or replace a record. Prompts are hidden or masked, and secret values are excluded from arguments, history, normal output, debug models, notifications, and the clipboard. Tests inject a memory backend and never access a developer or CI user keyring.

The SSH release audit in ssh-transport-audit.md ties this passphrase contract to the complete host-trust, retry, failure, frontend, and artifact matrix.