From 2f9f9892b240eb3d576aec9a432e00181896a862 Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Mon, 2 Jun 2025 21:21:52 +0000 Subject: [PATCH 1/3] fix: specify `--header-command` when running `coder start` --- src/api.ts | 2 ++ src/headers.ts | 22 ++++++++++++++++++++-- src/remote.ts | 30 ++++++++---------------------- src/util.ts | 4 ++++ 4 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/api.ts b/src/api.ts index fdb83b81..d741b60f 100644 --- a/src/api.ts +++ b/src/api.ts @@ -9,6 +9,7 @@ import * as vscode from "vscode" import * as ws from "ws" import { errToStr } from "./api-helper" import { CertificateError } from "./error" +import { getHeaderArgs } from "./headers" import { getProxyForUrl } from "./proxy" import { Storage } from "./storage" import { expandPath } from "./util" @@ -168,6 +169,7 @@ export async function startWorkspaceIfStoppedOrFailed( const startArgs = [ "--global-config", globalConfigDir, + ...getHeaderArgs(vscode.workspace.getConfiguration()), "start", "--yes", workspace.owner_name + "/" + workspace.name, diff --git a/src/headers.ts b/src/headers.ts index e870a557..2e23a18f 100644 --- a/src/headers.ts +++ b/src/headers.ts @@ -1,7 +1,8 @@ import * as cp from "child_process" +import * as os from "os" import * as util from "util" - -import { WorkspaceConfiguration } from "vscode" +import type { WorkspaceConfiguration } from "vscode" +import { escapeCommandArg } from "./util" export interface Logger { writeToCoderOutputChannel(message: string): void @@ -25,6 +26,23 @@ export function getHeaderCommand(config: WorkspaceConfiguration): string | undef return cmd } +export function getHeaderArgs(config: WorkspaceConfiguration): string[] { + // Escape a command line to be executed by the Coder binary, so ssh doesn't substitute variables. + const escapeSubcommand: (str: string) => string = + os.platform() === "win32" + ? // On Windows variables are %VAR%, and we need to use double quotes. + (str) => escapeCommandArg(str).replace(/%/g, "%%") + : // On *nix we can use single quotes to escape $VARS. + // Note single quotes cannot be escaped inside single quotes. + (str) => `'${str.replace(/'/g, "'\\''")}'` + + const command = getHeaderCommand(config) + if (!command) { + return [] + } + return ["--header-command", escapeSubcommand(command)] +} + // TODO: getHeaders might make more sense to directly implement on Storage // but it is difficult to test Storage right now since we use vitest instead of // the standard extension testing framework which would give us access to vscode diff --git a/src/remote.ts b/src/remote.ts index 5b8a9694..655e7bd8 100644 --- a/src/remote.ts +++ b/src/remote.ts @@ -14,12 +14,12 @@ import { extractAgents } from "./api-helper" import * as cli from "./cliManager" import { Commands } from "./commands" import { featureSetForVersion, FeatureSet } from "./featureSet" -import { getHeaderCommand } from "./headers" +import { getHeaderArgs } from "./headers" import { Inbox } from "./inbox" import { SSHConfig, SSHValues, mergeSSHConfigValues } from "./sshConfig" import { computeSSHProperties, sshSupportsSetEnv } from "./sshSupport" import { Storage } from "./storage" -import { AuthorityPrefix, expandPath, parseRemoteAuthority } from "./util" +import { AuthorityPrefix, escapeCommandArg, expandPath, parseRemoteAuthority } from "./util" import { WorkspaceMonitor } from "./workspaceMonitor" export interface RemoteDetails extends vscode.Disposable { @@ -611,32 +611,18 @@ export class Remote { const sshConfig = new SSHConfig(sshConfigFile) await sshConfig.load() - const escape = (str: string): string => `"${str.replace(/"/g, '\\"')}"` - // Escape a command line to be executed by the Coder binary, so ssh doesn't substitute variables. - const escapeSubcommand: (str: string) => string = - os.platform() === "win32" - ? // On Windows variables are %VAR%, and we need to use double quotes. - (str) => escape(str).replace(/%/g, "%%") - : // On *nix we can use single quotes to escape $VARS. - // Note single quotes cannot be escaped inside single quotes. - (str) => `'${str.replace(/'/g, "'\\''")}'` - - // Add headers from the header command. - let headerArg = "" - const headerCommand = getHeaderCommand(vscode.workspace.getConfiguration()) - if (typeof headerCommand === "string" && headerCommand.trim().length > 0) { - headerArg = ` --header-command ${escapeSubcommand(headerCommand)}` - } + const headerArgs = getHeaderArgs(vscode.workspace.getConfiguration()) + const headerArgList = headerArgs.length > 0 ? ` ${headerArgs.join(" ")}` : "" const hostPrefix = label ? `${AuthorityPrefix}.${label}--` : `${AuthorityPrefix}--` const proxyCommand = featureSet.wildcardSSH - ? `${escape(binaryPath)}${headerArg} --global-config ${escape( + ? `${escapeCommandArg(binaryPath)}${headerArgList} --global-config ${escapeCommandArg( path.dirname(this.storage.getSessionTokenPath(label)), - )} ssh --stdio --usage-app=vscode --disable-autostart --network-info-dir ${escape(this.storage.getNetworkInfoPath())}${await this.formatLogArg(logDir)} --ssh-host-prefix ${hostPrefix} %h` - : `${escape(binaryPath)}${headerArg} vscodessh --network-info-dir ${escape( + )} ssh --stdio --usage-app=vscode --disable-autostart --network-info-dir ${escapeCommandArg(this.storage.getNetworkInfoPath())}${await this.formatLogArg(logDir)} --ssh-host-prefix ${hostPrefix} %h` + : `${escapeCommandArg(binaryPath)}${headerArgList} vscodessh --network-info-dir ${escapeCommandArg( this.storage.getNetworkInfoPath(), - )}${await this.formatLogArg(logDir)} --session-token-file ${escape(this.storage.getSessionTokenPath(label))} --url-file ${escape( + )}${await this.formatLogArg(logDir)} --session-token-file ${escapeCommandArg(this.storage.getSessionTokenPath(label))} --url-file ${escapeCommandArg( this.storage.getUrlPath(label), )} %h` diff --git a/src/util.ts b/src/util.ts index 8253f152..8544e65a 100644 --- a/src/util.ts +++ b/src/util.ts @@ -93,3 +93,7 @@ export function expandPath(input: string): string { const userHome = os.homedir() return input.replace(/\${userHome}/g, userHome) } + +export function escapeCommandArg(arg: string): string { + return `"${arg.replace(/"/g, '\\"')}"` +} From ddcedb71bd49a50e0d15514f32112695e5a6bb3d Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Tue, 3 Jun 2025 17:39:01 +0000 Subject: [PATCH 2/3] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42bd5706..a0468a8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ - Multiple open instances of the extension could potentially clobber writes to `~/.ssh/config`. Updates to this file are now atomic. - Add support for `anysphere.remote-ssh` Remote SSH extension. +- Use `--header-command` properly when starting a workspace. ## [v1.9.0](https://github.com/coder/vscode-coder/releases/tag/v1.9.0) 2025-05-15 From 384cb15abd249ccf71009bb9a4926ecf5d5614fe Mon Sep 17 00:00:00 2001 From: McKayla Washburn Date: Tue, 3 Jun 2025 21:07:20 +0000 Subject: [PATCH 3/3] whoops --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0468a8a..e9bb3472 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Fixed + +- Use `--header-command` properly when starting a workspace. + ## [v1.9.1](https://github.com/coder/vscode-coder/releases/tag/v1.9.1) 2025-05-27 ### Fixed @@ -12,7 +16,6 @@ - Multiple open instances of the extension could potentially clobber writes to `~/.ssh/config`. Updates to this file are now atomic. - Add support for `anysphere.remote-ssh` Remote SSH extension. -- Use `--header-command` properly when starting a workspace. ## [v1.9.0](https://github.com/coder/vscode-coder/releases/tag/v1.9.0) 2025-05-15 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy