Files
NetMesh/domain/credentials.test.ts
zhaolei 3c72efcb7f
Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
[Init] Initial commit - NetMesh terminal manager
2026-09-13 18:24:01 +08:00

183 lines
5.6 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import {
findSyncPayloadEncryptedCredentialPaths,
healPoisonedSecretsForMerge,
isEncryptedCredentialPlaceholder,
isVaultStoredKeySource,
needsVaultStoredKeyHydration,
stripSyncPayloadEncryptedCredentials,
} from "./credentials.ts";
import type { SyncPayload } from "./sync.ts";
const completeBlob = Buffer.alloc(19, 0);
Buffer.from("v10", "utf8").copy(completeBlob, 0);
const ENC = `enc:v1:${completeBlob.toString("base64")}`;
function samplePayload(overrides: Partial<SyncPayload> = {}): SyncPayload {
return {
hosts: [
{
id: "h1",
label: "prod",
hostname: "prod.example",
username: "root",
password: ENC,
port: 22,
os: "linux",
group: "",
tags: [],
protocol: "ssh",
},
],
keys: [
{
id: "k1",
label: "key",
type: "ED25519",
privateKey: ENC,
source: "imported",
category: "key",
created: 1,
},
],
identities: [],
snippets: [],
customGroups: [],
syncedAt: 1,
...overrides,
};
}
test("isEncryptedCredentialPlaceholder detects complete v10 device-bound ciphertext", () => {
assert.equal(isEncryptedCredentialPlaceholder(ENC), true);
});
test("isEncryptedCredentialPlaceholder rejects intermediate v10 lengths that are neither CBC nor GCM", () => {
const body = Buffer.alloc(24, 0);
Buffer.from("v10", "utf8").copy(body, 0);
assert.equal(isEncryptedCredentialPlaceholder(`enc:v1:${body.toString("base64")}`), false);
});
test("isEncryptedCredentialPlaceholder detects real Windows DPAPI base64 prefixes", () => {
const body = Buffer.from([
0x01, 0x00, 0x00, 0x00,
0xd0, 0x8c, 0x9d, 0xdf, 0x01, 0x15, 0xd1, 0x11,
0x8c, 0x7a, 0x00, 0xc0, 0x4f, 0xc2, 0x97, 0xeb,
0xaa,
]);
const encoded = body.toString("base64");
assert.equal(encoded.startsWith("AQAAANCMnd8"), true);
assert.equal(isEncryptedCredentialPlaceholder(`enc:v1:${encoded}`), true);
});
test("isEncryptedCredentialPlaceholder rejects header-only enc:v1 payloads", () => {
assert.equal(isEncryptedCredentialPlaceholder("enc:v1:djEw"), false);
});
test("needsVaultStoredKeyHydration waits for imported or generated ciphertext and empty keys", () => {
assert.equal(isVaultStoredKeySource("imported"), true);
assert.equal(isVaultStoredKeySource("generated"), true);
assert.equal(isVaultStoredKeySource("reference"), false);
assert.equal(needsVaultStoredKeyHydration({
source: "imported",
privateKey: ENC,
}), true);
assert.equal(needsVaultStoredKeyHydration({
source: "generated",
privateKey: "",
}), true);
assert.equal(needsVaultStoredKeyHydration({
source: "imported",
privateKey: "-----BEGIN OPENSSH PRIVATE KEY-----",
}), false);
assert.equal(needsVaultStoredKeyHydration({
source: "reference",
privateKey: ENC,
}), false);
});
test("findSyncPayloadEncryptedCredentialPaths reports host and key secrets", () => {
const paths = findSyncPayloadEncryptedCredentialPaths(samplePayload());
assert.deepEqual(paths, ["hosts[0].password", "keys[0].privateKey"]);
});
test("stripSyncPayloadEncryptedCredentials clears device-bound placeholders for recovery", () => {
const stripped = stripSyncPayloadEncryptedCredentials(samplePayload());
assert.equal(stripped.hosts[0]?.password, undefined);
assert.equal(stripped.keys[0]?.privateKey, "");
assert.equal(findSyncPayloadEncryptedCredentialPaths(stripped).length, 0);
});
test("healPoisonedSecretsForMerge keeps usable preferred passwords over poisoned enc:v1", () => {
const poisoned = samplePayload();
const preferred = samplePayload({
hosts: [{
...samplePayload().hosts[0]!,
password: "preferred-secret",
}],
keys: [{
...samplePayload().keys[0]!,
privateKey: "PREFERRED_PRIVATE_KEY",
}],
});
const fallback = samplePayload({
hosts: [{
...samplePayload().hosts[0]!,
password: "base-secret",
}],
});
const healed = healPoisonedSecretsForMerge(poisoned, preferred, fallback);
assert.equal(healed.hosts[0]?.password, "preferred-secret");
assert.equal(healed.keys[0]?.privateKey, "PREFERRED_PRIVATE_KEY");
});
test("healPoisonedSecretsForMerge heals local poison from remote then base", () => {
const local = samplePayload();
const remote = samplePayload({
hosts: [{
...samplePayload().hosts[0]!,
password: "remote-secret",
}],
keys: [{
...samplePayload().keys[0]!,
privateKey: ENC,
}],
});
const base = samplePayload({
keys: [{
...samplePayload().keys[0]!,
privateKey: "BASE_PRIVATE_KEY",
}],
});
const healed = healPoisonedSecretsForMerge(local, remote, base);
assert.equal(healed.hosts[0]?.password, "remote-secret");
assert.equal(healed.keys[0]?.privateKey, "BASE_PRIVATE_KEY");
});
test("healPoisonedSecretsForMerge preserves explicit preferred credential deletions", () => {
const poisoned = samplePayload({
hosts: [{
...samplePayload().hosts[0]!,
label: "renamed-on-poisoned-device",
password: ENC,
}],
});
const preferred = samplePayload({
hosts: [{
...samplePayload().hosts[0]!,
label: "renamed-on-poisoned-device",
password: undefined,
}],
});
const fallback = samplePayload({
hosts: [{
...samplePayload().hosts[0]!,
password: "base-secret",
}],
});
const healed = healPoisonedSecretsForMerge(poisoned, preferred, fallback);
assert.equal(healed.hosts[0]?.password, undefined);
assert.equal(healed.hosts[0]?.label, "renamed-on-poisoned-device");
});