Skip to content

Enforce AllowedPaths read/write modes#271

Merged
matt-dz merged 15 commits into
mainfrom
codex/rshell-path-modes-poc
Jun 24, 2026
Merged

Enforce AllowedPaths read/write modes#271
matt-dz merged 15 commits into
mainfrom
codex/rshell-path-modes-poc

Conversation

@matt-dz

@matt-dz matt-dz commented May 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

This updates AllowedPaths to support and enforce optional terminal path mode suffixes:

  • no suffix and :ro configure a read-only root
  • :rw configures a root that may be written when the sandbox is placed in writable/remediation mode
  • overlapping roots use the most-specific configured path, so a narrower :ro overrides a broader :rw
  • POSIX literal paths ending in :ro or :rw are preserved when the literal path exists; Windows strips terminal mode suffixes directly

The write path now enforces those modes for both Open and Truncate. Write targets are checked after symlink/canonical resolution, Unix write opens use a no-follow openat walk, Windows uses Go no-reparse os.Root.OpenFile, and canonical symlink roots are verified against the already-opened root handle before they are used for write authorization.

Only the supported platform implementations are kept: Linux/macOS use the Unix openat implementation, and Windows uses the Windows os.Root implementation. There is no generic unsupported-platform write opener.

Validation

  • make fmt
  • go test ./allowedpaths ./analysis
  • go test ./interp ./builtins/tests/truncate ./tests
  • go test ./...
  • RSHELL_BASH_TEST=1 go test ./tests/ -run TestShellScenariosAgainstBash -timeout 120s
  • env GOTOOLCHAIN=local GOCACHE=/private/tmp/rshell-go-cache GOOS=windows GOARCH=amd64 go test -c ./allowedpaths -o /private/tmp/rshell-allowedpaths-windows.test.exe
  • git diff --check

Notes

The commit was created unsigned in the Codex execution environment because dd-gitsign could not access an SSH agent (SSH_AUTH_SOCK was unset).

@datadog-prod-us1-3

datadog-prod-us1-3 Bot commented May 29, 2026

Copy link
Copy Markdown
Contributor

Pipelines

Fix all issues with BitsAI

⚠️ Warnings

🚦 1 Pipeline job failed

Static Analysis Verification | Static Analysis Label Check   View in Datadog   GitHub Actions

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 0f8bec6 | Docs | Datadog PR Page | Give us feedback!

matt-dz commented May 29, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review this PR for correctness, security regressions around AllowedPaths path-mode parsing, most-specific root matching, write-surface preservation, cross-platform behavior, and missing test coverage.

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

Copy link
Copy Markdown

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: e0fd9d8702

ℹ️ 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 thread allowedpaths/path_mode.go Outdated

matt-dz commented May 29, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

Pushed 6fcaad31 to address the literal :ro/:rw path compatibility finding. Existing suffixed literal paths are now preserved as read-only; suffix parsing only applies when the literal path is absent.

Validation:

  • make fmt
  • go test ./allowedpaths
  • go test ./analysis
  • go test ./interp
  • go test ./...

matt-dz commented May 29, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

Pushed 61e87e13 after the compatibility fix to skip the POSIX-only colon-literal regression tests on Windows. The production behavior is unchanged from 6fcaad31; this only avoids invalid Windows test directory names.

Validation:

  • make fmt
  • go test ./allowedpaths
  • go test ./analysis
  • go test ./interp
  • env GOTOOLCHAIN=local GOCACHE=/private/tmp/rshell-go-cache GOOS=windows GOARCH=amd64 go test -c ./allowedpaths -o /private/tmp/rshell-allowedpaths-windows.test.exe
  • go test ./...

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

Copy link
Copy Markdown

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: 61e87e1375

ℹ️ 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 thread allowedpaths/sandbox.go Outdated

matt-dz commented May 29, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

Pushed 6cf4c4dc to address the Windows path-mode suffix finding. Path-mode resolution is now split by platform: POSIX/non-Windows preserves existing literal suffixed paths, while Windows strips terminal :ro/:rw suffixes directly and has a Windows-only regression test for that behavior.

