Skip to content

fix(vscode): stop leaking PII in remotePlatform, cut remote memory/CPU overhead - #773

Merged
ppat merged 2 commits into
mainfrom
fix/772-vscode-memory-settings
Aug 16, 2026
Merged

fix(vscode): stop leaking PII in remotePlatform, cut remote memory/CPU overhead#773
ppat merged 2 commits into
mainfrom
fix/772-vscode-memory-settings

Conversation

@ppat

@ppat ppat commented Aug 16, 2026

Copy link
Copy Markdown
Owner

Summary

Reduces VS Code's remote memory footprint (Phase 2 of the plan behind
ppat/coder#859's watchdog) and stops two personal identifiers from being
committed in plaintext.

  • extensions.autoUpdate was inverted against its own comment. The
    comment said "Prevent extensions from automatically updating" directly
    above "extensions.autoUpdate": true. This is what produced six
    concurrently-installed Claude Code extension versions on the remote.
    Fixed to "off" (the string value the current extensions.autoUpdate
    schema expects — VS Code's own configuration-migration code maps a
    legacy boolean false to "off" automatically, but setting the string
    directly avoids depending on that migration, including the in-place
    rewrite it would otherwise make to this chezmoi-managed file).
    extensions.autoCheckUpdates: false added alongside it.
  • files.watcherExclude/search.exclude extended to cover the
    remote home's ~11 GB ~/.vscode-server tree (previously watching
    itself), the Homebrew symlink farm, and mise's per-version toolchain
    store, plus .terraform, .cache, .cargo, go/pkg, .claude,
    target, vendor, .venv. search.followSymlinks: false added since
    the brew/mise trees are themselves symlink farms.
  • typescript.tsserver.maxTsServerMemory capped at 2048 MB and
    automatic type acquisition disabled — tsserver was otherwise unbounded.
  • Git extension's background repository scanning narrowed:
    git.autoRepositoryDetection: "openEditors", git.repositoryScanMaxDepth: 1,
    git.autofetch: false. Note: the last two already match current
    upstream VS Code defaults, so their practical effect depends on the
    installed VS Code version — kept for explicitness/robustness rather
    than because they're guaranteed to change behavior today.
  • remote.extensionKind added for vscode-icons-team.vscode-icons
    and bierner.markdown-mermaid, pushing them to the local (UI) extension
    host instead of the remote.

PII fix: remote.SSH.remotePlatform previously hardcoded the Coder
deployment's real domain and the operator's real username/workspace name
in plaintext, in this public repo. One of the two host-key entries does
not parse under the Coder VS Code extension's current SSH-authority
format (verified against coder/vscode-coder's src/util/authority.ts
on GitHub) and predates it — dropped rather than templated. The other is
templated: the domain now resolves through the same bitwardenSecrets
UUID this repo already uses for it elsewhere (private_dot_env.secrets.tmpl,
run_after_61_kubeconfig.sh.tmpl); the username/workspace segment is a
new coderUsername value prompted once via .chezmoi.toml.tmpl, the same
mechanism already used for name/email/bwsAccessToken. Git history
still contains the old plaintext values — this fixes it going forward
only.

