fix(config): bound gateway env ports · openclaw/openclaw@0f0c744
steipete
·
2026-05-29
·
via Recent Commits to openclaw:main
| Original file line number | Diff line number | Diff line change |
|---|
@@ -87,6 +87,24 @@ describe("gateway port resolution", () => {
|
87 | 87 | ).toBe(19003); |
88 | 88 | }); |
89 | 89 | |
| 90 | +it("falls back to config when env ports exceed TCP bounds", () => { |
| 91 | +expect( |
| 92 | +resolveGatewayPort({ gateway: { port: 19003 } }, envWith({ OPENCLAW_GATEWAY_PORT: "65536" })), |
| 93 | +).toBe(19003); |
| 94 | +expect( |
| 95 | +resolveGatewayPort( |
| 96 | +{ gateway: { port: 19004 } }, |
| 97 | +envWith({ OPENCLAW_GATEWAY_PORT: "127.0.0.1:65536" }), |
| 98 | +), |
| 99 | +).toBe(19004); |
| 100 | +expect( |
| 101 | +resolveGatewayPort( |
| 102 | +{ gateway: { port: 19005 } }, |
| 103 | +envWith({ OPENCLAW_GATEWAY_PORT: "[::1]:65536" }), |
| 104 | +), |
| 105 | +).toBe(19005); |
| 106 | +}); |
| 107 | + |
90 | 108 | it("falls back when malformed IPv6 inputs do not provide an explicit port", () => { |
91 | 109 | expect( |
92 | 110 | resolveGatewayPort({ gateway: { port: 19003 } }, envWith({ OPENCLAW_GATEWAY_PORT: "::1" })), |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
2 | 2 | import os from "node:os"; |
3 | 3 | import path from "node:path"; |
4 | 4 | import { resolveHomeRelativePath, resolveRequiredHomeDir } from "../infra/home-dir.js"; |
5 | | -import { parseStrictPositiveInteger } from "../infra/parse-finite-number.js"; |
| 5 | +import { parseTcpPort } from "../infra/tcp-port.js"; |
6 | 6 | import type { OpenClawConfig } from "./types.js"; |
7 | 7 | |
8 | 8 | /** |
@@ -306,14 +306,14 @@ function parseGatewayPortEnvValue(raw: string | undefined): number | null {
|
306 | 306 | return null; |
307 | 307 | } |
308 | 308 | if (/^\d+$/.test(trimmed)) { |
309 | | -return parseStrictPositiveInteger(trimmed) ?? null; |
| 309 | +return parseTcpPort(trimmed); |
310 | 310 | } |
311 | 311 | |
312 | 312 | // Docker Compose publish strings can leak into host CLI env loading via repo `.env`, |
313 | 313 | // for example `127.0.0.1:18789` or `[::1]:18789`. Accept only explicit host:port forms. |
314 | 314 | const bracketedIpv6Match = trimmed.match(/^\[[^\]]+\]:(\d+)$/); |
315 | 315 | if (bracketedIpv6Match?.[1]) { |
316 | | -return parseStrictPositiveInteger(bracketedIpv6Match[1]) ?? null; |
| 316 | +return parseTcpPort(bracketedIpv6Match[1]); |
317 | 317 | } |
318 | 318 | |
319 | 319 | const firstColon = trimmed.indexOf(":"); |
@@ -325,7 +325,7 @@ function parseGatewayPortEnvValue(raw: string | undefined): number | null {
|
325 | 325 | if (!/^\d+$/.test(suffix)) { |
326 | 326 | return null; |
327 | 327 | } |
328 | | -return parseStrictPositiveInteger(suffix) ?? null; |
| 328 | +return parseTcpPort(suffix); |
329 | 329 | } |
330 | 330 | |
331 | 331 | export function resolveGatewayPort( |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -158,6 +158,28 @@ describe("startGatewayDiscovery", () => {
|
158 | 158 | ); |
159 | 159 | }); |
160 | 160 | |
| 161 | +it("omits out-of-range SSH discovery ports", async () => { |
| 162 | +process.env.NODE_ENV = "development"; |
| 163 | +delete process.env.VITEST; |
| 164 | +process.env.OPENCLAW_SSH_PORT = "65536"; |
| 165 | + |
| 166 | +const service = makeDiscoveryService({ id: "bonjour" }); |
| 167 | + |
| 168 | +await startGatewayDiscovery({ |
| 169 | +machineDisplayName: "Lab Mac", |
| 170 | +port: 18789, |
| 171 | +wideAreaDiscoveryEnabled: false, |
| 172 | +tailscaleMode: "serve", |
| 173 | +mdnsMode: "full", |
| 174 | +gatewayDiscoveryServices: [service], |
| 175 | +logDiscovery: makeLogs(), |
| 176 | +}); |
| 177 | + |
| 178 | +expect(service.service.advertise).toHaveBeenCalledWith( |
| 179 | +expect.objectContaining({ sshPort: undefined }), |
| 180 | +); |
| 181 | +}); |
| 182 | + |
161 | 183 | it("continues startup when a local discovery service never settles", async () => { |
162 | 184 | vi.useFakeTimers(); |
163 | 185 | process.env.NODE_ENV = "development"; |
|
| Original file line number | Diff line number | Diff line change |
|---|
|
1 | 1 | import { isTruthyEnvValue } from "../infra/env.js"; |
2 | | -import { |
3 | | -parseStrictNonNegativeInteger, |
4 | | -parseStrictPositiveInteger, |
5 | | -} from "../infra/parse-finite-number.js"; |
| 2 | +import { parseStrictPositiveInteger } from "../infra/parse-finite-number.js"; |
6 | 3 | import { pickPrimaryTailnetIPv4, pickPrimaryTailnetIPv6 } from "../infra/tailnet.js"; |
| 4 | +import { parseTcpPort } from "../infra/tcp-port.js"; |
7 | 5 | import { resolveWideAreaDiscoveryDomain, writeWideAreaGatewayZone } from "../infra/widearea-dns.js"; |
8 | 6 | import type { PluginGatewayDiscoveryServiceRegistration } from "../plugins/registry-types.js"; |
9 | 7 | import { |
@@ -55,12 +53,9 @@ export async function startGatewayDiscovery(params: {
|
55 | 53 | const tailnetDns = needsTailnetDns |
56 | 54 | ? await resolveTailnetDnsHint({ enabled: tailscaleEnabled }) |
57 | 55 | : undefined; |
58 | | -const sshPortEnv = mdnsMinimal ? undefined : process.env.OPENCLAW_SSH_PORT?.trim(); |
59 | | -const sshPortParsed = parseStrictNonNegativeInteger(sshPortEnv); |
60 | | -const sshPort = |
61 | | -sshPortParsed !== undefined && sshPortParsed > 0 && sshPortParsed <= 65535 |
62 | | - ? sshPortParsed |
63 | | - : undefined; |
| 56 | +const sshPort = mdnsMinimal |
| 57 | + ? undefined |
| 58 | + : (parseTcpPort(process.env.OPENCLAW_SSH_PORT) ?? undefined); |
64 | 59 | const cliPath = mdnsMinimal ? undefined : resolveBonjourCliPath(); |
65 | 60 | |
66 | 61 | if (localDiscoveryEnabled) { |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。