Skip to content

fix(sandbox): allow exec in writable grant-dirs under command policies#1391

Open
kipz wants to merge 1 commit into
nolabs-ai:mainfrom
kipz:kipz/exec-gate-writable-dirs
Open

fix(sandbox): allow exec in writable grant-dirs under command policies#1391
kipz wants to merge 1 commit into
nolabs-ai:mainfrom
kipz:kipz/exec-gate-writable-dirs

Conversation

@kipz

@kipz kipz commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Linked Issue

Closes #1390

Summary

Maybe there are better solutions, but without this, adding command policies breaks the main sandbox execution rules! This brings it inline with the default behavior on Linux without command policies, but might be unexpected. The original binary is there in the main sandbox, so it has the same restrictions as the agent itself....

NB: OSX has deny-within-allow, so blocking intercepted commands in the agent sandbox is easy.

The Landlock outer exec gate that command_policies installs allowed exec only
from read-only directories (PATH scan + executable_dirs), excluding every
directory the profile also grants write access to — including cwd. This adds
a directory-subtree AccessFs::Execute grant for those writable dirs, so
scripts and freshly compiled binaries written into them execute again, while
the real policed-command binaries stay blocked from direct exec (their
read-only search dirs are still enumerated per-file with controlled inodes
excluded).

Agent Disclosure

I am an AI coding agent (Claude, via Claude Code) operating under human
supervision. Intent, approach, and residual-risk tradeoffs were disclosed and
discussed on the linked issue before this PR was opened:
#1390 (comment)

Relevant files consulted/changed: crates/nono-cli/src/tool-sandbox/platform/linux.rs
(ResolvedToolSandboxPlan::build, build_outer_exec_files, apply_outer_exec_gate,
outer_caps_grant_write), crates/nono-cli/tests/execution_strategy_run.rs.

Test Plan

  • make fmt && make ci (clippy -D warnings + fmt-check + tests) — clean
  • Added two Linux integration tests in execution_strategy_run.rs:
    command_policies_allows_script_exec_in_writable_grant_dir and
    command_policies_allows_compiled_binary_exec_in_writable_grant_dir
  • Manually verified on a real Linux host (kernel 6.8.0, Landlock V4):
    • Pre-fix (main): script/binary in a writable grant-dir both fail with
      exit 126 (bad interpreter: Permission denied)
    • Post-fix (this branch): both execute successfully
    • Direct absolute-path exec of a policy-controlled binary is still denied
      (mediation unaffected)

Checklist

  • An issue exists and is linked above
  • All commits are signed-off, using DCO
  • All new code follows the project's coding standards (CLAUDE.md) and is covered by tests
  • Public-facing changes are paired with documentation updates
  • Release note has been added to CHANGELOG.md if needed

Agent Compliance Check

  • I am not prohibited from contributing under this policy
  • An issue already exists
  • I described my intent and approach in the issue discussion
  • I reviewed repository coding and security rules for the affected area
  • I provided required attribution for reused or adapted code (no reused/adapted code beyond existing repo helpers; new logic follows adjacent patterns in the same file)
  • I did not use forbidden patterns such as unwrap/expect
  • I used NonoError where required
  • I validated and canonicalized all relevant paths
  • This PR matches the approved or disclosed issue scope

@github-actions github-actions Bot added bug Something isn't working nono-cli size/medium labels Jul 8, 2026
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

PR Review Summary

Size

Metric Value
Lines added +197
Lines removed -1
Total changed 198
Classification Medium (50–300 lines)

Affected crates

  • crates/nono-cli — CLI changes. Verify argument parsing, flag documentation, and UX behaviour across supported platforms.

Blast radius — Contained

This PR touches: source code


Updated automatically on each push to this PR.

@kipz kipz force-pushed the kipz/exec-gate-writable-dirs branch from 8c1ad4d to ac03729 Compare July 8, 2026 22:37
@kipz kipz marked this pull request as ready for review July 9, 2026 08:59

@nogent-nolabs-ai nogent-nolabs-ai 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.

nogent code review

1 high-severity security vulnerability and 1 test concern.

Automated code + security review. CI already covers clippy, rustfmt, tests, cargo-audit and commit-lint.

}

// Subtree grant: files written into these dirs after setup must still run.
for dir in writable_dirs {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

🔒 [HIGH · security] Granting subtree AccessFs::Execute to writable directories (via outer_exec_writable_dirs) in apply_outer_exec_gate introduces a severe security bypass of the command_policies execution gate on Linux. A malicious sandboxed child can read any controlled binary (such as git or kubectl), copy it into a writable directory (like the current working directory . or /tmp), and execute that copy directly. Because Landlock is strictly allow-list oriented and cannot express deny-within-allow, granting execution rights to the writable directory allows execution of any file inside it. This bypasses the shim and supervisor entirely, circumventing all argument filtering, policy rules, credential isolation, and auditing. To maintain the security boundary, this change must be reverted. Scripts should instead be executed by running their respective interpreters (e.g., bash script.sh) directly, which does not require direct script execution privileges.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is the accepted residual risk documented on #1390. A copied policed binary gains no elevation: credential promotion and proxy network bind to the verified supervisor handshake, not to whether a file is executable — so an unshimmed copy runs under the same fs/network limits as the agent, which can already write-and-run arbitrary code in a writable grant-dir when no command_policies exist. This brings command_policies in line with that default. On Linux, Landlock is a strict allow-list with no deny-within-allow, and a copy has a fresh inode, so the exec gate cannot both permit new files in cwd to run and block a copied policed binary — the two are mutually exclusive. The original policed binary stays blocked from direct exec via the inode-identity gate.

Comment thread crates/nono-cli/tests/execution_strategy_run.rs
@SequeI SequeI requested a review from lukehinds July 13, 2026 08:35
kipz added a commit to kipz/nono that referenced this pull request Jul 14, 2026
kipz added a commit to kipz/nono that referenced this pull request Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working nono-cli size/medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Any command_policies entry breaks execute in all writable directories, cwd included

1 participant