Skip to content

security: tighten configuration scope for SEC-200#965

Open
EhabY wants to merge 2 commits into
mainfrom
security/scope-hardening-sec-200
Open

security: tighten configuration scope for SEC-200#965
EhabY wants to merge 2 commits 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 "scope": "machine". VS Code itself drops workspace and folder values for machine-scoped settings, so the malicious workspace value never reaches our code. No runtime guard is needed.

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

Why machine and not window (the default)

VS Code's default scope is window, which means workspace and folder settings.json can override the user setting. That's precisely the SEC-200 attack vector. Any setting whose value can cause command execution, redirect network traffic, swap credentials, or substitute the CLI binary must not be controllable by a project file — only by the user who installed the extension.

Why machine and not application

Both application and machine block workspace/folder overrides, so both close SEC-200. The differences:

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

We pick machine because most of these settings are inherently machine-specific:

  • OS-dependent shell strings — a Windows cmd.exe /c … headerCommand would sync over to a Mac via Settings Sync (application) and silently break.
  • Filesystem pathsbinaryDestination, tlsCertFile, tlsKeyFile, tlsCaFile, proxyLogDirectory are absolute paths that differ per machine.
  • Network configproxyBypass, tlsAltHost depend on the local network environment.

machine keeps the security guarantee while letting per-machine values stay per-machine, including via VS Code's Remote SSH user-level settings.

Settings updated

Setting Scope Why it's sensitive
coder.headerCommand machine Runs an external shell command (SEC-200)
coder.tlsCertRefreshCommand machine Runs an external shell command (SEC-200)
coder.binarySource machine URL the Coder CLI is downloaded from
coder.binaryDestination machine Filesystem path of the executed CLI binary
coder.disableSignatureVerification machine Toggles CLI signature verification
coder.enableDownloads machine Force-enables downloads in restricted environments
coder.sshFlags machine SSH flags accept -o ProxyCommand=… (exec)
coder.globalFlags machine Flags applied to every CLI invocation
coder.tlsCertFile machine TLS client certificate path
coder.tlsKeyFile machine TLS client key path
coder.tlsCaFile machine TLS CA path (workspace-controlled CA → MITM)
coder.tlsAltHost machine Hostname override for TLS verification
coder.insecure machine Disables TLS host verification
coder.proxyLogDirectory machine Arbitrary write path
coder.proxyBypass machine Routes traffic around the proxy
coder.defaultUrl machine Default Coder deployment URL
coder.autologin machine Combined with defaultUrl could auto-login elsewhere
coder.useKeyring machine Credential-storage preference

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 having to merge everything sitting 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; it lands under ## Unreleased and will be folded into the next normal release.

Test plan

  • pnpm typecheck — clean
  • pnpm lint — clean
  • pnpm test — 1670 passed / 1 skipped, no regressions
  • Manual: open a workspace with a .vscode/settings.json setting coder.headerCommand; confirm VS Code reports it as unsettable at workspace scope and the value is ignored.

EhabY added 2 commits May 19, 2026 18:39
Mark security-sensitive settings as `scope: "machine"` so workspace and
folder `settings.json` can no longer override them. This closes 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.

Also drop the release-workflow gate that required tags to come from
`main` so a fix can be cut from a release branch.
- Bump `package.json` to 1.14.6 so `main` doesn't trail the v1.14.6
  tag cut from `release/v1.14.6`. Future work on main continues with
  v1.14.7+.
- Restore the `Verify tag is on main` step in the release workflow.
  The gate is correct for normal releases (cut from `main`); the
  release branch removes it locally because that branch is the
  exception.
- Move the Security entry from `## Unreleased` into a new `## [v1.14.6]`
  section so this branch's CHANGELOG converges with the release-branch
  CHANGELOG byte-for-byte once both PRs land.
@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

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