Skip to content

feat(sandbox): add default deny settings - #10940

Merged
jdx merged 3 commits into
jdx:mainfrom
risu729:codex-20260711-154810-fe4469
Jul 11, 2026
Merged

jdx merged 3 commits into
jdx:mainfrom
risu729:codex-20260711-154810-fe4469

Conversation

@risu729

@risu729 risu729 commented Jul 11, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • add [settings.sandbox] deny defaults matching the sandbox CLI deny flags
  • apply settings through the existing CLI-side SandboxConfig path for both mise exec and mise run
  • document the global default and verify task-level allow exceptions still compose with it

This addresses the design requested in discussion #10669 without introducing task defaults, implicit templates, or composable templates.

User impact

Users can set a sandbox policy once, including at a monorepo root:

[settings.sandbox]
deny_all = true

Individual tasks can continue to add allow_read, allow_write, allow_net, and allow_env exceptions.

E2E coverage

This PR intentionally does not include an E2E test. Filesystem sandbox enforcement on Linux requires Landlock, but the GitHub Actions E2E runner reports Landlock as NotEnabled. An E2E exercising [settings.sandbox] deny_all = true therefore fails while applying the kernel restriction rather than testing the settings behavior. The settings/CLI composition is covered by focused unit tests instead.

Validation

  • mise run format
  • mise run render:schema
  • cargo test test_from_settings_and_cli --all-features
  • cargo test test_settings_toml_is_sorted --all-features

Summary by CodeRabbit

  • New Features

    • Added global sandbox “default restrictions” settings to deny filesystem reads/writes, network access, and environment inheritance (deny_all, deny_env, deny_net, deny_read, deny_write).
    • Sandbox deny behavior is now combined from global settings and command-level/CLI options for both task execution and command execution, with existing allow-list exceptions still supported.
  • Documentation

    • Documented how to enable default sandbox deny rules and how allow-list exceptions override them.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Global sandbox deny settings are added to configuration and schema, merged with CLI restrictions for mise run and mise exec, documented, and validated through unit and end-to-end tests covering environment, filesystem, and allow-list behavior.

Changes

Sandbox settings

Layer / File(s) Summary
Sandbox configuration contract
settings.toml, schema/mise.json, docs/sandboxing.md
Defines five default-deny settings, their environment mappings, schema metadata, and configuration guidance.
Runtime restriction integration
src/sandbox/mod.rs, src/cli/run.rs, src/cli/exec.rs
Combines global settings with CLI deny flags through SandboxConfig::from_settings_and_cli, with unit tests covering selective and all-category denial.
Sandbox settings validation
e2e/cli/test_sandbox_settings
Verifies environment blocking, explicit allow_env and read exceptions, default-deny behavior, and blocked filesystem operations.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Settings
  participant RunExec
  participant SandboxConfig
  Settings->>RunExec: Provide global deny settings
  RunExec->>SandboxConfig: Combine global and CLI deny flags
  SandboxConfig-->>RunExec: Apply sandbox restrictions
Loading

Poem

A rabbit hops through settings bright,
Denying env by day and night.
Yet allow_env opens one small door,
While run and exec guard the floor.
“Configured!” I twitch my nose—
Safe little tasks in rows.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding default-deny sandbox settings.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 11, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR introduces global sandbox deny defaults via [settings.sandbox] in mise.toml, allowing users to set policies like deny_all = true once (including at a monorepo root) that apply to every mise exec and mise run invocation. A new SandboxConfig::from_settings_and_cli function merges the persistent settings-based deny flags with per-invocation CLI flags before passing the result through the existing sandbox enforcement path.

  • Adds five settings (deny_all, deny_read, deny_write, deny_net, deny_env) with corresponding MISE_SANDBOX_DENY_* env-var overrides, registered in settings.toml and surfaced in schema/mise.json.
  • Refactors exec.rs and run.rs to use from_settings_and_cli instead of inline OR logic; task-level allow_* exceptions continue to compose correctly via the pre-existing build_sandbox_for_task merge in the task executor.
  • Unit tests cover both the flag-combination and deny_all-expansion paths.

Confidence Score: 5/5

The change is a clean additive feature with all deny flags defaulting to false, so existing behavior is completely unchanged unless explicitly opted-in.

The refactor correctly preserves the semantics of the original OR logic, the new from_settings_and_cli function has full unit-test coverage, and path resolution ordering is unchanged in both callers. The feature defaults to no-op, so there is no risk of inadvertent sandbox activation for existing users.

No files require special attention.

Important Files Changed

