mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-07 17:04:42 +00:00
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:
@@ -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,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),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user