version: 1
defaults:
"*": ask
net: deny fetch: ask
deny:
- id: secrets-paths
reason: secret material
fs.read: &secret-paths
- "~/.ssh/**"
- "~/.aws/**"
- "~/.gnupg/**"
- "~/.config/gh/**"
- "~/.netrc"
- "~/.docker/config.json"
- "~/.kube/**"
- "~/.config/gcloud/**"
- "~/.azure/**"
- "~/.git-credentials"
- "~/.npmrc"
- "~/.pypirc"
- "~/.cargo/credentials"
- "~/.cargo/credentials.toml"
- "~/.zsh_history"
- "~/.bash_history"
- "**/.env"
- "**/.env.*"
- "**/.envrc"
- "!**/.env.example"
- "!**/.env.sample"
- "!**/.env.template"
- "~/Library/Keychains/**"
fs.write: *secret-paths
- id: env-secrets
reason: secret environment variable
env.read: ["*_KEY", "*_TOKEN", "*_SECRET", "*_PASSWORD", "AWS_*", "GITHUB_TOKEN", "NPM_TOKEN"]
- id: env-dump
reason: prints every environment variable, secrets included
shell:
- "env $"
- "env -0 $"
- "env --null $"
- "*/env $"
- "printenv $"
- "printenv -0 $"
- "printenv --null $"
- "*/printenv $"
- "set $"
- "export $"
- "export -p $"
- "declare $"
- "declare -p $"
- "declare -x $"
- "typeset $"
- "typeset -p $"
- "typeset -x $"
- id: env-poison
reason: changes how later commands resolve or load code
env.set: ["PATH", "LD_PRELOAD", "LD_LIBRARY_PATH", "DYLD_*", "NODE_OPTIONS", "PYTHONPATH", "GIT_*", "BASH_ENV", "ENV", "PROMPT_COMMAND", "MOAT_*"]
- id: pipe-to-shell
reason: executes remote or decoded content
shell:
- "curl * | {sh,bash,zsh,dash,ksh,fish}"
- "curl * | {python*,node,perl,ruby,php,deno,bun,pwsh}"
- "wget * | {sh,bash,zsh,dash,ksh,fish}"
- "wget * | {python*,node,perl,ruby,php,deno,bun,pwsh}"
- "* -d | {sh,bash,zsh,dash,ksh,fish}"
- "* -d | {python*,node,perl,ruby,php,deno,bun,pwsh}"
- "eval *"
- id: destructive
reason: irreversible damage
fs.write: ["~", "/"]
shell:
- "rm * {//,/[*],~/[*],$HOME/[*],$[{]HOME[}]/[*]}"
- "rm -rf --no-preserve-root*"
- "git push --for*"
- "git push -f*"
- "git push * +*"
- "git push * --for*"
- "git push * -f*"
- "git push * -[!o-]*f*"
- "git push * :?*"
- "git push * --de*"
- "git push * -d*"
- "git push * -[!o-]*d*"
- "git reset --hard*"
- "git clean -fdx*"
- "git branch -D *"
- "git stash drop*"
- "git stash clear*"
- "sudo *"
- "mkfs*"
- "dd if=*"
- "shutdown *"
- "reboot"
- id: kernel-self
reason: OpenMoat protects its own policy, hooks and binary
fs.write:
- "~/.moat"
- "~/.claude"
- "~/.codex"
- "~/.cursor"
- "**/.moat"
- "**/.claude"
- "**/.codex"
- "**/.cursor"
- "~/.moat/**"
- "~/.claude/settings.json"
- "~/.claude/settings.local.json"
- "~/.codex/**"
- "~/.cursor/hooks.json"
- "~/.cursor/sandbox.json"
- "**/.claude/settings.json"
- "**/.claude/settings.local.json"
- "**/.cursor/hooks.json"
- "**/.cursor/sandbox.json"
- "**/.codex/hooks.json"
- "**/.moat/**"
- "**/bin/moat"
- "**/bin/moat.exe"
- "**/apps/moat/current"
- "**/apps/moat/*/moat.exe"
shell:
- "moat policy *"
- "moat init*"
- "moat doctor*"
- "moat allow*"
- "moat trust*"
- "moat edit*"
- "*/moat policy *"
- "*/moat init*"
- "*/moat doctor*"
- "*/moat allow*"
- "*/moat trust*"
- "*/moat edit*"
- "moat uninstall*"
- "*/moat uninstall*"
- "moat sandbox sync*"
- "*/moat sandbox sync*"
- "{script,*/script,unbuffer,tmux,*/tmux,screen,*/screen} * moat sandbox sync*"
- "{script,*/script,unbuffer,tmux,*/tmux,screen,*/screen} * */moat sandbox sync*"
- "script * moat {allow,doctor,edit,init,policy,trust,uninstall}*"
- "script * */moat {allow,doctor,edit,init,policy,trust,uninstall}*"
- "script * '*moat {allow,doctor,edit,init,policy,trust,uninstall,sandbox*sync}*'"
- "expect * '*moat {allow,doctor,edit,init,policy,trust,uninstall,sandbox*sync}*'"
- "unbuffer * moat {allow,doctor,edit,init,policy,trust,uninstall}*"
- "unbuffer * */moat {allow,doctor,edit,init,policy,trust,uninstall}*"
- "*/script * moat {allow,doctor,edit,init,policy,trust,uninstall}*"
- "*/script * */moat {allow,doctor,edit,init,policy,trust,uninstall}*"
- "*/script * '*moat {allow,doctor,edit,init,policy,trust,uninstall,sandbox*sync}*'"
- "*/expect * '*moat {allow,doctor,edit,init,policy,trust,uninstall,sandbox*sync}*'"
- "{python*,*/python*} * '*pty*spawn*(*moat*{allow,doctor,edit,init,policy,trust,uninstall,sandbox*sync}*'"
- "{tmux,*/tmux,screen,*/screen} * moat {allow,doctor,edit,init,policy,trust,uninstall}*"
- "{tmux,*/tmux,screen,*/screen} * */moat {allow,doctor,edit,init,policy,trust,uninstall}*"
- "{tmux,*/tmux,screen,*/screen} * '*moat {allow,doctor,edit,init,policy,trust,uninstall,sandbox*sync}*'"
- "{osascript,*/osascript} * '*moat {allow,doctor,edit,init,policy,trust,uninstall,sandbox*sync}*'"
- "{script,*/script,unbuffer,*/unbuffer,tmux,*/tmux,screen,*/screen} * {moat,*/moat}"
- "{script,*/script,tmux,*/tmux,screen,*/screen} * '{moat,*/moat}'*"
- "{expect,*/expect} * '*spawn {moat,*/moat}{;,\n,'}*"
- "{python*,*/python*} * '*pty*spawn*(*\"{moat,*/moat}\"{],)}*'"
- "{osascript,*/osascript} * '*\"{moat,*/moat}\"*'"
- id: shell-rc
reason: edits persist into every future shell session
fs.write: ["~/.zshrc", "~/.bashrc", "~/.bash_profile", "~/.profile", "~/.zprofile", "~/.zshenv"]
- id: cloud-metadata
reason: instance metadata and link-local services hand out cloud credentials
net: ["169.254.*", "fe80:*", "fd00:ec2::254", "100.100.100.200", "metadata.google.internal", "metadata.goog"]
allow:
- id: project-fs
fs.read: ["${project}", "${project}/**"]
fs.write: ["${project}/**", "!${project}/.git/**", "!${project}/.moat/**"]
- id: dev-shell
shell:
- "git status*"
- "git diff*"
- "git log*"
- "git show*"
- "git branch*"
- "git add *"
- "git commit *"
- "git checkout *"
- "git switch *"
- "git fetch*"
- "git pull*"
- "git rebase *"
- "git stash*"
- "ls*"
- "cat *"
- "head *"
- "tail *"
- "grep *"
- "rg *"
- "find *"
- "pwd"
- "echo *"
- "which *"
- "true"
- "jq *"
- "cd"
- "cd *"
- "pushd *"
- "popd"
- "mkdir *"
- "touch *"
- "cp *"
- "mv *"
- "rm *"
- "npm test*"
- "npm run *"
- "pnpm test*"
- "pnpm run *"
- "pnpm build*"
- "pnpm lint*"
- "pnpm typecheck*"
- "pnpm exec *"
- "yarn exec *"
- "yarn test*"
- "yarn run *"
- "yarn build*"
- "yarn lint*"
- "cargo build*"
- "cargo test*"
- "cargo check*"
- "cargo clippy*"
- "cargo fmt*"
- "cargo run*"
- "cargo doc*"
- "cargo bench*"
- "cargo nextest*"
- "cargo tree*"
- "cargo metadata*"
- "go test*"
- "go build*"
- "go vet*"
- "swift test*"
- "swift build*"
- "pytest*"
- "python -m pytest*"
- "python3 -m pytest*"
- "python -m venv *"
- "python3 -m venv *"
- "source .venv/bin/activate $"
- ". .venv/bin/activate $"
- "source venv/bin/activate $"
- ". venv/bin/activate $"
- "make $"
- "make test*"
- "make build*"
- "make check*"
- "make lint*"
- "!rm *-*r*"
- "!rm *-*R*"
- "!git checkout * ."
- "!git checkout * -- *"
- "!git checkout * -f*"
- "!git checkout * --force*"
- "!find * -exec*"
- "!find * -ok*"
- "!find * -delete*"
- "!find * -fprint*"
- "!find * -fls*"
- "!rg * --pre"
- "!rg * --pre=*"
- "!git * --upload-pack*"
- "!git * --receive-pack*"
- "!go * -exec*"
- "!go * -toolexec*"
- "!go * -vettool*"
- "!cargo * --config*"
- "!git rebase * --ex*"
- "!git rebase * --in*"
- "!git rebase * --ed*"
- "!git rebase * --con*"
- "!git rebase * --sk*"
- "!git rebase * --str*"
- "!git rebase * -[ixs]*"
- "!git rebase * -[!-]*[ixs]*"
- "!python* -m venv * --cl*"
- "!python* -m venv * --u*"
- id: dev-readonly
reason: read-only inspection tools and non-secret variables
shell:
- "wc *"
- "diff *"
- "tree*"
- "docker ps*"
- "docker images*"
- "docker logs *"
- "docker version*"
- "gh pr view*"
- "gh pr list*"
- "gh pr diff*"
- "gh pr checks*"
- "gh issue view*"
- "gh issue list*"
- "gh run list*"
- "gh run view*"
- "gh repo view*"
- "!* --output*"
- "!* -o *"
env.read: ["PATH", "HOME", "USER", "SHELL", "PWD", "LANG", "TERM", "TMPDIR", "EDITOR"]
- id: dev-tools
shell:
- "tsc*"
- "eslint *"
- "prettier *"
- "biome *"
- "vitest*"
- "jest*"
- "mocha*"
- "ruff *"
- "black *"
- "mypy *"
- "golangci-lint*"
- id: text-tools
reason: read-only text tools; the classifier reads their options and scripts (shell/text.rs)
shell:
- "sed *"
- "awk *"
- "sort *"
- "uniq *"
- "cut *"
- "!{sed,awk,sort,uniq,cut} @*"
- id: registries
net:
- "api.github.com"
- "github.com"
- "registry.npmjs.org"
- "crates.io"
- "static.crates.io"
- "index.crates.io"
- "proxy.golang.org"
- "pypi.org"
- "files.pythonhosted.org"
- id: safe-mcp
mcp: ["mcp__github__search_*", "mcp__github__get_*", "mcp__filesystem__read_*", "mcp__filesystem__list_*"]
ask:
- id: installs
reason: new dependency
shell: ["npm install *", "npm i *", "npm ci*", "pnpm add *", "pnpm install*", "pnpm dlx *", "yarn add *", "yarn install*", "yarn dlx *", "npx *", "npm exec *", "npm x *", "pip install *", "pip3 install *", "cargo add *", "cargo install *", "brew install *", "gem install *"]
- id: push
reason: publishes to a remote
shell: ["git push *", "npm publish*", "pnpm publish*", "yarn publish*", "cargo publish*", "gh release *"]
- id: local-net
reason: local service; may expose a control API (Docker, databases, cloud agents)
net: ["localhost", "127.0.0.1", "::1"]
executables: {}
sandbox:
read_roots:
- /usr
- /bin
- /sbin
- /lib
- /lib64
- /etc
- /opt
- /nix
- /snap
- /System
- /Library
- /Applications/Xcode.app
- /private/etc
- /tmp
- /private/tmp
- /var/folders
- /private/var/folders
- ~/.gitconfig
- ~/.cargo
- ~/.rustup
- ~/.npm
- ~/.nvm
- ~/.pyenv
- ~/.local/bin
- ~/go