# SSH Known Hosts Management in Tabby: Implementation and Configuration Guide

> Learn how Tabby implements and configures SSH known hosts management. Discover its Angular service, key fingerprint persistence, and interactive prompts for secure SSH connections.

- Repository: [Eugene/tabby](https://github.com/Eugeny/tabby)
- Tags: how-to-guide
- Published: 2026-03-03

---

**Tabby implements SSH known hosts management through an Angular injectable service that persists host-key fingerprints in the user configuration file and triggers interactive prompts when server keys are unknown or mismatched.**

Tabby, the open-source terminal emulator by Eugeny, provides built-in SSH known hosts management to prevent man-in-the-middle attacks during remote connections. The implementation stores verified host-key digests in the application's config store and automatically validates subsequent connections against these fingerprints. This guide examines the source code architecture behind Tabby's SSH security model, covering configuration storage, verification workflows, and programmatic APIs.

## Configuration Storage Structure

Tabby defines the default SSH configuration structure in [`tabby-ssh/src/config.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-ssh/src/config.ts) within the `SSHConfigProvider` class. The implementation uses two critical properties for host key management:

- **`knownHosts`**: An array that stores objects containing host identifiers and their corresponding key fingerprints
- **`verifyHostKeys`**: A boolean flag that globally enables or disables host key verification

```typescript
// https://github.com/Eugeny/tabby/blob/master/tabby-ssh/src/config.ts#L12-L14
knownHosts: [],
verifyHostKeys: true,

```

When persisted to disk, these values are written to the user's configuration file (typically located at `~/.config/Tabby/config.json` on Linux systems). The `knownHosts` array maintains the trust anchor for all previously accepted SSH servers.

## The SSHKnownHostsService API

The core logic for reading and writing known host entries resides in [`tabby-ssh/src/services/sshKnownHosts.service.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-ssh/src/services/sshKnownHosts.service.ts). The `SSHKnownHostsService` is an injectable singleton that operates directly on `config.store.ssh.knownHosts` and provides a type-safe interface for host key retrieval and persistence.

The service exposes two primary methods:

- **`getFor(selector: KnownHostSelector)`**: Retrieves a stored host entry matching the provided host, port, and algorithm type. Returns `undefined` if no matching entry exists.
- **`store(selector: KnownHostSelector, digest: string)`**: Updates an existing entry or appends a new one to the configuration array, then persists changes via `config.save()`.

```typescript
// https://github.com/Eugeny/tabby/blob/master/tabby-ssh/src/services/sshKnownHosts.service.ts#L20-L31
getFor (selector) { … }
async store (selector, digest) { … }

```

The `KnownHostSelector` interface requires three properties: `host` (string), `port` (number), and `type` (string representing the algorithm name such as 'ssh-rsa' or 'ssh-ed25519').

## Host Key Verification Flow

When establishing an SSH connection, `SSHSession.verifyHostKey()` in [`tabby-ssh/src/session/ssh.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-ssh/src/session/ssh.ts) validates each host key presented by the server. The method implements the following security checks:

1. **Digest Computation**: Calculates a SHA-256 fingerprint of the raw key bytes received from the server
2. **Global Bypass**: If `verifyHostKeys` is set to `false`, verification is skipped entirely
3. **Selector Construction**: Creates a selector object containing the target host, port, and key algorithm
4. **Lookup**: Queries `SSHKnownHostsService.getFor()` to find a matching stored entry

```typescript
// https://github.com/Eugeny/tabby/blob/master/tabby-ssh/src/session/ssh.ts#L55-L71
const selector = { host, port, type: key.algorithm() }
const knownHost = this.knownHosts.getFor(selector)

```

If the lookup returns no result, or if the stored digest differs from the computed fingerprint, the session triggers the user interface prompt to resolve the discrepancy.

## User Interaction and Key Prompting

When verification fails or finds no existing entry, Tabby instantiates `HostKeyPromptModalComponent` from [`tabby-ssh/src/components/hostKeyPromptModal.component.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-ssh/src/components/hostKeyPromptModal.component.ts). This modal displays the new host key fingerprint and provides options to accept temporarily or permanently trust the key.

The modal component implements `acceptAndSave()`, which persists the new fingerprint to configuration:

```typescript
// https://github.com/Eugeny/tabby/blob/master/tabby-ssh/src/components/hostKeyPromptModal.component.ts#L31-L38
async acceptAndSave () {
    await this.knownHosts.store(this.selector, this.digest)
    this.accept()
}

```

Once the user confirms acceptance, the fingerprint is permanently stored in the configuration file, enabling automatic verification for all future connections to that specific host, port, and algorithm combination.

## Programmatic Access Examples

You can interact with Tabby's SSH known hosts management system programmatically through the service APIs.

### Retrieve a Known Host Entry

```typescript
import { SSHKnownHostsService, KnownHostSelector } from 'tabby-ssh/src/services/sshKnownHosts.service';
import { Injector } from '@angular/core';

const injector = Injector.create({providers: [{provide: SSHKnownHostsService, useClass: SSHKnownHostsService, deps: []}]});
const knownHosts = injector.get(SSHKnownHostsService);

const selector: KnownHostSelector = {
    host: 'example.com',
    port: 22,
    type: 'ssh-rsa',
};

const entry = knownHosts.getFor(selector);
if (entry) {
    console.log(`Stored fingerprint: ${entry.digest}`);
} else {
    console.log('Host not known yet');
}

```

### Add or Update a Host Entry

```typescript
import { SSHKnownHostsService, KnownHostSelector } from 'tabby-ssh/src/services/sshKnownHosts.service';
import { Injector } from '@angular/core';

const injector = Injector.create({providers: [{provide: SSHKnownHostsService, useClass: SSHKnownHostsService, deps: []}]});
const knownHosts = injector.get(SSHKnownHostsService);

const selector: KnownHostSelector = {
    host: 'my.server',
    port: 2222,
    type: 'ssh-ed25519',
};

const fingerprint = 'SHA256:abcdef...';

await knownHosts.store(selector, fingerprint);
console.log('Host key stored');

```

### Disable Host Key Verification Globally

Edit the configuration file directly:

```json
{
  "ssh": {
    "verifyHostKeys": false
  }
}

```

Or modify the setting programmatically:

```typescript
import { ConfigService } from 'tabby-core';
const config = injector.get(ConfigService);
config.store.ssh.verifyHostKeys = false;
config.save();

```

## Summary

- **Storage Location**: Host fingerprints are stored in the `ssh.knownHosts` array within Tabby's user configuration file, defined in [`tabby-ssh/src/config.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-ssh/src/config.ts).
- **Service Layer**: `SSHKnownHostsService` provides the primary API for lookups (`getFor`) and persistence (`store`), operating directly on the config store.
- **Verification Logic**: `SSHSession.verifyHostKey()` in [`tabby-ssh/src/session/ssh.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-ssh/src/session/ssh.ts) computes SHA-256 digests and validates against stored entries, respecting the `verifyHostKeys` boolean flag.
- **User Interface**: `HostKeyPromptModalComponent` handles unknown or changed keys, calling `store()` to persist user-approved fingerprints via `acceptAndSave()`.
- **Security Model**: The implementation prevents man-in-the-middle attacks by maintaining a persistent trust-on-first-use (TOFU) database with interactive confirmation for new or modified host keys.

## Frequently Asked Questions

### Where does Tabby store SSH known host fingerprints?

Tabby stores SSH host-key fingerprints in the user configuration file, typically located at `~/.config/Tabby/config.json` on Linux systems or equivalent paths on other platforms. The fingerprints reside in the `ssh.knownHosts` array as objects containing host, port, algorithm type, and digest properties, as defined in [`tabby-ssh/src/config.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-ssh/src/config.ts).

### How do I disable host key verification in Tabby?

Set the `verifyHostKeys` property to `false` in the SSH configuration section. You can edit the configuration JSON file directly or access `config.store.ssh.verifyHostKeys` through the `ConfigService` API in `tabby-core`. When disabled, `SSHSession.verifyHostKey()` bypasses all fingerprint validation checks.

### What hashing algorithm does Tabby use for host key verification?

Tabby uses **SHA-256** to compute digests of raw host key bytes during the verification process in `SSHSession.verifyHostKey()`. The resulting fingerprint is compared against previously stored entries in the `knownHosts` array, with mismatches triggering the modal prompt for user confirmation.

### Can extensions programmatically manage known hosts in Tabby?

Yes, extensions can inject `SSHKnownHostsService` from [`tabby-ssh/src/services/sshKnownHosts.service.ts`](https://github.com/Eugeny/tabby/blob/main/tabby-ssh/src/services/sshKnownHosts.service.ts) to programmatically retrieve entries via `getFor(selector)` or persist new fingerprints using `store(selector, digest)`. Both methods accept a `KnownHostSelector` object specifying the host, port, and algorithm type, enabling automated host key management for specialized workflows.