Skip to content

fix: canonicalize symlinked Linux sandbox cwd#14849

Merged
viyatb-oai merged 3 commits intomainfrom
codex/viyatb/fix-linux-sandbox-symlinked-cwd
Mar 17, 2026
Merged

fix: canonicalize symlinked Linux sandbox cwd#14849
viyatb-oai merged 3 commits intomainfrom
codex/viyatb/fix-linux-sandbox-symlinked-cwd

Conversation

@viyatb-oai
Copy link
Copy Markdown
Collaborator

@viyatb-oai viyatb-oai commented Mar 16, 2026

Problem

On Linux, Codex can be launched from a workspace path that is a symlink (for example, a symlinked checkout or a symlinked parent directory).

Our sandbox policy intentionally canonicalizes writable/readable roots to the real filesystem path before building the bubblewrap mounts. That part is correct and needed for safety.

The remaining bug was that bubblewrap could still inherit the helper process's logical cwd, which might be the symlinked alias instead of the mounted canonical path. In that case, the sandbox starts in a cwd that does not exist inside the sandbox namespace even though the real workspace is mounted. This can cause sandboxed commands to fail in symlinked workspaces.

Fix

This PR keeps the sandbox policy behavior the same, but separates two concepts that were previously conflated:

  • the canonical cwd used to define sandbox mounts and permissions
  • the caller's logical cwd used when launching the command

On the Linux bubblewrap path, we now thread the logical command cwd through the helper explicitly and only add --chdir <canonical path> when the logical cwd differs from the mounted canonical path.

That means:

  • permissions are still computed from canonical paths
  • bubblewrap starts the command from a cwd that definitely exists inside the sandbox
  • we do not widen filesystem access or undo the earlier symlink hardening

Why This Is Safe

This is a narrow Linux-only launch fix, not a policy change.

  • Writable/readable root canonicalization stays intact.
  • Protected metadata carveouts still operate on canonical roots.
  • We only override bubblewrap's inherited cwd when the logical path would otherwise point at a symlink alias that is not mounted in the sandbox.

Tests

  • kept the existing protocol/core regression coverage for symlink canonicalization
  • added regression coverage for symlinked cwd handling in the Linux bubblewrap builder/helper path

Local validation:

  • just fmt
  • cargo test -p codex-protocol
  • cargo test -p codex-core normalize_additional_permissions_canonicalizes_symlinked_write_paths
  • cargo clippy -p codex-linux-sandbox -p codex-protocol -p codex-core --tests -- -D warnings
  • cargo build --bin codex

Context

This is related to #14694. The earlier writable-root symlink fix addressed the mount/permission side; this PR fixes the remaining symlinked-cwd launch mismatch in the Linux sandbox path.

Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6979b9dc19

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@etraut-openai
Copy link
Copy Markdown
Collaborator

@codex review

Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a9be5c725c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +414 to +416
command_cwd
.canonicalize()
.unwrap_or_else(|_| command_cwd.to_path_buf())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Badge Resolve relative command-cwd before canonicalizing

normalize_command_cwd_for_bwrap canonicalizes command_cwd as-is. If --command-cwd is relative, canonicalization runs relative to the helper's current dir (already set to that cwd), so foo can resolve as <base>/foo/foo. The added --chdir then points to the wrong directory, changing command behavior versus the requested cwd.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

not reachable from codex but could be reached if someone used relative paths with codex sandbox linux

@viyatb-oai viyatb-oai merged commit db7e02c into main Mar 17, 2026
32 checks passed
@viyatb-oai viyatb-oai deleted the codex/viyatb/fix-linux-sandbox-symlinked-cwd branch March 17, 2026 05:39
@github-actions github-actions bot locked and limited conversation to collaborators Mar 17, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

2 participants