From 3af7a181453992ee401a0e255eafb1ae53e7156f Mon Sep 17 00:00:00 2001 From: Kai Schwarz Date: Tue, 8 Sep 2026 16:55:12 +0200 Subject: [PATCH] ci(devcontainer): mount the history file, not the host home MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The frame mounted ${localEnv:HOME} at /WSL_USER to reach one file inside it, ~/.zsh_history, which post-create.sh symlinks into place. That granted the container read-write reach over the host's SSH keys, shell profiles and every other repository on the machine as a side effect of wanting one history file. In the workspace repository the same pattern made the readonly flag on its GitHub token directory decorative — the same inodes were writable by the second path, verified by inode before the fix. That is what makes this a fleet-wide change (RSRMID-3052) rather than a per-repository tidy-up. Bind the single file at the same path instead. post-create.sh is unchanged and still does the linking: this repository is **not** on the shared devbase Feature, so that script is what makes history persist here, and removing it would have silently ended history persistence rather than tidied anything. A single-file bind needs the host file to exist first, so initializeCommand touches it. Without that, Docker creates the missing source as a directory — on the host, where it outlives the container — and the symlink then points at a directory that zsh cannot write to. initializeCommand is the only place that can run before the container exists, which is why the touch cannot live in post-create.sh. Also drops the GitHub.copilot extension, deprecated for us since the team works with Claude; anthropic.claude-code stays. Unrelated to the mount change, kept in the same commit only because it edits the same few lines of the same file. --- .devcontainer/devcontainer.json | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 6199c45a..81090b2a 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -12,7 +12,6 @@ "extensions": [ "vscjava.vscode-java-pack", "eamodio.gitlens", - "GitHub.copilot", "anthropic.claude-code" ] } @@ -32,8 +31,19 @@ "--name", "rtldev-middleware-java-sdk" ], + // The bind below names a *file*, and Docker creates a missing bind source itself, + // as a directory — on the host, where it outlives the container. Without this + // touch, post-create.sh's symlink would point at a directory and zsh could not + // write a line of history. Runs on the host before the container is created, so + // it cannot live in post-create.sh. (RSRMID-3052) + "initializeCommand": "touch ${localEnv:HOME}/.zsh_history", + // Only the history file, never the host home. This used to mount ${localEnv:HOME} + // at /WSL_USER to reach that one file, which handed the container read-write reach + // over the host's SSH keys, credentials and every other repository on the machine. + // post-create.sh symlinks ~/.zsh_history to this path; this repository is not on + // the devbase Feature, so that script is what makes history persist here. "mounts": [ - "source=${localEnv:HOME}${localEnv:USERPROFILE},target=/WSL_USER,type=bind,consistency=cached" + "source=${localEnv:HOME}/.zsh_history,target=/WSL_USER/.zsh_history,type=bind,consistency=cached" ], "remoteUser": "vscode" } \ No newline at end of file