Skip to content

Inline @-mentioned files outside the workspace instead of blocking them - #365

Merged
TheGreatAxios merged 2 commits into
mainfrom
cl-5479-path-grants
Aug 7, 2026
Merged

Inline @-mentioned files outside the workspace instead of blocking them#365
TheGreatAxios merged 2 commits into
mainfrom
cl-5479-path-grants

Conversation

@TheGreatAxios

@TheGreatAxios TheGreatAxios commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

An @-mention of a file or directory outside the workspace now resolves and inlines its content — gated by the sensitive-path (.env, keys, credential stores, etc.) and size checks — instead of being hard-blocked with "outside workspace". Everything else about the permission gate is untouched.

This started as a larger change (a persistent read grant minted on mention) but a security review found the durable half unfit to ship: a working TOCTOU (grant coverage re-resolved the path via realpath on every check instead of trusting the mint-time path, so swapping the granted directory for a symlink after minting silently redirected the grant), recursive silent-permanent scope from directory mentions, no UI to see or revoke a grant, leakage into unattended exec runs, a second hand-rolled allow surface parallel to the existing @intx/authz approvals store, and a settings.json read-modify-write race. All of that was deleted. What ships here is the reduction: a mention inlines a file once, the same consent that already covers workspace files, and authorizes nothing beyond that single read — no state persists, no later read is affected.

Why the sensitive-path list had to be extended

The workspace boundary used to be doing double duty. Before this change, a hard-coded "outside workspace" block caught any escape before isSensitivePath was ever consulted, so gaps in that list didn't matter for outside-workspace paths. Now that the boundary no longer applies to mentions, isSensitivePath is the only thing standing between an operator typing @~/.bash_history and its contents landing in the model's context. A live check against the list as it existed found two working leaks: ~/.bash_history and /etc/shadow both inlined unblocked (.env, .ssh/id_rsa, and .aws/credentials already blocked correctly).

Extended SENSITIVE_PATTERNS in src/plugins/secret-guard-plugin.ts — reasoning per category:

  • Shell histories (.bash_history, .zsh_history, .sh_history, fish_history): operators paste secrets into interactive shells constantly (export TOKEN=…, curl -H "Authorization: …", a password on a psql command line); the history file is a durable log of exactly that.
  • /etc/shadow, /etc/sudoers(.d/*): not API-key secrets, but password hashes and the privilege-escalation policy — direct system-compromise material once reachable.
  • macOS Keychain (Library/Keychains/, *.keychain[-db]): every saved Wi-Fi password, site login, and app credential on the machine.
  • Browser cookie jars and saved-login stores (Cookies, Login Data for Chrome/Chromium/Edge; cookies.sqlite, logins.json, key4.db for Firefox): a cookie store alone is often enough to hijack an authenticated session without ever seeing a password.
  • Cloud credentials beyond AWS: broadened the existing single-file gcloud pattern to the whole .config/gcloud/ directory (legacy_credentials/, credentials.db, etc. live alongside the one file that was already covered), and added Azure CLI's credential cache (.azure/accessTokens.json, .azure/azureProfile.json) — the Azure equivalent of the already-covered ~/.aws/credentials.

Deliberately left out: full browser history (places.sqlite) and GPG keyrings beyond what .gnupg/ (already covered) catches — out of the "cookie/login-data" and "credential file" scope actually requested, and each would need its own justification.

Every new pattern class has both a positive test (the file gets blocked) and, where a plausible false-positive existed, a negative test (e.g. src/etc/shadow-dom.ts, src/gcloud-deploy.ts, docs/bash_history_format.md all still resolve normally). Live-verified: the exact .bash_history and /etc/shadow-shaped leaks reported are now blocked with no content in the output.

Tests added

  • src/plugins/secret-guard-plugin.test.ts: one positive + one adjacent negative case per new pattern class.
  • tests/unit/tui/at-mention-resolution.test.ts: a symlink whose target is both outside the workspace and sensitive (@looks-like-a-normal-file → symlink → outside-workspace id_rsa) — the existing symlink test only covered a sensitive target inside the workspace, and the outside-workspace sensitivity test only covered a direct (non-symlink) path. This combination was previously unverified by any test.
  • src/permission/path-restriction.test.ts: kept the prefix-sibling regression (/tmp/x vs /tmp/xbaz) as a resolveWorkspacePath/workspace-boundary test, since that property still matters independent of the deleted grant system.

What I verified by running

  • bun run typecheck, bun run build, bun run test all pass (4037 tests, 0 failures).
  • Standalone script re-creating the exact two leaks from the review (.bash_history under a fake $HOME, and an etc/shadow-shaped path with fabricated hash content) — both now return (blocked: sensitive path) with zero leaked content in the resolved text.
  • Standalone script from the prior round: an @-mention of an outside-workspace file inlines its content once; a separate, later read_file call against that same path on a fresh permission gate still prompts the operator and is denied when declined — confirming no standing grant survives the mention (the one-shot property is structural: resolveAtMentions never calls into path-restriction.ts, gate.ts, or admin.ts).

@linear-code

linear-code Bot commented Aug 7, 2026

Copy link
Copy Markdown

CL-5479

@TheGreatAxios TheGreatAxios changed the title Grant read-only access for @-mentioned outside-workspace paths Inline @-mentioned files outside the workspace instead of blocking them Aug 7, 2026
An @-mention is the operator asking the agent to read one path, once,
right now — the same consent that already covers workspace files.
Outside-workspace mentions now resolve and inline like any other
mention, gated only by the sensitive-path and size checks that already
applied. Nothing about the mention persists past that one read: no
grant is minted, nothing is written to settings, and later reads of
the same path still go through the permission gate on its own terms.
@-mentioning a file outside the workspace now inlines it, so the
workspace boundary no longer stands between an outside path and the
sensitivity check — that check has to carry the full weight alone.
Add shell histories, /etc/shadow and /etc/sudoers, macOS Keychain
databases, browser cookie jars and saved-login stores, and cloud
credential files beyond AWS (gcloud config dir, Azure CLI cache).
@TheGreatAxios
TheGreatAxios merged commit 1e617b1 into main Aug 7, 2026
3 checks passed
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