Back to overview
Security model

Built so the service can't read your sessions.

XShell is layered: transport, peer-to-peer channel, application, and authentication each protect you independently. Breaking one does not break the others. This page is the long version — what each layer does, what it doesn't, and what we considered when designing it.

Defense in depth

Four independent layers protect every session. Each is meaningful on its own; together they remove single points of failure.

1
Transport
TLS / WSS

Every WebSocket connection — host to relay, browser to relay — runs over TLS. The relay's certificate is verified by the browser and the agent. This protects against passive network observers and standard man-in-the-middle attacks at the network layer.

2
P2P channel
DTLS over WebRTC

When a direct peer-to-peer connection is established between your browser and your device, it runs over a DTLS-secured WebRTC data channel. The DTLS fingerprints in the signaling messages are integrity-protected by the authenticated end-to-end channel, so the relay cannot swap them to insert itself.

3
Application
AES-256-SIV

Terminal I/O, file transfer chunks, and editor traffic are encrypted end-to-end with AES-256-SIV — independent of the transport. Keys are derived via HKDF-SHA256 from the SRP session key, mixed with fresh nonces from both sides and the device identifier. The relay never sees the derived keys.

4
Authentication
SRP-6a

Secure Remote Password is a zero-knowledge proof: your password is never transmitted in any form — not in plaintext, not encrypted, not hashed in transit. Both sides prove knowledge of the password to each other without exposing it. Ed25519 public-key authentication is also supported for passwordless connections.

What we guarantee

The properties below are structural — they come from how the system is built, not from a policy the operator promises to keep.

Zero-knowledge relay

Our relay forwards bytes between your device and your browser. It does not hold the keys to decrypt them. Even with full access to the relay's memory and disk, the operator cannot read your sessions.

No exposed surface on your machine

The agent makes an outbound WebSocket connection. It does not listen on any port and does not require firewall changes. Attackers cannot scan a service that isn't bound to a public interface.

Replay-protected message framing

Every encrypted packet carries a monotonic continuity counter and an authenticated tag. Replayed or tampered packets are rejected on receipt. The counter resets per session, per direction.

Tokens cannot outlive their enrollment

Device enrollment is the trust boundary; access tokens are short-lived and refresh tokens are subordinate to enrollment state. Revoke an enrollment and every token derived from it stops working immediately.

Pairing tokens are one-time

The pairing code shown in your workspace authorizes one enrollment, then dies. Refresh and access tokens are stored hashed — never in plaintext. Raw tokens are never logged.

Open-source agent

The agent — the code that runs on your machine — is licensed under GPLv3 and built from source you can read. You can verify exactly what's running, what it's connecting to, and what it's sending.

How the session key is derived

The end-to-end key is not stored, not exchanged, and not recoverable from observed traffic.

  1. 1

    SRP-6a mutual proof

    The browser and the agent each prove they know the password without sending it. In XShell, your agent plays the role of the SRP "server" — the verifier never leaves the machine you are connecting to. The relay sees neither the verifier nor any data that could be used to mount an offline dictionary attack against it.

  2. 2

    Shared session key K

    Both sides independently compute the same SRP session key K from the proof. K is never transmitted.

  3. 3

    HKDF-SHA256 derivation

    The encryption keys are derived from K using HKDF-SHA256, with both the host nonce and the client nonce mixed in as salt, and the device identifier as info. Fresh nonces from both sides mean neither party alone can predict or replay the derived keys.

  4. 4

    AES-256-SIV per session

    Each session uses its own derived key. SIV mode is misuse-resistant — even if internal counter state were to repeat, the cipher does not catastrophically fail.

  5. 5

    Continuity counter

    Every encrypted packet carries a monotonic counter, starting at 1 per session and direction. Replays and reordering are rejected by the receiver before the payload is processed.

Threat model

The scenarios we designed against, and how the system holds up.

ThreatMitigation
Relay operator goes rogueSession data is end-to-end encrypted with AES-256-SIV under keys the relay never holds. The worst case is denial of service — the operator can refuse to route, but cannot read or forge sessions.
Network observer / ISP / state actorAll transport is TLS. The peer-to-peer path is DTLS over WebRTC. Application traffic is independently end-to-end encrypted. Observed traffic looks like opaque encrypted frames.
Stolen credentials databaseThere is no credentials database to steal. XShell never stores credentials in the database. The salt and verifier derived from your password stay on your local disk and never leave it.
Stolen refresh tokenRefresh tokens are bound to a specific enrollment. Revoke the enrollment from your workspace and the token stops working immediately. They do not participate in session encryption or device authorization, so your data and device remain protected.
Replayed or modified packets in flightEvery encrypted packet includes a monotonic continuity counter and a full-packet authentication tag. Out-of-order, replayed, or tampered packets are rejected.
WebRTC signaling injectionWebRTC offer / answer / ICE candidates are exchanged over the authenticated end-to-end channel after SRP completes. DTLS fingerprints inside SDP are integrity-protected, blocking relay-level peer impersonation.

What the relay operator can and cannot do

Concrete boundaries, so you don't have to guess.

Can

  • Route encrypted frames between your devices
  • Refuse to route (denial of service)
  • See which devices are online and roughly how much traffic flows
  • Enforce account-level limits (device count, parallel sessions)

Cannot

  • Decrypt your terminal output or file transfers
  • Forge a session on your behalf
  • Insert itself as a peer in your WebRTC connection
  • Recover your password from anything it stores

Audit it before you trust it

The agent is open source. Read the code, build it yourself, and verify the security properties on this page.