From a8b31b82a35a442a48355f8619f9eb8fe3ffe77a Mon Sep 17 00:00:00 2001 From: ntoofu Date: Tue, 7 Apr 2026 01:35:49 +0000 Subject: [PATCH] feat: enhance parseRemoteAuthority to handle domains containing "--" --- src/util.ts | 24 ++++++++++++++++++++---- test/unit/util.test.ts | 11 +++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/util.ts b/src/util.ts index f9aa549d..b8223d0d 100644 --- a/src/util.ts +++ b/src/util.ts @@ -61,15 +61,31 @@ export function parseRemoteAuthority(authority: string): AuthorityParts | null { // coder-vscode(--|.)--(--|.) // The agent can be omitted; the user will be prompted for it instead. // Anything else is unrelated to Coder and can be ignored. - const parts = authorityParts[1].split("--"); + const rawParts = authorityParts[1].split("--"); if ( - parts.length <= 1 || - (parts[0] !== AuthorityPrefix && - !parts[0].startsWith(`${AuthorityPrefix}.`)) + rawParts.length <= 1 || + (rawParts[0] !== AuthorityPrefix && + !rawParts[0].startsWith(`${AuthorityPrefix}.`)) ) { return null; } + // DNS labels may legally contain "--" (Punycode labels like "xn--{encoded}" + // are a common example), which breaks a naive split. Coder usernames and + // workspace names follow a slug pattern that never contains dots, so a + // dot-bearing segment after splitting on "--" must be a hostname fragment + // rather than a username. We reassemble from the front: while the next + // segment contains a dot, merge it back into the accumulated prefix. + let reassemblingParts = rawParts; + while (reassemblingParts.length >= 2) { + if (reassemblingParts[1].includes(".")) { + reassemblingParts = [reassemblingParts.slice(0, 2).join("--"), ...reassemblingParts.slice(2)]; + } else { + break; + } + } + const parts = reassemblingParts; + // It has the proper prefix, so this is probably a Coder host name. // Validate the SSH host name. Including the prefix, we expect at least // three parts, or four if including the agent. diff --git a/test/unit/util.test.ts b/test/unit/util.test.ts index 8e07e145..bd6f7275 100644 --- a/test/unit/util.test.ts +++ b/test/unit/util.test.ts @@ -91,6 +91,17 @@ describe("parseRemoteAuthority", () => { username: "foo", workspace: "bar", }); + expect( + parseRemoteAuthority( + "vscode://ssh-remote+coder-vscode.dev.coder.xn--eckwd4c7cu47r2wf.jp--foo--bar", + ), + ).toStrictEqual({ + agent: "", + sshHost: "coder-vscode.dev.coder.xn--eckwd4c7cu47r2wf.jp--foo--bar", + safeHostname: "dev.coder.xn--eckwd4c7cu47r2wf.jp", + username: "foo", + workspace: "bar", + }); }); });