Skip to content

security: tighten configuration scope for SEC-200#965

Open
EhabY wants to merge 1 commit into
mainfrom
security/scope-hardening-sec-200
Open

security: tighten configuration scope for SEC-200#965
EhabY wants to merge 1 commit into
mainfrom
security/scope-hardening-sec-200

Conversation

@EhabY
Copy link
Copy Markdown
Collaborator

@EhabY EhabY commented May 19, 2026

Summary

Closes the SEC-200 attack path where a malicious .vscode/settings.json could override security-sensitive Coder settings — most notably the two command-execution settings (coder.headerCommand, coder.tlsCertRefreshCommand) called out in the original report.

The fix is metadata-only: each affected setting gets a scope of application or machine. VS Code drops workspace and folder values for both scopes, so a malicious workspace value never reaches our code. No runtime guard needed.

Also relaxes the release workflow so a fix can be cut from a release branch (paired with release/v1.14.6 off v1.14.5).

Why not window (the default)

VS Code's default scope is window, which lets workspace and folder settings.json override the user setting — exactly the SEC-200 vector. Any setting that can cause command execution, redirect network traffic, swap credentials, or substitute the CLI binary must not be controllable by a project file.

application vs machine

Both block workspace/folder overrides, so both close SEC-200. They differ in Settings Sync behavior:

Scope Settable in Synced via Settings Sync?
application User settings only Yes
machine User OR per-machine remote settings No

We split by what the setting actually represents:

  • application — user-wide preferences with no OS or filesystem coupling. Safe (and desirable) to sync across machines.
  • machine — paths, shell commands, and network config that are inherently per-machine. A Windows cmd.exe /c … headerCommand syncing to a Mac would silently break; absolute paths like tlsCaFile don't translate.

This follows VS Code's recommended scope semantics.

Settings updated

application (synced, user-wide preferences):

Setting Why it's sensitive
coder.insecure Disables TLS host verification
coder.disableSignatureVerification Toggles CLI signature verification
coder.enableDownloads Force-enables downloads in restricted environments
coder.defaultUrl Default Coder deployment URL
coder.autologin Combined with defaultUrl could auto-login elsewhere
coder.useKeyring Credential-storage preference

machine (per-machine, not synced):

Setting Why it's sensitive
coder.headerCommand Runs an external shell command (SEC-200)
coder.tlsCertRefreshCommand Runs an external shell command (SEC-200)
coder.binarySource URL the Coder CLI is downloaded from
coder.binaryDestination Filesystem path of the executed CLI binary
coder.sshFlags SSH flags accept -o ProxyCommand=… (exec)
coder.globalFlags Flags applied to every CLI invocation
coder.tlsCertFile TLS client certificate path
coder.tlsKeyFile TLS client key path
coder.tlsCaFile TLS CA path (workspace-controlled CA → MITM)
coder.tlsAltHost Hostname override for TLS verification
coder.proxyLogDirectory Arbitrary write path
coder.proxyBypass Routes traffic around the proxy

Already machine: coder.sshConfig.

Settings deliberately left workspace-overridable (no security risk, project-local override is legitimate): coder.networkThreshold.latencyMs, coder.httpClientLogLevel, coder.disableNotifications, coder.disableUpdateNotifications, coder.experimental.oauth, coder.telemetry.level, coder.telemetry.local.

CI change

Drops the Verify tag is on main step from .github/workflows/release.yaml so a security fix can be cut from a release branch (e.g. release/v1.14.6 off v1.14.5) without first merging everything on main.

Companion PR

A second PR cuts the same fix as v1.14.6 off the v1.14.5 tag for users on the stable channel. This PR delivers the change on main.

@EhabY EhabY self-assigned this May 19, 2026
@EhabY EhabY requested a review from jdomeracki-coder May 19, 2026 15:54
@jdomeracki-coder
Copy link
Copy Markdown
Contributor

Does the job security wise ✅
I think a UX focused validation is warranted as well

cc: @matifali, @zenithwolf1000

@EhabY
Copy link
Copy Markdown
Collaborator Author

EhabY commented May 20, 2026

Currently those 18 settings have been moved from window to machine but there are 6 settings that can be moved into the application scope so they could be synced:

  • coder.defaultUrl — preferred Coder deployment URL
  • coder.autologin — boolean preference
  • coder.useKeyring — credential-storage preference
  • coder.insecure — TLS verification preference
  • coder.disableSignatureVerification — signature-check preference
  • coder.enableDownloads — download-toggle preference

Does it make sense to move these into the application scope since it's a better fit (not OS-specific nor per-machine) and can be synced?

@EhabY
Copy link
Copy Markdown
Collaborator Author

EhabY commented May 20, 2026

Fair but a lot of these settings are applied prior to establishing an SSH connection and thus it'd be very difficult to set them on the remote machine workspace and have it work consistently

Mark security-sensitive settings so workspace and folder `settings.json`
can no longer override them. VS Code itself drops workspace/folder values
for these settings, closing a path where a malicious workspace could
redirect command execution (`coder.headerCommand`,
`coder.tlsCertRefreshCommand`), swap the CLI binary or its source, inject
CLI/SSH flags, substitute TLS material, or override identity and
credential-storage settings.

Path-, command-, and network-dependent settings use `scope: machine`
(per-machine, not synced via Settings Sync). User-wide preferences
(`coder.defaultUrl`, `coder.autologin`, `coder.useKeyring`,
`coder.insecure`, `coder.disableSignatureVerification`,
`coder.enableDownloads`) use `scope: application`, which preserves
Settings Sync across machines while still blocking workspace overrides.

Bumps to 1.14.6 to match the v1.14.6 tag cut from `release/v1.14.6`.
@EhabY EhabY force-pushed the security/scope-hardening-sec-200 branch from 3d3a976 to 4112657 Compare May 21, 2026 10:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants