Skip to content

fix: devcontainer obj/ files owned by root break incremental builds#534

Merged
joshsmithxrm merged 4 commits intomainfrom
fix/devcontainer-obj-ownership
Feb 12, 2026
Merged

fix: devcontainer obj/ files owned by root break incremental builds#534
joshsmithxrm merged 4 commits intomainfrom
fix/devcontainer-obj-ownership

Conversation

@joshsmithxrm
Copy link
Owner

Summary

  • postCreateCommand runs dotnet restore as root in some devcontainer CLI versions, creating obj/ directories owned by root:root
  • MSBuild's incremental build fails with MSB3374 because utimensat() requires file ownership to set timestamps — 777 permissions aren't sufficient
  • Adds explicit remoteUser: vscode to devcontainer.json and a chown safety net in setup.sh after dotnet restore

Test plan

  • Run dev reset to rebuild the container from scratch
  • Run dev ppds on main repo — verify build succeeds
  • Run dev ppds on a worktree — verify build succeeds
  • Verify ls -la src/PPDS.Cli/obj/Debug/net10.0/ shows vscode:vscode ownership

🤖 Generated with Claude Code

postCreateCommand runs dotnet restore as root in some devcontainer CLI
versions, creating obj/ directories owned by root:root. MSBuild's
incremental build then fails with MSB3374 because utimensat() requires
file ownership to set timestamps — 777 permissions aren't sufficient.

Fix: explicitly set remoteUser to vscode and add a chown safety net
in setup.sh after dotnet restore.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gemini-code-assist
Copy link

Summary of Changes

Hello @joshsmithxrm, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical issue in the devcontainer setup where dotnet restore could create build artifacts with incorrect root ownership, leading to incremental build failures. By explicitly setting the remote user and adding a robust ownership correction step, the changes ensure a consistent and functional development environment, improving build reliability and developer experience.

Highlights

  • Devcontainer User Configuration: Explicitly configured the remoteUser to vscode in devcontainer.json to ensure that commands within the devcontainer run under the intended user, preventing root-owned file creation.
  • File Ownership Safety Net: Implemented a conditional chown command in setup.sh to automatically correct file ownership to vscode:vscode if the postCreateCommand runs as root, specifically targeting obj/ directories created by dotnet restore.
  • Incremental Build Fix: Resolved MSB3374 errors that occurred during incremental builds by addressing the root cause of obj/ files being owned by root:root, which prevented MSBuild from setting timestamps due to utimensat() requiring file ownership.
Changelog
  • .devcontainer/devcontainer.json
    • Added "remoteUser": "vscode" to ensure commands run as the vscode user.
  • .devcontainer/setup.sh
    • Introduced a conditional chown -R 1000:1000 "$(pwd)" command to fix workspace ownership if the script is executed as root.
    • Added comments explaining the purpose of the ownership fix related to dotnet restore and utimensat().
Activity
  • The pull request was created by joshsmithxrm to fix devcontainer build issues related to file ownership.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses an issue with file ownership in the dev container that breaks incremental builds. The fix involves explicitly setting the remoteUser in devcontainer.json and adding a safety net in setup.sh to correct file permissions if the script runs as root. The changes are logical and well-explained. I have one suggestion to improve the robustness of the shell script by using the username vscode instead of a hardcoded UID/GID.

New `rebase` command rebases a feature branch onto origin/main:
- Syncs origin refs first (reuses bundle mechanism)
- Launches Claude Code for conflict resolution if rebase fails
- Guards against running on main (use `sync` instead)

Simplified `push` divergence handling:
- Removed auto-rebase-onto-origin/branch + Claude logic from push
- Replaced with force-with-lease when history diverged (e.g., after rebase)
- Uses remoteSha from ls-remote as the expected lease value

Also addresses review feedback: use vscode:vscode instead of 1000:1000
in setup.sh chown for robustness across image versions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@joshsmithxrm
Copy link
Owner Author

@gemini-code-assist review

@joshsmithxrm
Copy link
Owner Author

Addressed in 978a40e — using vscode:vscode now. Good catch.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request addresses an important issue with file ownership in the devcontainer, which can break incremental builds. The scripts/devcontainer.ps1 introduces several instances where the $workdir variable is unsafely concatenated into bash command strings. While in this local development context, with $workdir derived from trusted sources like git worktree names, the risk is primarily related to shell injection from unescaped special characters rather than a high-severity command injection by an attacker, it is still important to address. It is recommended to use positional arguments with bash -c to safely pass variables and prevent unexpected command execution. The file ownership fix in .devcontainer/devcontainer.json and .devcontainer/setup.sh is robust, and the push command simplification (using force-with-lease) is a positive improvement. Future pull requests should ideally separate unrelated changes to streamline the review process.

Replace string interpolation of $workdir (and other variables) in
bash -c commands with positional arguments via -- $arg. This prevents
shell metacharacter injection from directory/branch names.

Converts all 13 call sites to use 'cd "$1" && ...' -- $workdir
pattern, verified working through the PowerShell → devcontainer exec
→ docker exec → bash argument chain.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@joshsmithxrm
Copy link
Owner Author

Addressed the shell injection feedback across all 13 call sites in 36baafc. Converted all \ to \ using positional args. Verified the \ pattern passes through the PowerShell → devcontainer exec → docker exec → bash chain correctly.

@joshsmithxrm
Copy link
Owner Author

@gemini-code-assist review

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses an issue with file ownership in the devcontainer that was breaking incremental builds. While it successfully hardens scripts/devcontainer.ps1 against command injection vulnerabilities by using parameterized arguments, a new security concern was identified. The recursive chown operation in .devcontainer/setup.sh could be exploited via malicious symbolic links to change the ownership of sensitive system files. Additionally, scripts/devcontainer.ps1 has been refactored to include a new rebase command and a safer push command. I have provided specific feedback regarding the chown vulnerability and a minor suggestion for consistency in the new rebase command.

setup.sh: use -h (no symlink follow) and --from=root (only fix
root-owned files from dotnet restore, skip vscode-owned files).

devcontainer.ps1: run git log in workdir context for consistency
with all other devcontainer exec calls in the rebase block.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@joshsmithxrm joshsmithxrm merged commit 0b78146 into main Feb 12, 2026
9 checks passed
@joshsmithxrm joshsmithxrm deleted the fix/devcontainer-obj-ownership branch February 12, 2026 08:28
@github-project-automation github-project-automation bot moved this from Todo to Done in PPDS Roadmap Feb 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant

Comments