Skip to content

feat(sandbox): filesystem allow-list via --sandbox-root + JCODE_SANDBOX_ROOT (#110 follow-up)#292

Merged
quangdang46 merged 1 commit into
masterfrom
feat/sandbox-filesystem-allowlist
May 24, 2026
Merged

feat(sandbox): filesystem allow-list via --sandbox-root + JCODE_SANDBOX_ROOT (#110 follow-up)#292
quangdang46 merged 1 commit into
masterfrom
feat/sandbox-filesystem-allowlist

Conversation

@quangdang46
Copy link
Copy Markdown
Owner

Gap close on #110

Previous PR #276 only set JCODE_REQUIRE_MCP_TRUST + JCODE_EXTENSION_POLICY. Upstream PR 1jehuang/jcode#138 actually wanted filesystem confinement: tools reject paths that escape a configured root.

jcode --sandbox-root ~/scratch run 'experiment'
JCODE_SANDBOX_ROOT=/tmp/safe jcode

What ships

  • ToolContext::sandbox_root: Option<PathBuf>
  • ToolContext::resolve_path_checked(path) — rejects paths outside sandbox_root, with canonicalization-based symlink-escape protection. Walks up to closest existing ancestor when target is a new file.
  • --sandbox-root <DIR> CLI flag (separate from existing --sandbox boolean)
  • JCODE_SANDBOX_ROOT env var
  • crate::sandbox::current_sandbox_root() helper for ToolContext construction sites
  • Refactored 11 file tools: read, write, edit, multiedit, hashline_edit, glob, grep, ls, open, side_panel, lsp, patch, apply_patch
  • 8 new unit tests

Design choices

  • Kept --sandbox boolean (PR feat(cli): --sandbox flag for hardened-defaults profile (#110 MVP) #276) as 'hardened defaults' shortcut. Added --sandbox-root separately for FS confinement.
  • agentgrep display-only resolve_path call sites kept as-is (non-Result context).
  • Bash tool not yet anchored to sandbox root (upstream did this but it's a soft boundary, not OS-level — defer).

Tests

$ cargo test -p jcode-tool-core --lib sandbox  # 5 passed
$ cargo test -p jcode --lib sandbox            # 11 passed

Refs upstream PR 1jehuang/jcode#138, fork #110.

…OX_ROOT (#110 follow-up)

GAP CLOSE for issue #110. Previous PR #276 only set JCODE_REQUIRE_MCP_TRUST + JCODE_EXTENSION_POLICY.
Upstream PR #138 actually wanted filesystem confinement: tools reject paths that escape a configured root.

This PR ports that filesystem allow-list semantics, integrating with the existing --sandbox boolean flag.

## What ships

- ToolContext::sandbox_root: Option<PathBuf>
- ToolContext::resolve_path_checked(path) — rejects paths outside sandbox_root, with canonicalization-based symlink-escape protection. Walks up to closest existing ancestor when target is a new file (so writes inside sandbox work).
- --sandbox-root <DIR> CLI flag (separate from existing --sandbox bool)
- JCODE_SANDBOX_ROOT env var
- crate::sandbox::current_sandbox_root() helper for ToolContext construction sites
- Refactored 11 file tools to use resolve_path_checked: read, write, edit, multiedit, hashline_edit, glob, grep, ls, open, side_panel, lsp, patch, apply_patch
- 5 unit tests in jcode-tool-core: allowed-relative, rejected-absolute, dot-dot escape, no-sandbox passthrough, new-file inside sandbox
- 3 unit tests in jcode crate: sandbox helper env round-trips

## Design choices

- Kept --sandbox boolean (PR #276) as 'hardened defaults' shortcut. Added --sandbox-root <DIR> as separate flag for FS confinement.
- agentgrep / mod.rs display-only resolve_path call sites kept as-is (no Result-bearing context).
- Bash tool not yet anchored to sandbox root (upstream did this but it's a soft boundary, not OS-level — defer until needed).

## Tests

  cargo test -p jcode-tool-core --lib sandbox  # 5 passed
  cargo test -p jcode --lib sandbox            # 11 passed (3 new + existing)

Refs upstream PR 1jehuang#138, fork #110.
@quangdang46 quangdang46 merged commit d241c1f into master May 24, 2026
@quangdang46 quangdang46 deleted the feat/sandbox-filesystem-allowlist branch May 24, 2026 22:12
quangdang46 added a commit that referenced this pull request May 24, 2026
After merging 13 PRs in sequence (#290 + #292-#303), two squash-merges
collided on shared schema state:

1. crates/jcode-provider-metadata/src/catalog.rs:
   - Both VERTEX_AI (#283, prior) and BIGMODEL (#297) added entries.
   - Both #19 (#263 GitLab Duo, prior) and #297 declared array size,
     each thinking they were +1 from baseline. Net actual: +2 from
     baseline but final declared count was off by 1.
   - Fixed: OPENAI_COMPAT_PROFILES 35→36, LOGIN_PROVIDERS 48→49 to
     match actual entry count.

2. src/cli/commands/provider_setup.rs:
   - PR #299 added headers: BTreeMap<String, String> field to
     NamedProviderConfig but didn't update this constructor (which
     pre-dated #299 in master).
   - Fixed: added headers: BTreeMap::new() in the configure
     constructor.

cargo check -p jcode --bin jcode now clean. No behavioral change
beyond what each PR brought.
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.

1 participant