Added private_dot_local/bash/limits.bash (auto-sourced by the
existing dot_bashrc loop over ~/.local/bash/): restores an unlimited
soft RLIMIT_DATA in every interactive shell. The memory watchdog
(ppat/coder#859) stamps a soft RLIMIT_DATA on the VS Code server process
tree; terminals forked from ptyHost inherit that limit, and the
watchdog leaves the hard limit at unlimited specifically so a shell can
restore itself.

Roo Code is untouched in remote.SSH.defaultExtensions — its removal
is blocked on the Mac-side backup in #770, which hasn't
happened yet.

Scope verification (VS Code source, not assumption)

Checked against microsoft/vscode's own configuration registrations
(extensions.contribution.ts, files.contribution.ts,
search.contribution.ts, remote.contribution.ts) and the git /
typescript-language-features bundled extensions' package.json:

Setting Scope Where it must live
extensions.autoUpdate, extensions.autoCheckUpdates APPLICATION User settings only — confirmed
remote.extensionKind WINDOW (not APPLICATION as originally assumed — see note below) User settings; still silently dropped by the remote Machine file since WINDOW isn't in [MACHINE, MACHINE_OVERRIDABLE]
files.watcherExclude, search.exclude RESOURCE User settings
search.followSymlinks, typescript.tsserver.maxTsServerMemory, typescript.disableAutomaticTypeAcquisition WINDOW User settings
git.autoRepositoryDetection WINDOW (unscoped in the manifest → registry default) User settings
git.autofetch, git.repositoryScanMaxDepth RESOURCE User settings

All of the above land in the Mac user settings file
(private_Library/private_Application Support/private_Code/User/settings.json.tmpl)
for the same reason: in a Remote-SSH window, User settings come from the
client and apply to the remote window for every scope except
MACHINE/MACHINE_OVERRIDABLE. The remote Machine settings file
(private_dot_vscode-server/data/Machine/settings.json) is untouched —
its existing entries (mise.binPath, shellcheck.executablePath,
git.defaultCloneDirectory) are genuinely machine-scoped.

One incidental finding, not fixed here since it's outside this task's
scope: that Machine settings file also already contains git.pruneOnFetch,
which is RESOURCE-scoped, not MACHINE/MACHINE_OVERRIDABLE — it's
likely already silently inert in that file today. Worth a follow-up.

What still needs the owner to confirm

This branch could not be applied on the current machine (chezmoi apply/chezmoi update are off-limits here — it's a shared live
workspace) or on the Mac. Verification here was chezmoi execute-template
against a scratch config seeded with fake values (mirroring exactly what
CI's full-apply-test.yaml does), plus reviewing the rendered JSON by
hand. chezmoi diff itself could not be exercised at all on this
machine — its local bwsAccessToken is already being rejected by the
Bitwarden Secrets Manager API for an unrelated, pre-existing reason.

After merging, every machine needs one chezmoi init re-run (Mac
included) before its next chezmoi apply/chezmoi update: the new
coderUsername prompt is only asked by chezmoi init, and until it's
answered once, this file fails to render with a hard template error
(map has no entry for key "coderUsername"), which would otherwise abort
the whole apply. promptStringOnce means this is asked exactly once, same
as the existing name/email/bwsAccessToken prompts.

Once applied, the owner should open Settings UI in a reconnected remote
window and confirm each new setting shows the right value and the right
provenance (User vs Remote)
— that's the only real proof a setting isn't
silently inert, and it can't be checked from here.

Test plan

  • pre-commit run --all-files passes
  • shellcheck --rcfile .shellcheckrc private_dot_local/bash/limits.bash clean
  • chezmoi execute-template renders the changed template cleanly with
    CI's exact fake-value substitution (fake-test-value for
    bitwardenSecrets, fake coderUsername)
  • Rendered output is valid JSON after stripping // comments and
    trailing commas (same JSONC shape as the file already had)
  • Owner: chezmoi init once per machine, then chezmoi diff/apply
  • Owner: confirm each setting's value and provenance in the Settings UI
    after reconnecting to the remote
  • Owner: compare fileWatcher/ext-host RSS before and after ~30 min of
    normal work

Ref: #772

ppat and others added 2 commits August 16, 2026 20:20
…form

extensions.autoUpdate was inverted against its own comment (APPLICATION
scope, verified against microsoft/vscode's extensions.contribution.ts) --
this produced six concurrently-installed Claude Code extension versions on
the remote. Extends files.watcherExclude/search.exclude to cover the
~11 GB ~/.vscode-server tree, the brew symlink farm and mise's toolchain
store, caps tsserver memory, and narrows the git extension's background
repository scanning -- all confirmed RESOURCE/WINDOW scope, so they load
from this file (VS Code Remote reads User settings from the client for
every scope except MACHINE/MACHINE_OVERRIDABLE).

remote.SSH.remotePlatform previously hardcoded the deployment's real
domain and username in plaintext. One of the two host-key entries doesn't
parse under the Coder VS Code extension's current SSH authority format
(coder/vscode-coder's src/util/authority.ts) and predates it, so it's
dropped; the other is templated using the domain's existing bitwardenSecrets
UUID (already used elsewhere in this repo) plus a new coderUsername prompt.

Adds private_dot_local/bash/limits.bash to restore an unlimited soft
RLIMIT_DATA in every interactive shell, for ppat/coder#859's watchdog,
which stamps that limit on the VS Code server tree and relies on
inheriting terminals restoring themselves.

Roo Code stays in remote.SSH.defaultExtensions -- its removal is blocked
on the Mac-side backup in #770.

Ref: #772

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…args

grep -rl | xargs (no -Z/-0) word-splits on spaces in paths. This repo's
own private_Application Support tree has one, and the previous commit
added the first *.tmpl file under it -- full-apply-test's "Fake out
bitwardenSecrets calls" step failed immediately once that path was
actually matched by --include='*.tmpl'.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ppat
ppat merged commit b58cd21 into main Aug 16, 2026
9 checks passed
@ppat
ppat deleted the fix/772-vscode-memory-settings branch August 16, 2026 23:04
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.

1 participant