Revert "fix(codeql): go/path-injection in pkg/server/session_manager.go:542" (#3758) - #3788
Conversation
…go:542" (docker#3758) docker#3758 added a containment check on user-supplied `working_dir` in `POST /api/sessions` that falls back to `os.Getwd()` as the permitted root when `--working-dir` is unset. That fallback confines every session to whatever directory the process was launched from, which breaks all callers that run docker-agent as a long-lived daemon and legitimately point sessions at arbitrary paths on the host: working directory "…" is outside the permitted root "…" `--working-dir`'s documented purpose (`cmd/root/flags.go`) is a default cwd for tool execution, not a sandbox root. Overloading it as one made the API unusable for the majority of deployments. This reverts commit 9194b2b, reversing changes made to 9650b15. CodeQL alert docker#57 is re-opened; it should be addressed with a design that does not overload `--working-dir` as a security boundary — e.g. a dedicated containment flag whose default is unrestricted.
docker-agent
left a comment
There was a problem hiding this comment.
Assessment: 🟢 APPROVE
This PR is a clean revert of #3758. The surviving + lines pass absWd (the result of filepath.Abs) directly to os.Stat and session.WithWorkingDir, which is the pre-#3758 behaviour. No compile errors, broken imports, nil dereferences, resource leaks, or logic errors were introduced. The removed helper methods (resolveWithinRoot, workingDirRoot) are fully deleted with no dangling call sites, and all imports they used are retained by other code in the file.
docker-agent
left a comment
There was a problem hiding this comment.
Assessment: 🔴 CRITICAL
This revert re-opens CodeQL path-injection alert #57 (CWE-22). The resolveWithinRoot / workingDirRoot containment methods introduced by #3758 are fully removed; user-supplied working_dir is now accepted without any boundary check.
The PR description acknowledges this and calls for a follow-up --session-workingdir-root flag. Until that follow-up lands, authenticated API callers can direct the agent runtime to operate in any directory on the host filesystem the server process can access.
| return nil, errors.New("working directory must be a directory") | ||
| } | ||
| opts = append(opts, session.WithWorkingDir(resolvedWd)) | ||
| opts = append(opts, session.WithWorkingDir(absWd)) |
There was a problem hiding this comment.
[HIGH/SECURITY] Path traversal re-introduced: user-supplied working_dir accepted without containment check (CWE-22)
The revert removes the resolveWithinRoot + workingDirRoot helpers that PR #3758 introduced. CreateSession now calls only filepath.Abs(wd) (which resolves relative paths against the process CWD but imposes no root boundary) and os.Stat (existence + directory check only), then stores the result verbatim as the session's WorkingDir.
An authenticated API caller can supply:
- an absolute path like
/etc,/root, or/home/another-user - a traversal like
../../../../etc
Both will pass the filepath.Abs → os.Stat gauntlet. The accepted path is then passed to teamloader.LoadWithConfig(…, teamloader.WithWorkingDir(sess.WorkingDir)) and used throughout the agent runtime, enabling the caller to load arbitrary agent config and access files anywhere the server process can read.
This is the behaviour the PR intentionally restores. CodeQL alert #57 is explicitly re-opened (per PR description). The risk is real: block merging until the companion --session-workingdir-root flag (mentioned in the PR as a follow-up) is in place, or document that the API server is trusted-network-only and the caller is already authenticated.
| Confidence | Score |
|---|---|
| 🟢 strong | 100/100 |
Why
#3758 added a containment check on user-supplied
working_dirinPOST /api/sessionsthat falls back toos.Getwd()as the permittedroot when
--working-diris unset. That fallback confines everysession to whatever directory the process was launched from, which
breaks all callers that run docker-agent as a long-lived daemon and
legitimately point sessions at arbitrary paths on the host:
--working-dir's documented purpose (cmd/root/flags.go) is a defaultcwd for tool execution, not a sandbox root. Overloading it as one made
the API unusable for the majority of deployments.
An earlier attempt at a targeted fix (#3787) made containment opt-in,
but the automated security reviewer kept flagging the "no boundary
when the flag is unset" branch as a regression even though that is the
only behaviour the API can plausibly ship as its default. A clean
revert is simpler: put the code back to its pre-#3758 shape and design
the CodeQL fix separately, on a dedicated containment flag that
defaults to unrestricted.
Follow-up
CodeQL alert #57 is re-opened by this revert. It should be closed by a
new PR that introduces a dedicated
--session-workingdir-root(orsimilar) flag whose only job is containment, so
--working-dirkeepsits documented purpose and hosted / multi-user deployments can opt
into boundary enforcement explicitly.