Files
dosh/docs/THREAT_MODEL.md
T
2026-06-19 16:00:51 -04:00

15 KiB

Dosh Threat Model

This is the published threat model for Dosh native v1, derived from docs/NATIVE_V1_SPEC.md sections 4-6. It states the assets Dosh protects, the attackers it does and does not defend against, the security properties Dosh claims relative to SSH, the cryptographic building blocks actually in use, and an honest list of accepted residual risks and known gaps.

Dosh is a remote-login transport for Dosh-installed servers. It is intended to replace the day-to-day ssh host workflow for terminals and TCP forwarding while keeping OpenSSH as a recovery and bootstrap fallback. Dosh is not an RFC-compatible SSH implementation and does not claim SSH's entire protocol security surface. It claims security that is equivalent to, and in some respects stronger than, SSH for the Dosh terminal and forwarding use case on hosts running dosh-server.

1. Assets

Dosh protects:

  • Terminal session contents. Keystrokes, command output, and the authoritative screen state for every named or generated session.
  • Forwarded TCP streams. Bytes carried over -L, -R, and -D channels.
  • User authentication credentials. The user's SSH/Dosh private keys and any ssh-agent identities. Dosh never sees private key material in plaintext on the wire; signatures are produced locally or by the agent.
  • Server-issued credentials. Session keys, ClientId association state, server-sealed attach tickets, and the client-held attach-ticket PSK.
  • Server identity. The persistent Dosh host key (~/.config/dosh/host_key) and the server secret used to seal attach tickets and derive bootstrap material.
  • Host-trust state. The client's pinned known-hosts file (~/.config/dosh/known_hosts).
  • Authorization policy. ~/.ssh/authorized_keys / ~/.config/dosh/authorized_keys and the forwarding policy they encode.

2. Attackers

In scope (Dosh must defend against these)

  • Passive network observer. May record all UDP traffic between client and server.
  • Active network attacker. May spoof, drop, replay, reorder, or modify any packet, and may attempt to inject forged packets in either direction.
  • NAT rebinding / roaming. Client source IP and port may change mid-session, including across sleep, network switch, and NAT timeout.
  • Stolen attach-ticket cache without the user's private key. An attacker who reads a client cache copies a server-sealed ticket plus its PSK but does not have the user's SSH private key.
  • Server restart and key rotation. Stale session keys, tickets, and replay state must not be usable after the server rotates its secret or host key.
  • Malicious unauthenticated client flooding auth attempts. A peer that has no authorized key tries to exhaust server resources or guess credentials.
  • Compromised low-privilege local user on a shared client. A different local user attempts to read Dosh credential caches on the same machine.

Out of scope (explicitly not defended against)

  • Compromised client machine. If the endpoint running dosh-client is owned by the attacker, the attacker has the user's keys and terminal.
  • Compromised server account. If the login account on the server is owned, the attacker already has the shell Dosh would have given them.
  • Malicious kernel, terminal emulator, or PTY implementation on either side.
  • A server that was legitimately authorized and later turns malicious. Host-key pinning detects a substituted server, not a trusted server that decides to misbehave.

These exclusions match SSH's own boundaries: SSH likewise cannot protect a compromised endpoint or a malicious authorized peer.

3. Security Properties Claimed vs SSH

Property SSH Dosh native v1 Notes
Server authentication before trusting session data yes yes Host key signs the handshake transcript; client verifies before sending user auth or accepting terminal bytes.
User authentication by private-key possession yes yes Ed25519, ECDSA P-256, and RSA-SHA2 via ssh-agent or OpenSSH key; signature binds the full transcript.
Forward secrecy yes yes Ephemeral X25519 per connection; long-term host/user keys never derive the traffic key.
AEAD on every post-handshake packet yes yes ChaCha20-Poly1305 with per-direction, per-sequence nonces.
Replay protection yes yes Sliding replay window over the AEAD packet counter, plus transcript-bound handshake.
Host-key pinning with explicit first use TOFU, weakly tied to transport yes, with explicit policy Default refuses unknown host keys; TOFU only when trust_on_first_use is set; mismatch hard-fails and never auto-replaces.
No plaintext terminal bytes after handshake yes yes All Frame/Input/stream packets are AEAD-sealed.
No custom cryptographic primitives yes yes Standard X25519/HKDF-SHA256/ChaCha20-Poly1305/signature crates only.
Fail-closed downgrade behavior yes yes Native auth failure surfaces an explicit error and SSH fallback is explicit; it never silently drops to an unauthenticated mode.
Fast resumption without re-auth ControlMaster only yes, native Cached session/ticket attach skips a fresh round of public-key proof; this is a deliberate speed/security trade discussed in section 6.