Validation:

  • make fmt
  • go test ./allowedpaths
  • go test ./analysis
  • go test ./interp
  • env GOTOOLCHAIN=local GOCACHE=/private/tmp/rshell-go-cache GOOS=windows GOARCH=amd64 go test -c ./allowedpaths -o /private/tmp/rshell-allowedpaths-windows.test.exe
  • go test ./...

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

ℹ️ 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".

@matt-dz matt-dz changed the title [codex] Parse path access modes in allowed paths Parse path access modes in allowed paths Jun 22, 2026
@matt-dz
matt-dz force-pushed the codex/rshell-path-modes-poc branch from 6cf4c4d to 819c858 Compare June 22, 2026 15:05

matt-dz commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

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

Copy link
Copy Markdown

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: 6cfa761ad9

ℹ️ 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 thread allowedpaths/sandbox.go Outdated

matt-dz commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

Pushed 2abf4338 to enforce :rw path modes at sandbox write boundaries and added regression coverage for read-only roots in remediation mode.

Validation:

  • make fmt
  • go test ./allowedpaths
  • go test ./analysis ./interp
  • go test ./builtins/tests/truncate ./tests
  • go test ./...

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

Copy link
Copy Markdown

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: 2abf43382b

ℹ️ 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 thread allowedpaths/sandbox.go Outdated
@matt-dz

matt-dz commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

Pushed 3f733b9d to enforce path modes after resolving in-root symlink write targets, closing the symlink bypass into narrower read-only roots.

Validation:

  • make fmt
  • go test ./allowedpaths
  • go test ./analysis ./interp
  • go test ./builtins/tests/truncate ./tests
  • go test ./...
  • env GOTOOLCHAIN=local GOCACHE=/private/tmp/rshell-go-cache GOOS=windows GOARCH=amd64 go test -c ./allowedpaths -o /private/tmp/rshell-allowedpaths-windows.test.exe
  • git diff --check

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

Copy link
Copy Markdown

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: 3f733b9d6d

ℹ️ 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 thread allowedpaths/sandbox.go
@matt-dz

matt-dz commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

Pushed 17902805 to enforce write path modes against canonical root spellings too, including symlinked allowed roots that point at real paths configured read-only.

Validation:

  • make fmt
  • go test ./allowedpaths
  • go test ./...
  • env GOTOOLCHAIN=local GOCACHE=/private/tmp/rshell-go-cache GOOS=windows GOARCH=amd64 go test -c ./allowedpaths -o /private/tmp/rshell-allowedpaths-windows.test.exe
  • git diff --check

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

Copy link
Copy Markdown

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: 17902805f8

ℹ️ 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 thread allowedpaths/sandbox.go
@matt-dz

matt-dz commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

Pushed d0ca37c5 to make Unix write opens use a no-follow openat walk after the path-mode decision, closing the symlink swap race into read-only child roots.

Validation:

  • make fmt
  • go test ./allowedpaths ./analysis
  • go test ./interp
  • go test ./builtins/tests/truncate ./tests
  • go test ./...
  • env GOTOOLCHAIN=local GOCACHE=/private/tmp/rshell-go-cache GOOS=windows GOARCH=amd64 go test -c ./allowedpaths -o /private/tmp/rshell-allowedpaths-windows.test.exe
  • git diff --check

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

Copy link
Copy Markdown

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: d0ca37c562

ℹ️ 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 thread allowedpaths/sandbox.go Outdated
Comment thread tests/scenarios_test.go Outdated
@matt-dz

matt-dz commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

Pushed 95293912 to address the latest review findings: read-only/default roots no longer allocate Unix write-root fds, and scenario AllowedPaths now preserve YAML path-mode semantics without a remediation-mode :rw harness rewrite.

