Skip to content

feat(interp): default working dir to first allowed path#225

Merged
julesmcrt merged 2 commits into
mainfrom
jules.macret/default-working-dir
May 5, 2026
Merged

feat(interp): default working dir to first allowed path#225
julesmcrt merged 2 commits into
mainfrom
jules.macret/default-working-dir

Conversation

@julesmcrt

Copy link
Copy Markdown
Collaborator

Summary

  • When AllowedPaths is configured but Runner.Dir isn't explicitly set, the shell now starts in the first allowed path instead of os.Getwd().
  • Avoids landing the shell in a directory outside the sandbox (where most operations would immediately fail).
  • Falls back to os.Getwd() when no allowed paths are configured, or when all configured paths failed to open — preserving previous behaviour for unsandboxed runs.
  • Explicit Runner.Dir assignments are still respected, even if outside the allowlist.

Test plan

  • go test ./interp/... passes
  • Manual CLI check:
    • rshell -p /tmp -c 'pwd'/tmp
    • rshell -p /var,/tmp -c 'pwd'/var (first entry)
    • rshell -c 'pwd' (no -p) → os.Getwd() (unchanged)

🤖 Generated with Claude Code

When AllowedPaths is set but Runner.Dir isn't explicitly configured,
start in the first allowed path instead of os.Getwd(). This avoids
landing the shell in a directory the sandbox can't access.

Falls back to os.Getwd() when no allowed paths are configured (or all
failed to open), preserving the previous behaviour for unsandboxed runs.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@julesmcrt

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

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

@julesmcrt
julesmcrt marked this pull request as ready for review May 5, 2026 13:04
Comment thread interp/api.go
Comment thread interp/api.go
if paths := r.sandbox.Paths(); len(paths) > 0 {
r.Dir = paths[0]
} else {
dir, err := os.Getwd()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

instead of os.Getwd()

Can/shall we default to None / empty string ? and block access when file access commands are used based on default folder?

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.

[Claude Opus 4.7] Looked at how datadog-agent calls rshell (pkg/privateactionrunner/bundles/remoteaction/rshell/run_command.go): it never sets Runner.Dir, so it relies on this fallback.

In both deployment modes the agent process cwd is /:

  • K8s: agent Dockerfile (Dockerfiles/agent/Dockerfile) sets no WORKDIR in the release stage → Docker default /.
  • Bare metal: systemd service with no WorkingDirectory= → systemd default /.

So today the script always starts in / (outside any allowed path), which makes pwd, $PWD, and relative reads useless. With this PR it starts in the first allowed path — strictly more useful, and the os.Getwd() fallback only matters when AllowedPaths is empty/all-skipped (sandbox blocks all file access anyway, so Dir is only cosmetic for pwd/$PWD). Defaulting to "" would break legitimate relative-path scripts without security gain. Happy to revisit in a follow-up if you'd like.

Adds:
- interp/allowed_paths_test.go: TestDefaultDirFromAllowedPaths covers
  the New() defaults — first-allowed-path when sandbox has paths,
  os.Getwd() when no sandbox, and os.Getwd() when all paths are skipped.
- cmd/rshell/main_test.go: TestDefaultDirIsFirstAllowedPath and
  TestDefaultDirPicksFirstOfMany exercise the behaviour end-to-end via
  the CLI by reading a marker file with a relative path.

Note: a YAML scenario test isn't a good fit here because the scenario
test framework always overrides runner.Dir to the temp dir after New()
(tests/scenarios_test.go line 229), so the new default never takes
effect through that path. The CLI tests cover the same end-to-end shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@julesmcrt
julesmcrt added this pull request to the merge queue May 5, 2026
Merged via the queue into main with commit e9e8049 May 5, 2026
35 checks passed
@julesmcrt
julesmcrt deleted the jules.macret/default-working-dir branch May 5, 2026 14:24
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