fix: close temp file before git reads it and handle Windows pipe/scanner errors - #355
Open
awdemos wants to merge 5 commits into
Open
fix: close temp file before git reads it and handle Windows pipe/scanner errors#355awdemos wants to merge 5 commits into
awdemos wants to merge 5 commits into
Conversation
Explicitly close and check the temporary state file after writing but before passing its path to git notes. The previous deferred close happened after the git command ran, which can fail on Windows (open handle prevents git from reading the file) and masks write/close errors. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Check errors from scanner.Err() and os.Stdout.Write(), and close pipe ends cleanly after reading. Previously these errors were silently discarded, which could truncate output or leave pipe handles open on Windows without reporting failure to the caller. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add validateGitRefComponent to reject ref/branch names that start with '-' or contain unsafe characters before passing them to git commands. Apply validation in Checkout, Merge, Apply, and initializeWorktree to prevent argument injection. Also reject absolute paths and '..' traversal in exportEnvironmentFile so that agent-provided target_file cannot escape the environment worktree on the host filesystem. Regression tests included for ref validation and path traversal classification.
Reject unsupported shell strings before building container exec args. This prevents a caller from passing an arbitrary executable path as the shell interpreter (e.g. '/bin/echo') in environment_run_cmd. Regression test included.
Change the default debug stderr log file mode from 0644 to 0600 so that other users on the same host cannot read potentially sensitive command output or environment metadata.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR fixes
A focused bug-fix sweep of the repository, with an emphasis on security-validated inputs and safe resource handling. All changes are small, backwards-compatible fixes with regression tests where appropriate.
1.
repository/git.go: temporary state file not closed beforegit notesreads itProblem:
saveState()created a temp file, deferredf.Close(), wrote the serialized state into it, and then passed the file path togit notes --ref container-use-state add -F <file>inside a lock. Because the file was still open when git was invoked, the close could race the git read. On Windows this is especially problematic because an open file handle prevents another process from reading the file. It also meant any write/close error was masked until function exit.Fix: Close the temp file explicitly (and check the error) immediately after writing and before invoking git. The deferred close remains as a safety net for error paths.
2.
cmd/container-use/watch_windows.go: ignored errors inrunGitLogWindows()Problem: The Windows-specific
watchcommand pipedgit logoutput into a buffer and then wrote it to stdout, but it ignoredscanner.Err(), ignored the return value ofos.Stdout.Write(), and manually closed pipes whencmd.Start()failed without handling close errors.Fix: Check
scanner.Err()andos.Stdout.Write()errors, and return them to the caller. Handle pipe close errors cleanly; best-effort cleanup oncmd.Start()failure is annotated with//nolint:errcheck.3.
repository/git.go/repository/repository.go: git argument injection and path traversal from agent-controlled inputsProblem:
RunGitCommand. A value starting with-could be interpreted by git as an option; whitespace or control characters could split into unexpected arguments.exportEnvironmentFile()joined an agent-controlledtarget_filedirectly to the host worktree path withfilepath.Join, allowing../traversal to write outside the environment worktree.Fix:
validateGitRefComponent()and applied it inCheckout,Merge,Apply, andinitializeWorktree...-prefixed paths inexportEnvironmentFile()before any host filesystem or Dagger operation.repository/git_test.go.4.
environment/environment.go: arbitrary executable via user-controlledshellparameterProblem:
Environment.Run()built exec args as[]string{shell, "-c", command}without validatingshell. A caller could pass any executable path (e.g./bin/echo) and have it invoked as the shell interpreter.Fix: Added
isAllowedShell()allowlist (sh,bash,zsh,ashand their/bin/*forms) and reject unsupported values before building args. Added regression test inenvironment/environment_test.go.5.
cmd/container-use/logger.go: debug log file world-readableProblem: The default debug log file was opened with mode
0644, making it readable by any local user. The log can contain command output and environment metadata.Fix: Open the log file with mode
0600.Residual risk / intentionally not addressed in this PR
A parallel security audit also flagged the items below. They are either core product behavior or require larger design changes, so they are left for separate issues rather than being squeezed into a "tiny fix" PR:
setup_commands,install_commands, andenvironment_run_cmdcommands inside their isolated containers. This is the product's purpose; the fix is policy/allowlist design, not a code patch..container-use/environment.json: Moving to a secrets manager or encrypted store is an architecture change.git submodule update --init --recursiveruns with host credentials. Changing this requires design decisions about submodule trust boundaries.--single-tenantis documented as one environment per process; multi-session isolation would require protocol-level auth design.daggerbinary interminalcommand:exec.LookPath("dagger")trusts PATH. A robust fix needs an agreed way to locate the Dagger binary (well-known paths, config, or absolute path). Left as future hardening.Tests
go test -short -count=1 ./...passes for all packages:go vet ./...is clean.go fmt ./...is clean.Note:
dagger call lintcould not be run locally because the Dagger/Podman engine on this host is currently in a bad state (cannot re-exec process to join the existing user namespace), unrelated to these code changes.Checklist
go test -short ./...passesgo vet ./...passesgo fmt ./...passes