fix: harden port listener detection

This commit is contained in:
Peter Steinberger
2026-01-21 18:52:26 +00:00
parent 32550154f9
commit 403904ecd1
6 changed files with 139 additions and 21 deletions

View File

@@ -50,22 +50,28 @@ export function pickProbeHostForBind(
return "127.0.0.1";
}
export function safeDaemonEnv(env: Record<string, string> | undefined): string[] {
if (!env) return [];
const allow = [
"CLAWDBOT_PROFILE",
"CLAWDBOT_STATE_DIR",
"CLAWDBOT_CONFIG_PATH",
"CLAWDBOT_GATEWAY_PORT",
"CLAWDBOT_NIX_MODE",
];
const lines: string[] = [];
for (const key of allow) {
const SAFE_DAEMON_ENV_KEYS = [
"CLAWDBOT_PROFILE",
"CLAWDBOT_STATE_DIR",
"CLAWDBOT_CONFIG_PATH",
"CLAWDBOT_GATEWAY_PORT",
"CLAWDBOT_NIX_MODE",
];
export function filterDaemonEnv(env: Record<string, string> | undefined): Record<string, string> {
if (!env) return {};
const filtered: Record<string, string> = {};
for (const key of SAFE_DAEMON_ENV_KEYS) {
const value = env[key];
if (!value?.trim()) continue;
lines.push(`${key}=${value.trim()}`);
filtered[key] = value.trim();
}
return lines;
return filtered;
}
export function safeDaemonEnv(env: Record<string, string> | undefined): string[] {
const filtered = filterDaemonEnv(env);
return Object.entries(filtered).map(([key, value]) => `${key}=${value}`);
}
export function normalizeListenerAddress(raw: string): string {

View File

@@ -14,16 +14,39 @@ import { getResolvedLoggerSettings } from "../../logging.js";
import { defaultRuntime } from "../../runtime.js";
import { colorize, isRich, theme } from "../../terminal/theme.js";
import { formatCliCommand } from "../command-format.js";
import { formatRuntimeStatus, renderRuntimeHints, safeDaemonEnv } from "./shared.js";
import {
filterDaemonEnv,
formatRuntimeStatus,
renderRuntimeHints,
safeDaemonEnv,
} from "./shared.js";
import {
type DaemonStatus,
renderPortDiagnosticsForCli,
resolvePortListeningAddresses,
} from "./status.gather.js";
function sanitizeDaemonStatusForJson(status: DaemonStatus): DaemonStatus {
const command = status.service.command;
if (!command?.environment) return status;
const safeEnv = filterDaemonEnv(command.environment);
const nextCommand = {
...command,
environment: Object.keys(safeEnv).length > 0 ? safeEnv : undefined,
};
return {
...status,
service: {
...status.service,
command: nextCommand,
},
};
}
export function printDaemonStatus(status: DaemonStatus, opts: { json: boolean }) {
if (opts.json) {
defaultRuntime.log(JSON.stringify(status, null, 2));
const sanitized = sanitizeDaemonStatusForJson(status);
defaultRuntime.log(JSON.stringify(sanitized, null, 2));
return;
}

View File

@@ -1,4 +1,5 @@
import { execFileSync } from "node:child_process";
import { resolveLsofCommandSync } from "../infra/ports-lsof.js";
export type PortProcess = { pid: number; command?: string };
@@ -30,7 +31,8 @@ export function parseLsofOutput(output: string): PortProcess[] {
export function listPortListeners(port: number): PortProcess[] {
try {
const out = execFileSync("lsof", ["-nP", `-iTCP:${port}`, "-sTCP:LISTEN", "-FpFc"], {
const lsof = resolveLsofCommandSync();
const out = execFileSync(lsof, ["-nP", `-iTCP:${port}`, "-sTCP:LISTEN", "-FpFc"], {
encoding: "utf-8",
});
return parseLsofOutput(out);