Filename Overview
src/sandbox/mod.rs Adds from_settings_and_cli that correctly ORs settings deny flags into CLI deny flags; unit tests verify both combination and deny_all expansion paths.
src/cli/exec.rs Replaces inline SandboxConfig construction with from_settings_and_cli; semantics preserved, resolve_paths() still called immediately after.
src/cli/run.rs Same refactor as exec.rs; path resolution is deferred correctly to build_sandbox_for_task in the task executor.
settings.toml Adds five sandbox deny settings with env-var overrides; alphabetical ordering preserved relative to adjacent shared_install_dirs section.
schema/mise.json Adds sandbox object to JSON schema with unevaluatedProperties: false and correct boolean defaults for all five deny properties.
docs/sandboxing.md Adds accurate "Default Restrictions" section documenting the new settings and how task-level allow exceptions still compose.

Reviews (3): Last reviewed commit: "test(sandbox): remove unsupported e2e te..." | Re-trigger Greptile

Comment thread e2e/cli/test_sandbox_settings Resolved

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
src/cli/run.rs (1)

716-748: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract duplicated deny-flag composition logic.

This settings+CLI deny composition block is duplicated verbatim in src/cli/exec.rs (lines 237-255). Consider a shared constructor on SandboxConfig (e.g. SandboxConfig::from_settings(sandbox_settings, cli_deny_all, cli_deny_read, ..., allow_read, ...)) in src/sandbox/mod.rs to avoid the two call sites drifting if the composition rule changes.

♻️ Proposed refactor
+impl SandboxConfig {
+    pub fn from_settings_and_cli(
+        settings: &crate::config::settings::SandboxSettings,
+        cli_deny_all: bool,
+        cli_deny_read: bool,
+        cli_deny_write: bool,
+        cli_deny_net: bool,
+        cli_deny_env: bool,
+        allow_read: Vec<PathBuf>,
+        allow_write: Vec<PathBuf>,
+        allow_net: Vec<String>,
+        allow_env: Vec<String>,
+    ) -> Self {
+        Self {
+            deny_read: settings.deny_all || settings.deny_read || cli_deny_all || cli_deny_read,
+            deny_write: settings.deny_all || settings.deny_write || cli_deny_all || cli_deny_write,
+            deny_net: settings.deny_all || settings.deny_net || cli_deny_all || cli_deny_net,
+            deny_env: settings.deny_all || settings.deny_env || cli_deny_all || cli_deny_env,
+            allow_read,
+            allow_write,
+            allow_net,
+            allow_env,
+        }
+    }
+}

Then call it from both run.rs and exec.rs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/cli/run.rs` around lines 716 - 748, Extract the duplicated sandbox
settings and CLI flag composition into a shared constructor, such as
SandboxConfig::from_settings, in the SandboxConfig implementation within
sandbox/mod.rs. Have it accept the sandbox settings, deny flags, and allow
lists, apply the existing OR-composition rules, and replace the inline
construction in both the run command and exec command paths.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/cli/run.rs`:
- Around line 716-748: Extract the duplicated sandbox settings and CLI flag
composition into a shared constructor, such as SandboxConfig::from_settings, in
the SandboxConfig implementation within sandbox/mod.rs. Have it accept the
sandbox settings, deny flags, and allow lists, apply the existing OR-composition
rules, and replace the inline construction in both the run command and exec
command paths.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 7724fb32-d226-419d-b95b-aa1fa15a4701

📥 Commits

Reviewing files that changed from the base of the PR and between 20888f4 and 88f29fa.

📒 Files selected for processing (6)
  • docs/sandboxing.md
  • e2e/cli/test_sandbox_settings
  • schema/mise.json
  • settings.toml
  • src/cli/exec.rs
  • src/cli/run.rs

@risu729

risu729 commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the AI review feedback in 236b375:

  • centralized settings + CLI deny composition in SandboxConfig::from_settings_and_cli, shared by mise run and mise exec
  • expanded unit and E2E coverage for deny_all, individual deny merging, all five environment overrides, allow exceptions, and denied writes

Validation passed:

  • cargo test sandbox::tests::test_from_settings_and_cli --all-features
  • mise run test:e2e test_sandbox_settings

This comment was generated by an AI coding assistant.

@risu729
risu729 marked this pull request as ready for review July 11, 2026 07:37
@jdx
jdx merged commit b6a4920 into jdx:main Jul 11, 2026
34 checks passed
@risu729
risu729 deleted the codex-20260711-154810-fe4469 branch July 12, 2026 03:57
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