Skip to content

fix(file_tools): don't treat macOS temp/scratch paths as sensitive - #46412

Open
OmarB97 wants to merge 2 commits into
NousResearch:mainfrom
OmarB97:fix/macos-temp-not-sensitive-upstream
Open

OmarB97 wants to merge 2 commits into
NousResearch:mainfrom
OmarB97:fix/macos-temp-not-sensitive-upstream

Conversation

@OmarB97

@OmarB97 OmarB97 commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Problem

On macOS, $TMPDIR resolves to /private/var/folders/.../T and /var/tmp to /private/var/tmp — both live under /private/var/, which is listed in _SENSITIVE_PATH_PREFIXES. As a result _check_sensitive_path refused every write_file/patch inside a temp or scratch directory.

This breaks any agent working in a temporary git worktree: the write tool returns "Refusing to write to sensitive system path: …", the model loops unable to complete its task (the file-mutation verifier keeps flagging the unwritten file), and the goal run ends with no final response. Observed across local-model goal runs whose workspace was a macOS temp worktree.

Fix

Exempt the standard temp/scratch roots — /private/var/folders/, /private/var/tmp/, /var/folders/, /var/tmp/, /tmp/, and the resolved tempfile.gettempdir() — from only the broad sensitive-prefix scan. A realpath() check defeats symlink escapes (a temp symlink pointing at /etc resolves out of temp and stays refused). The exact-path (docker socket) and Hermes-config protections still run, and genuinely-sensitive /private/var subtrees (/private/var/db, /private/var/root) remain refused.

Tests

tests/tools/test_file_tools.py::TestSensitivePathCheck gains:

  • test_macos_temp_scratch_not_blocked — temp/scratch paths are allowed.
  • test_real_private_var_still_blocked/private/var/db, /private/var/root, docker.sock, /etc/passwd, /private/etc stay refused.

pytest tests/tools/test_file_tools.py::TestSensitivePathCheck tests/tools/test_file_write_safety.py tests/tools/test_write_deny.py57 passed.

On macOS $TMPDIR resolves to /private/var/folders/.../T and /var/tmp to
/private/var/tmp — both under /private/var/, which is in
_SENSITIVE_PATH_PREFIXES. So _check_sensitive_path refused EVERY write inside a
temp/scratch directory (e.g. an agent working in a temporary git worktree): the
write_file tool returned "Refusing to write to sensitive system path", the model
looped unable to complete the task, and the goal run produced no final response.

Exempt the standard temp/scratch roots (/private/var/folders, /private/var/tmp,
/var/folders, /var/tmp, /tmp, and the resolved tempfile.gettempdir()) from ONLY
the broad prefix scan, via a realpath() check that defeats symlink escapes. The
exact-path (docker.sock) and Hermes-config protections still apply, and the
genuinely-sensitive /private/var subtrees (/private/var/db, /private/var/root)
stay refused.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@alt-glitch alt-glitch added type/bug Something isn't working tool/file File tools (read, write, patch, search) P2 Medium — degraded but workaround exists duplicate This issue or pull request already exists labels Jun 15, 2026
@alt-glitch

Copy link
Copy Markdown
Contributor

Duplicate of #46395 — same tools/file_tools.py fix exempting macOS temp/scratch roots from the sensitive-prefix scan with a realpath symlink defense. This PR is the clean, isolated version; #46395 carries the same fix buried under a whole-fork push. Related to the existing cluster: #41285 / #13733 / #31021 (issue #32681).

@OmarB97

OmarB97 commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

Correct triage @alt-glitch, thanks. Closing the loop on it: #46395 (my whole-fork-push variant) has since been closed, so this PR is now the single canonical version of the fix from my side.

For anyone consolidating the cluster (#41285 / #13733 / #31021, issue #32681), what this variant includes as of the current head (e28fc32, merged with mainline 2026-07-05, still mergeable):

  • Exempts only symlink-resolved temp/scratch roots (/private/var/folders/, /private/var/tmp/, /var/folders/, /var/tmp/, /tmp/, plus the runtime tempfile.gettempdir()) from the broad sensitive-prefix scan in tools/file_tools.py.
  • _is_temp_scratch_path runs os.path.realpath first, so a symlink planted in temp that points at /etc resolves out of the temp root and stays blocked — the symlink-escape defense.
  • The exact-path guard (docker.sock) and the Hermes-config guard still apply inside temp; only the prefix scan is skipped.
  • Regression tests in both directions: temp writes allowed, and /private/var/db, /private/var/root, /var/run/docker.sock, /etc/passwd all still refused.

Happy for this to serve as the consolidation target for #32681, and glad to coordinate with the other authors if maintainers want a single landing.

@teknium1 teknium1 added sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

duplicate This issue or pull request already exists P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-security-boundary Sweeper risk: may affect sandboxing, auth, credentials, or sensitive data tool/file File tools (read, write, patch, search) type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants