omp packages

out-of-project-guard0.1.0

omp safety hook: any tool call that touches a local path outside the session workspace requires explicit user approval (fail-closed).

22w0n0 Published 24 days ago MIT ~161 downloads/mo

Built for omp

The author tagged this package omp-package.

Did it work for you?

Result

One report per person. A new report replaces your old one.

Reports 0

No reports yet.

Readme

out-of-project-guard

Safety hook for omp: any tool call that touches a local filesystem path outside the session workspace requires explicit user approval.

omp install npm:out-of-project-guard     # from npm
omp install ./out-of-project-guard-0.1.0.tgz   # from a local tarball
  • Hook file in this package: hooks/pre/out-of-project-guard.ts — the only runtime file.
  • Once installed, omp loads it from <plugins>/node_modules/out-of-project-guard/hooks/pre/out-of-project-guard.ts via its native hook discovery (hooks/pre/*.ts), so it applies to every session started after the install. No config.yml entry is needed.
  • Disable for one run: omp --no-extensions; disable permanently with disabledExtensions: [hook:pre:out-of-project-guard:out-of-project-guard] in ~/.omp/agent/config.yml (the capability id is hook:<pre|post>:<tool>:<name>, where <tool> and <name> both derive from the filename).
  • Project override: drop a copy at <repo>/.omp/hooks/pre/out-of-project-guard.ts.
  • Self-contained: no config file, no state file, no environment variable. Everything it needs is the session it is loaded into (cwd, workspace roots, the UI). The only switch is the disable id above or the project override.

Workspace roots (never prompt)

  1. session cwd (symlinks resolved)
  2. --add-dir / /add-dir / workspace.additionalDirectories roots, read live from the session header
  3. nearest ancestor of cwd containing .git — skipped when that repository also contains $HOME (a home-directory repo would otherwise disable the guard)

Everything else prompts. Paths are compared after realpath, so a symlink inside the project pointing outside still prompts, and /tmp vs /private/tmp does not false-positive.

Prompt

Three-way selector (ctx.ui.select), only when ctx.hasUI:

Choice Effect
Allow once This call runs; the next outside access prompts again
Allow for this session Grants every offending target's directory for the rest of the process
Deny Call blocked; the same target is refused without prompting until the session ends

The block reason returned to the model names the path, the workspace roots, and the exit routes (/add-dir, /outside-access), so it can ask the user instead of looping.

Fail-closed cases

Blocked, never silently allowed:

  • Headless / print / RPC / subagent contexts where hasUI is false
  • Prompt dismissed or answered with an unrecognized label
  • Hook handler throws
  • Handler exceeds extensionHandlers.toolCallTimeoutMs (runner-enforced, default 30s). Open dialogs pause that budget, so a human can take as long as they need to answer.

Coverage

Known path arguments per tool (read, write, edit, glob, grep, find, ast_grep, ast_edit, lsp, debug, security_scan) plus a generic key scan (path, paths, file, filePath, dir, cwd, root, target, destination, old_path, ...) for any other tool, including MCP tools. Free text is also tokenized for absolute, ~, $HOME, and .. paths in:

  • bash.command (cat /etc/hosts, cd ../..)
  • edit.input (absolute paths inside apply-patch / hashline / sloppy patches)
  • eval.code (Python/JS bodies referencing absolute paths)
  • browser.url (file:///...)

Never prompted: harness-handled URI schemes (memory://, skill://, artifact://, https://, ssh://, ...) and execution-only prefixes under /dev, /proc, /sys, /bin, /sbin, /usr/bin, /usr/sbin, /usr/local/bin, /opt/homebrew/bin.

/outside-access

  • /outside-access — workspace roots, live session grants, live denials
  • /outside-access clear — drop all grants and denials (state is per-process, so a restart clears it too)

Known limits

  • $VAR/... shell paths other than $HOME are not expanded; the hook cannot know the value, so cat $TMPDIR/secret is not flagged. ~user/... is flagged but unresolved.
  • Command substitution (cat "$(cat /etc/path-list)"), shell loops, and paths built at runtime inside eval code are not statically visible.
  • write.content is not scanned (it would flag absolute paths quoted inside generated files).
  • security_scan is listed with its path arguments, but scanning a whole repository is not path-visible when the target comes from a plan id.
  • Grants and denials live in process memory: they do not survive a restart, and subagents share the parent session's state.
  • The hook is not a sandbox. It gates the tools it can see; code that runs inside eval can still open any file the process can read.

License

MIT © 2026 Zenon