fix!: validate HostnameSuffix and SSHConfigOptions' (#26154)

- Adds server-side and client-side validation for
CODER_CONFIGSSH_HOSTNAME_SUFFIX and CODER_SSH_CONFIG_OPTIONS.
- **Server-side breaking change:** invalid values for either of these will cause `coderd` to exit with an error.
- Client-side: `coder config-ssh` will exit with an error if it detects invalid config.
- Adds tests for the above

Local smoke-testing: ran `develop.sh --env-file <path to an env file
containing badness>`. Validated that server startup failed as expected.

> 🤖 Generated by Coder Agents with supervision from a human.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Cian Johnston
2026-06-10 15:48:02 +01:00
committed by GitHub
co-authored by Copilot Autofix powered by AI
parent 1dc12f8ae7
commit a26c46a3bf
11 changed files with 681 additions and 39 deletions
+57
View File
@@ -168,6 +168,63 @@ func TestConfigSSH(t *testing.T) {
<-copyDone
}
func TestConfigSSH_RejectsUnsafeServerConfig(t *testing.T) {
t.Parallel()
if runtime.GOOS == "windows" {
t.Skip("See coder/internal#117")
}
testCases := []struct {
name string
configSSH codersdk.SSHConfigResponse
wantErr string
}{
{
name: "HostnameSuffix",
configSSH: codersdk.SSHConfigResponse{HostnameSuffix: "coder\nHost *"},
wantErr: "workspace hostname suffix",
},
{
name: "HostnamePrefix",
configSSH: codersdk.SSHConfigResponse{HostnamePrefix: "coder.\nHost *"},
wantErr: "workspace hostname prefix",
},
{
name: "HostnameSuffixGlob",
configSSH: codersdk.SSHConfigResponse{HostnameSuffix: "*"},
wantErr: "glob",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
const existingConfig = "Host safe\n\tHostName safe.example.com\n"
client := coderdtest.New(t, &coderdtest.Options{
ConfigSSH: tc.configSSH,
})
_ = coderdtest.CreateFirstUser(t, client)
sshConfigPath := sshConfigFileName(t)
sshConfigFileCreate(t, sshConfigPath, strings.NewReader(existingConfig))
inv, root := clitest.New(t,
"config-ssh",
"--ssh-config-file", sshConfigPath,
"--yes",
)
clitest.SetupConfig(t, client, root)
err := inv.Run()
require.Error(t, err)
require.ErrorContains(t, err, tc.wantErr)
require.Equal(t, existingConfig, sshConfigFileRead(t, sshConfigPath))
})
}
}
func TestConfigSSH_MissingDirectory(t *testing.T) {
t.Parallel()