fix(hub): correct relationship trust boundaries

Authenticated daemon sessions own relationship management regardless of transport. The separate Hub session remains operation-allowlisted, rejects malformed execution inputs, and uses bounded outbound handshakes.
This commit is contained in:
Mohamed Boudra
2026-07-13 17:47:40 +02:00
parent 3772a8a118
commit dfcaa9bf89
11 changed files with 142 additions and 188 deletions
@@ -1,30 +0,0 @@
import { describe, expect, test } from "vitest";
import { assertLocalHubManagementTarget } from "./index.js";
describe("Hub CLI target authority", () => {
test.each(["relay.paseo.test:443", "tcp://10.0.0.5:6767?ssl=true"])(
"rejects non-local explicit target %s before connect",
(host) => {
expect(() => assertLocalHubManagementTarget(host, {})).toThrow(
"Hub relationship management requires a local daemon target",
);
},
);
test.each([
undefined,
"localhost:6767",
"127.0.0.1:6767",
"[::1]:6767",
"[0:0:0:0:0:0:0:1]:6767",
"unix:///tmp/paseo.sock",
])("accepts local target %s", (host) => {
expect(() => assertLocalHubManagementTarget(host, {})).not.toThrow();
});
test("rejects a non-local PASEO_HOST target", () => {
expect(() =>
assertLocalHubManagementTarget(undefined, { PASEO_HOST: "hub.test:6767" }),
).toThrow("Hub relationship management requires a local daemon target");
});
});
+1 -22
View File
@@ -1,7 +1,7 @@
import { Command } from "commander";
import { withOutput, type ListResult, type OutputSchema } from "../../output/index.js";
import { addJsonAndDaemonHostOptions } from "../../utils/command-options.js";
import { connectToDaemon, resolveDaemonTarget } from "../../utils/client.js";
import { connectToDaemon } from "../../utils/client.js";
interface HubRow {
state: string;
@@ -66,26 +66,6 @@ async function withClient<T>(
}
}
export function assertLocalHubManagementTarget(
host: string | undefined,
env: NodeJS.ProcessEnv = process.env,
): void {
const explicitHost = host ?? env.PASEO_HOST;
if (!explicitHost) return;
const target = resolveDaemonTarget(explicitHost);
if (target.type === "ipc") return;
const hostname = new URL(target.url).hostname.replace(/^\[|\]$/g, "").toLowerCase();
if (
hostname === "localhost" ||
hostname === "::1" ||
hostname === "0:0:0:0:0:0:0:1" ||
/^127(?:\.\d{1,3}){3}$/.test(hostname)
) {
return;
}
throw new Error("Hub relationship management requires a local daemon target");
}
export function createHubCommand(): Command {
const hub = new Command("hub").description("Manage this daemon's Paseo Hub relationship");
addJsonAndDaemonHostOptions(
@@ -94,7 +74,6 @@ export function createHubCommand(): Command {
withOutput(async (...args) => {
const url = args[0] as string;
const options = args.at(-2) as { token: string; host?: string };
assertLocalHubManagementTarget(options.host);
return withClient(options.host, async (client) =>
result((await client.connectHub(url, options.token)).status),
);