Where Dosh aims to exceed SSH for this use case

  • Tighter transcript binding. A user-auth signature binds both ephemeral keys, both randoms, the server host key, requested user/session/mode/terminal size, selected algorithms, and protocol version into one transcript. This forecloses cross-protocol and partial-replay confusion classes for the narrow Dosh surface.
  • Smaller attack surface. Dosh deliberately omits the full SSH transport/channel machinery, arbitrary subsystems, X11, SFTP/SCP, and forced-command subsystems. Fewer features means fewer parsers and fewer reachable states.
  • Explicit, file-pinned host trust. Host trust is a first-class, inspectable known-hosts entry with source provenance (tofu/ssh/manual) and a hard-fail mismatch path, rather than the looser default TOFU behavior most SSH clients ship.
  • Modern primitives only. Ed25519 and X25519 by default; ECDSA P-256 and RSA-SHA2 are accepted for SSH-key compatibility; no DSA, no SHA-1 signatures, no CBC-and-MAC constructions.

Dosh does not claim generic SSH compatibility and must not be described as an SSH-protocol implementation.

4. Cryptographic Building Blocks (as implemented)

These reflect the code in src/crypto.rs, src/native.rs, src/auth.rs, and src/protocol.rs, not just the spec.

  • Key exchange: X25519 ephemeral-ephemeral (x25519-dalek). The shared secret is checked for contributory behaviour; a non-contributory result is rejected.
  • Handshake/transport KDF: HKDF-SHA256 (hkdf), salted with the SHA-256 of the serialized ClientHello and ServerHello, binding traffic keys to the transcript.
  • AEAD: ChaCha20-Poly1305 (chacha20poly1305) for every encrypted packet and for sealed attach tickets. Nonces are derived as direction || sequence, giving a unique nonce per (key, direction, sequence). AES-GCM is reserved for later and is not selectable today.
  • Host-key signatures: Ed25519 (ed25519-dalek) over the handshake transcript.
  • User-auth signatures: Ed25519, ECDSA P-256, and RSA-SHA2, produced either by ssh-agent over a Unix socket (src/ssh_agent.rs) or from an encrypted/plaintext OpenSSH private key (ssh-key). The signature covers the user-auth transcript described above. RSA public keys are matched as ssh-rsa authorized keys, but native signatures must be rsa-sha2-256 or rsa-sha2-512; legacy SHA-1 ssh-rsa signatures are rejected.
  • Bootstrap auth (SSH fallback path): HMAC-SHA256 attach tokens and HKDF-SHA256 derived session keys, with attach tickets sealed under an HKDF-derived ticket key. Token comparison is constant-time.
  • Hashing/transcript: SHA-256 (sha2).
  • Randomness: OS CSPRNG via rand::thread_rng() / OsRng.

No homegrown ciphers, MACs, padding schemes, or key derivation are used. No nonce or key pair is reused within a direction.

5. How the Properties Are Enforced (handshake and transport)

  • Server authentication. ServerHello carries the host public key and an Ed25519 signature over dosh/native/server-hello/v1 || ClientHello || ServerHello(unsigned). The client verifies this signature and checks the host key against its pinned known-hosts entry before sending user auth or accepting terminal bytes. Unknown keys are refused unless TOFU is enabled; mismatches hard-fail with both fingerprints and the file path.
  • User authentication. UserAuth carries an Ed25519 signature over dosh/native/user-auth/v1 || ClientHello || ServerHello || UserAuth(unsigned). The server looks the public key up in authorized_keys, enforces authorized-key options, then verifies the signature. A removed key can no longer authenticate.
  • Authorization options. from= (with CIDR, glob, and negation), no-port-forwarding, and permitopen= are enforced. command= is rejected for native terminal login. Any unrecognized restrictive option fails closed rather than being silently ignored.
  • Forwarding policy. The server enforces allow_tcp_forwarding, allow_remote_forwarding, and a loopback-only default for remote binds (allow_remote_non_loopback_bind), in addition to per-key permitopen= / no-port-forwarding.
  • Replay protection. A 128-wide sliding window over the per-direction packet counter rejects duplicates and stale sequences. Sequence 0 is never accepted.
  • Stale-key tolerance. Each encrypted packet carries a session_key_id; packets under an old key are dropped as "stale or wrong session key id" rather than treated as fatal decrypt failures, so reconnect after rotation is non-destructive.
  • Roaming. The server keys clients by ClientId and session key id, not by source address, and updates the endpoint after any valid encrypted packet from a new address — without weakening authentication, because the packet must still decrypt and verify.

6. Accepted Residual Risks and Known Gaps

These are stated openly so the public claim gate (NATIVE_V1_SPEC.md section 17) can be evaluated honestly. Items here are not yet "green".

Accepted residual risks (by design)

  • Attach tickets prove recent server-issued possession, not fresh private-key possession. A stolen client cache containing both the sealed ticket and its PSK can attach until the ticket expires (default TTL 24h, configurable down to zero) or until the server rotates its secret/host key or the user key is removed. This is the deliberate speed trade. It is bounded by TTL, scoped to host/user/session/mode, and can be disabled. SSH ControlMaster has an analogous live-socket exposure.
  • Local cache confidentiality relies on filesystem permissions. Host keys, server secret, known-hosts, and credential caches are written 0600. A same-machine attacker who can already read another user's 0600 files (e.g. via root) is out of scope, as with SSH's ~/.ssh.
  • A trusted server that turns malicious is not detected. Host-key pinning detects substitution, not betrayal by an already-authorized server. This matches SSH.

Known gaps / work in progress (must close before the public claim)

  • Native-auth rate limiting needs tuning, not first implementation. The server enforces a per-source token bucket before expensive native-auth work, evicts half-finished handshakes on a TTL, and reports remaining capacity in ServerHello. It is covered by unit/integration tests, but still needs abusive real-host tuning before public hardening claims.
  • Protocol VERSION compatibility is intentionally single-version for v1. The packet header rejects any non-matching VERSION byte and the native handshake rejects any non-matching protocol_version; peers get a named upgrade error, not a silent downgrade. docs/PROTOCOL_VERSIONING.md defines the bump rules and the post-v1 requirements for any future multi-version negotiation.
  • Deep fuzzing still needs launch evidence. CI runs parser/auth fuzz targets for 20 seconds per target on push/PR and 300 seconds per target on weekly/manual runs when nightly/cargo-fuzz is available. That catches obvious panics and parser robustness regressions; public security claims should cite a completed make fuzz-deep or scheduled CI run with durations.
  • User-key algorithm coverage now matches the v1 target. Ed25519, ECDSA P-256, and compatibility RSA-SHA2 native auth are implemented for ssh-agent and OpenSSH identity files. RSA remains compatibility-only and deliberately rejects legacy SHA-1 ssh-rsa signatures.
  • Forwarded stream data uses ordered retransmission. Streams carry byte offsets, cumulative received-offset ACKs, and retransmit unacknowledged chunks as fresh encrypted transport packets. Hostile-network tests cover replay/reorder and server-to-client stream recovery after deliberate UDP loss; broader real-host load soak remains launch evidence.
  • Long-soak evidence is a launch gate. Roaming, retransmit, resize, and multi-client tests exist, and sleep_roaming_soak_30m / make soak-local provide the 30-minute sleep/roaming gate. That gate should be run and published before public security/reliability claims.
  • No third-party audit claim. Dosh maintains a public threat model and hardening checklist, but should not market itself as externally audited unless that actually happens.

Auth posture

Native auth is opt-in alongside SSH fallback. auth_preference defaults to native,ssh: Dosh tries the native authenticated path first and falls back to SSH bootstrap explicitly and visibly when native auth is disabled, unavailable, or rejected. Native auth failure never silently degrades to an unauthenticated mode. Forwarding (-L/-R/-D) requires the native authenticated path and refuses to run under --local-auth.

7. Verification and Public-Claim Status

Dosh may claim "native SSH replacement for Dosh-installed servers" only after the conditions in NATIVE_V1_SPEC.md section 17 are met: native auth default on a real host, SSH fallback available, the section 16 checklist green, this threat model published, and benchmarks with raw samples for SSH cold, Dosh native cold, Dosh cached attach, and Mosh startup.

Current status: this threat model is published (this document). The verification checklist is not yet fully green — see the item-by-item status table in docs/PUBLIC_READINESS.md ("Native v1 verification checklist status") and the known gaps in section 6 above. Until the gaps close, Dosh's defensible public claim remains fast, encrypted native attach/reconnect and forwarding with SSH bootstrap fallback on Dosh-installed servers, not generic SSH compatibility or a third-party audited security product.