fix(bonjour): harden DNS label truncation

This commit is contained in:
Vincent Koc
2026-04-27 11:50:42 -07:00
committed by Peter Steinberger
parent 9ac0b7edbc
commit 16322d5cfc
2 changed files with 10 additions and 3 deletions

View File

@@ -736,7 +736,7 @@ describe("gateway bonjour advertiser", () => {
});
it("truncates service name exceeding 63-byte DNS label limit", async () => {
const longHostname = "app-41627eae5842473f9e05f139ea307277-7f9477f4d6-lqqzf";
const longHostname = "app-41627eae5842473f9e05f139ea307277-7f9477f4d6-lqqzf-abcdefghi";
enableAdvertiserUnitMode(longHostname);
const destroy = vi.fn().mockResolvedValue(undefined);
@@ -755,6 +755,7 @@ describe("gateway bonjour advertiser", () => {
// Both name and hostname must be within the 63-byte DNS label limit
expect(new TextEncoder().encode(serviceName).byteLength).toBeLessThanOrEqual(63);
expect(new TextEncoder().encode(hostname).byteLength).toBeLessThanOrEqual(63);
expect(hostname).not.toMatch(/-$/);
await started.stop();
});

View File

@@ -185,7 +185,7 @@ function resolveSystemMdnsHostname(): string | null {
const MAX_DNS_LABEL_BYTES = 63;
function truncateToDnsLabel(name: string): string {
function truncateToDnsLabel(name: string, fallback = "OpenClaw"): string {
const encoder = new TextEncoder();
const encoded = encoder.encode(name);
if (encoded.byteLength <= MAX_DNS_LABEL_BYTES) {
@@ -195,7 +195,12 @@ function truncateToDnsLabel(name: string): string {
const truncated = encoded.slice(0, MAX_DNS_LABEL_BYTES);
const decoded = new TextDecoder("utf-8", { fatal: false }).decode(truncated);
// Strip any replacement character from incomplete multi-byte sequence at the end
return decoded.replace(/\uFFFD$/, "").trim() || "OpenClaw";
return (
decoded
.replace(/\uFFFD$/, "")
.replace(/-+$/, "")
.trim() || fallback
);
}
function safeServiceName(name: string) {
@@ -373,6 +378,7 @@ export async function startGatewayBonjourAdvertiser(
.replace(/\.local$/i, "")
.split(".")[0]
.trim() || "openclaw",
"openclaw",
);
const instanceName =
typeof opts.instanceName === "string" && opts.instanceName.trim()