Validation:

  • make fmt
  • go test ./allowedpaths ./tests
  • go test ./analysis ./interp
  • go test ./builtins/tests/truncate
  • go test ./...
  • RSHELL_BASH_TEST=1 go test ./tests/ -run TestShellScenariosAgainstBash -timeout 120s
  • env GOTOOLCHAIN=local GOCACHE=/private/tmp/rshell-go-cache GOOS=windows GOARCH=amd64 go test -c ./allowedpaths -o /private/tmp/rshell-allowedpaths-windows.test.exe
  • git diff --check

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

Copy link
Copy Markdown

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: 95293912e4

ℹ️ 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 thread allowedpaths/sandbox.go Outdated
@matt-dz

matt-dz commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

Pushed bd3174ba to bind Unix write roots to the already-opened sandbox root instead of reopening the configured pathname, closing the construction-time root-swap race.

Validation:

  • make fmt
  • go test ./allowedpaths ./analysis
  • go test ./interp ./builtins/tests/truncate ./tests
  • go test ./...
  • RSHELL_BASH_TEST=1 go test ./tests/ -run TestShellScenariosAgainstBash -timeout 120s
  • env GOTOOLCHAIN=local GOCACHE=/private/tmp/rshell-go-cache GOOS=windows GOARCH=amd64 go test -c ./allowedpaths -o /private/tmp/rshell-allowedpaths-windows.test.exe
  • git diff --check

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

Copy link
Copy Markdown

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: bd3174badf

ℹ️ 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 thread allowedpaths/sandbox.go
Comment thread allowedpaths/internal/writeopen/writeopen_fallback.go
@matt-dz

matt-dz commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: 6033b6a0ee

ℹ️ 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".

@matt-dz matt-dz changed the title Parse path access modes in allowed paths Enforce AllowedPaths read/write modes Jun 22, 2026
@matt-dz
matt-dz marked this pull request as ready for review June 22, 2026 20:13
@matt-dz
matt-dz enabled auto-merge June 23, 2026 17:22

@julesmcrt julesmcrt left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Few nits, overall LGTM

Comment thread interp/api.go
// AllowedPaths restricts file and directory access to the specified directories.
// Paths must be absolute directories that exist. When set, only files within
// these directories can be opened (for reading or writing), read, or executed.
// Paths must be absolute directories that exist. A path may end with :ro or :rw

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

CLI --allowed-paths help text not updated for :ro/:rw suffixes

go run ./cmd/rshell --help outputs:

...
-p, --allowed-paths string      comma-separated list of directories the shell is allowed to access
...

❓ Should we make the suffix appear here?

See cmd/rshell/main.go:142,147


package allowedpaths

func resolveAllowedPathMode(path string) (string, pathMode) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not a blocker as we don't plan on supporting Windows for now.

❓ Should we add a comment documenting that ADS-style suffixes are intentionally treated as mode suffixes on Windows, so the divergence from the Unix literal-preservation behavior is explicit.

A path like C:\data\file:rw is ambiguous with an NTFS Alternate Data Stream (file:rw), so the Windows code strips unconditionally.

However the Unix resolveAllowedPathMode carefully preserves a literal path that genuinely ends in :ro/:rw (via os.Lstat), so a real directory named tenant:rw is never silently reinterpreted as a mode.

"os.Getuid", // 🟠 returns the numeric user id of the caller; read-only syscall.
"os.O_APPEND", // 🟢 append-on-write file flag constant; pure constant. Part of the sandbox open-flag allowlist.
"os.O_CREATE", // 🟢 create-if-missing file flag constant; pure constant. Part of the sandbox open-flag allowlist.
"os.Lstat", // 🟠 checks whether a literal AllowedPaths entry exists without following symlinks, preserving legacy paths that end in :ro/:rw.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Shouldn't we preserve alphabetical order here?

@matt-dz
matt-dz added this pull request to the merge queue Jun 24, 2026
Merged via the queue into main with commit b6ca032 Jun 24, 2026
40 of 41 checks passed
@matt-dz
matt-dz deleted the codex/rshell-path-modes-poc branch June 24, 2026 09:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants