fix: plan — async host key verification via ssh2 verify callback

This commit is contained in:
Vantz Stockwell 2026-03-12 17:02:20 -04:00
parent de1bb71173
commit 99f3c5caab

View File

@ -2448,6 +2448,7 @@ This is the core of Wraith. The SSH connection service manages ssh2 connections,
```typescript ```typescript
import { Injectable, Logger } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import { Client, ClientChannel } from 'ssh2'; import { Client, ClientChannel } from 'ssh2';
import { createHash } from 'crypto';
import { CredentialsService } from '../vault/credentials.service'; import { CredentialsService } from '../vault/credentials.service';
import { HostsService } from '../connections/hosts.service'; import { HostsService } from '../connections/hosts.service';
import { PrismaService } from '../prisma/prisma.service'; import { PrismaService } from '../prisma/prisma.service';
@ -2522,16 +2523,27 @@ export class SshConnectionService {
host: host.hostname, host: host.hostname,
port: host.port, port: host.port,
username: cred?.username || 'root', username: cred?.username || 'root',
hostVerifier: (key: Buffer) => { hostVerifier: (key: Buffer, verify: (accept: boolean) => void) => {
const fingerprint = require('crypto') const fingerprint = createHash('sha256').update(key).digest('base64');
.createHash('sha256')
.update(key)
.digest('base64');
const fp = `SHA256:${fingerprint}`; const fp = `SHA256:${fingerprint}`;
if (host.hostFingerprint === fp) return true; // known host if (host.hostFingerprint === fp) {
// Async verification — return false for now, handle via callback verify(true); // known host — accept silently
return true; // TODO: wire up onHostKeyVerify properly with async flow return;
}
// Unknown or changed fingerprint — ask the user via WebSocket
const isNew = !host.hostFingerprint;
onHostKeyVerify(fp, isNew).then((accepted) => {
if (accepted) {
// Persist fingerprint so future connections auto-accept
this.prisma.host.update({
where: { id: hostId },
data: { hostFingerprint: fp },
}).catch(() => {});
}
verify(accepted);
});
}, },
}; };