fix(provider): use init-files for gh config to fix .config ownership#224
Conversation
Docker creates missing parent directories as root when setting up bind mounts. The GitHub provider's bind mount to ~/.config/gh caused ~/.config to be owned by root, breaking any CLI that needed to write config files inside the container. Switch from ContainerMounts to ContainerInitFiles (matching the pattern used by the Graphite provider). The config is passed via MOAT_INIT_FILES env var and written by moat-init.sh, which properly chowns to moatuser. Additional improvements: - Sanitize gh config to strip embedded credentials (hosts, oauth_token) that may be present with --insecure-storage or older gh versions - Pre-create ~/.config in Dockerfile with correct ownership - Unset MOAT_INIT_FILES after processing to avoid leaking to agent
📦 Previous Review (superseded by newer review)Claude finished @dpup's task in 2m 17s —— View job Code Review
The fix is well-reasoned and consistent with the Graphite provider pattern. Root cause is correctly identified and the defense-in-depth ( Issues1. Silent error swallowing in
sanitized, err := sanitizeGhConfig(content)
if err != nil || sanitized == nil {
return nil
}If the user's 2. YAML round-trip removes comments and reorders keys — not documented
Minor observations3. No test for invalid YAML input
4. The stub at What's good
The core fix is correct and ready to merge. Issues #1 and #2 are low-severity but would improve debuggability. |
Address review feedback: - Log sanitization errors at debug level for --verbose diagnostics - Document that YAML round-trip strips comments and reorders keys - Add test case for invalid YAML input
📦 Previous Review (superseded by newer review)Claude finished @dpup's task in 2m 31s —— View job Code Review
The issues raised in the previous review are resolved: Issues1.
dir=$(dirname "$filepath")
mkdir -p "$dir" && chmod 755 "$dir"If both 2.
proxyEnv = append(proxyEnv, "MOAT_INIT_FILES="+buf.String())The sanitization correctly removes credentials from the YAML before this point, so actual tokens don't leak. But non-sensitive gh preferences (aliases, editor choice, etc.) do appear in Minor observations3. 4. What's good
The core fix is correct and the previous review's issues are addressed. Issue #1 above is low severity and not a current bug. Ready to merge. |
|
Claude finished @dpup's task in 3m 38s —— View job Code Review
The previous two review passes addressed all issues raised (debug log on sanitization failure, YAML round-trip caveat in doc comment, invalid YAML test case). This pass focuses on anything not yet flagged. Remaining open item from review #2 (not addressed)
dir=$(dirname "$filepath")
mkdir -p "$dir" && chmod 755 "$dir"If New observations1.
2. If the input YAML is 3. if tt.wantNil {
if result != nil {
t.Errorf(...)
}
return // doesn't check err
}The "invalid yaml" case returns 4. The 5.
What's good
Issues #5 (silent read error) is the only new actionable finding. Issues are all low-severity; the fix is correct and ready to merge. |
Summary
root:rootwhen setting up bind mounts. The GitHub provider's bind mount to~/.config/ghcaused~/.configto be owned by root, breaking any CLI that needed to write config files inside the container.ContainerMounts(bind mount) toContainerInitFiles(matching the Graphite provider pattern). Config is passed viaMOAT_INIT_FILESenv var and written bymoat-init.shwith correct ownership.hosts,oauth_token) before passing to container. UnsetMOAT_INIT_FILESenv var after processing.~/.configin the Dockerfile with correct moatuser ownership.Test plan
go test -race ./internal/providers/github/— all tests passgo test -race ./internal/deps/— all relevant tests pass (pre-existing GitHub URL 401s unrelated)make lint— 0 issuesmoat run --grant github— verifyls -la /home/moatuser/shows.configowned by moatuserghCLI works inside container (aliases, preferences preserved)~/.config/succeeds inside the container🤖 Generated with Claude Code