auto-permission-system 0.0.0-stage → 2.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +74 -0
- package/LICENSE +22 -0
- package/README.md +258 -2
- package/banner.png +0 -0
- package/extensions/guard.ts +386 -0
- package/extensions/permission-mode.ts +122 -0
- package/extensions/sandbox.ts +208 -0
- package/package.json +76 -4
- package/sandbox.default.json +129 -0
- package/sandbox.example.json +92 -0
- package/skills/auto-permission-system/SKILL.md +144 -0
- package/src/core/grep-filter.ts +45 -0
- package/src/core/index.ts +16 -0
- package/src/core/policy/classify.ts +30 -0
- package/src/core/policy/commands.ts +44 -0
- package/src/core/policy/default-file.ts +45 -0
- package/src/core/policy/defaults.ts +10 -0
- package/src/core/policy/fence.ts +136 -0
- package/src/core/policy/files.ts +48 -0
- package/src/core/policy/merge.ts +39 -0
- package/src/core/policy/mode.ts +26 -0
- package/src/core/policy/patterns.ts +89 -0
- package/src/core/trust.ts +214 -0
- package/src/core/user-named.ts +86 -0
- package/src/detect/filename-gate/classify.ts +150 -0
- package/src/detect/filename-gate/index.ts +9 -0
- package/src/detect/filename-gate/patterns.ts +206 -0
- package/src/detect/filename-gate/types.ts +33 -0
- package/src/detect/index.ts +12 -0
- package/src/detect/mcp-gate/constants.ts +6 -0
- package/src/detect/mcp-gate/evaluate.ts +243 -0
- package/src/detect/mcp-gate/index.ts +11 -0
- package/src/detect/mcp-gate/signals.ts +407 -0
- package/src/detect/mcp-gate/types.ts +91 -0
- package/src/detect/mcp-gate/verbs.ts +252 -0
- package/src/detect/sensitive-file-scanner/assignment.ts +305 -0
- package/src/detect/sensitive-file-scanner/constants.ts +91 -0
- package/src/detect/sensitive-file-scanner/content-scan.ts +196 -0
- package/src/detect/sensitive-file-scanner/decoding.ts +153 -0
- package/src/detect/sensitive-file-scanner/entropy.ts +19 -0
- package/src/detect/sensitive-file-scanner/file-scan.ts +234 -0
- package/src/detect/sensitive-file-scanner/index.ts +12 -0
- package/src/detect/sensitive-file-scanner/jwt.ts +70 -0
- package/src/detect/sensitive-file-scanner/keys.ts +98 -0
- package/src/detect/sensitive-file-scanner/patterns.ts +194 -0
- package/src/detect/sensitive-file-scanner/redaction.ts +138 -0
- package/src/detect/sensitive-file-scanner/scoring.ts +125 -0
- package/src/detect/sensitive-file-scanner/types.ts +71 -0
- package/src/detect/sensitive-file-scanner/value-analysis.ts +139 -0
- package/src/detect/tool-output-scanner/constants.ts +23 -0
- package/src/detect/tool-output-scanner/evaluate.ts +170 -0
- package/src/detect/tool-output-scanner/index.ts +20 -0
- package/src/detect/tool-output-scanner/scan.ts +253 -0
- package/src/detect/tool-output-scanner/size.ts +80 -0
- package/src/detect/tool-output-scanner/types.ts +90 -0
- package/src/l1-sandbox/bash-ops.ts +369 -0
- package/src/l1-sandbox/config.ts +166 -0
- package/src/l1-sandbox/manager.ts +73 -0
- package/src/l2-guard/ask.ts +95 -0
- package/src/l2-guard/exposure.ts +32 -0
- package/src/l2-guard/matching.ts +179 -0
- package/src/l2-guard/policy.ts +127 -0
- package/src/l2-guard/prompts.ts +136 -0
- package/src/l2-guard/subagent.ts +37 -0
- package/src/l2-guard/url.ts +34 -0
- package/src/shared/audit.ts +17 -0
- package/src/shared/yolo.ts +82 -0
- package/src/ui/ask-flow.ts +100 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
Entries below [1.0.0] are generated automatically by [semantic-release](https://semantic-release.gitbook.io/) from [Conventional Commits](https://www.conventionalcommits.org/) — do not edit by hand.
|
|
5
|
+
|
|
6
|
+
# [2.0.0](https://github.com/Navin009/auto-permission-system/compare/v1.2.0...v2.0.0) (2026-10-02)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
* fix(policy)!: an untrusted project sandbox.json may only tighten the policy ([94deb76](https://github.com/Navin009/auto-permission-system/commit/94deb763cbaf47c908a7a746cc59a469979f92d9))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* **policy:** explain an untrusted project file in plain words and remember "no" ([0a38470](https://github.com/Navin009/auto-permission-system/commit/0a38470788df9b6eb91a334b48c61cee4f726e9c))
|
|
15
|
+
* **sandbox:** attribute Layer 1 blocks to the right path and never offer / as a grant ([c8c89be](https://github.com/Navin009/auto-permission-system/commit/c8c89bec61a3b7077c71173e36bae343a345ddcd))
|
|
16
|
+
* **sandbox:** make file-name deny patterns match anywhere in the project for bash ([fdd8f22](https://github.com/Navin009/auto-permission-system/commit/fdd8f22fe97f2a3c6c7615b798bea578bbc25f05))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
* **guard:** ask before reading outside the project; a named path runs once ([49e089a](https://github.com/Navin009/auto-permission-system/commit/49e089affa8bf98d9f02163f4b8c9d56e9882516))
|
|
22
|
+
* **guard:** pre-select "no" in the ask-tier prompt and add session grants ([b1e5530](https://github.com/Navin009/auto-permission-system/commit/b1e553030e133f2749ad6214bcf7ac13f6f0695d))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### BREAKING CHANGES
|
|
26
|
+
|
|
27
|
+
* existing project .pi/sandbox.json files are untrusted
|
|
28
|
+
after upgrading. Their deny rules still apply; their allow lists,
|
|
29
|
+
overrides and enabled flag apply after one /security trust per project.
|
|
30
|
+
|
|
31
|
+
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
32
|
+
|
|
33
|
+
# [1.2.0](https://github.com/Navin009/auto-permission-system/compare/v1.1.0...v1.2.0) (2026-10-01)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### Bug Fixes
|
|
37
|
+
|
|
38
|
+
* **deps:** bump @anthropic-ai/sandbox-runtime to ^0.0.78 ([de536c8](https://github.com/Navin009/auto-permission-system/commit/de536c83962d6203700696ae27543d0b9d5dc512))
|
|
39
|
+
* **guard:** enforce the read policy on grep, find and ls ([3b8d992](https://github.com/Navin009/auto-permission-system/commit/3b8d992ebbcd02d87bbe99f7f190fbe8a019d6cf))
|
|
40
|
+
* **guard:** make the absolute-deny tier deny on its own ([bad9249](https://github.com/Navin009/auto-permission-system/commit/bad9249aa5374bc9dde5989bd189a12c5405e9af)), closes [hi#risk](https://github.com/hi/issues/risk)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
### Features
|
|
44
|
+
|
|
45
|
+
* **guard:** two-step select instead of typing "i understand" ([a4b1430](https://github.com/Navin009/auto-permission-system/commit/a4b14304398d5197e7b6d5fa025b9e5726769c0e))
|
|
46
|
+
|
|
47
|
+
# [1.1.0](https://github.com/Navin009/auto-permission-system/compare/v1.0.0...v1.1.0) (2026-07-19)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
### Features
|
|
51
|
+
|
|
52
|
+
* add CLAUDE.md for documentation on pi-secure-it extension and conventions ([b5e6487](https://github.com/Navin009/auto-permission-system/commit/b5e6487c7334be0bc42a7af7dff96a6aaa3a5dcf))
|
|
53
|
+
|
|
54
|
+
# 1.0.0 (2026-07-19)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
### Features
|
|
58
|
+
|
|
59
|
+
* Implement CI/CD workflows with semantic-release, updated dependencies ([f53b39a](https://github.com/Navin009/auto-permission-system/commit/f53b39a8be162d22a1cddca123ae3c00b7dca70a))
|
|
60
|
+
* Update CI configuration and add test script to package.json ([bc43b09](https://github.com/Navin009/auto-permission-system/commit/bc43b09f69a4ef849d39c045c3dd609d316e7728))
|
|
61
|
+
|
|
62
|
+
## [1.0.0] - 2026-07-15
|
|
63
|
+
|
|
64
|
+
### Added
|
|
65
|
+
- **Layer 1** — OS-level bash sandbox via `@anthropic-ai/sandbox-runtime` (`sandbox-exec` on macOS, `bubblewrap` on Linux). Blocks filesystem writes outside `allowWrite`, reads of `denyRead`, and network outside `allowedDomains`.
|
|
66
|
+
- **Layer 2** — In-process tool guard hooking `read`, `write`, `edit`, `fetch_content`, `web_search`, `get_search_content`. Applies the same policy file as Layer 1.
|
|
67
|
+
- **Layer 3** — Subagent posture: stricter network policy when `ctx.hasUI === false` (subagents, `-p` mode, JSON mode). Configurable via `subagent.network`: `allow` (default) | `deny` | `research-only`.
|
|
68
|
+
- **Ask-tier prompts** — Interactive per-call allow/deny dialog with four persistence tiers: this-once, always-for-current-project (file), always-for-current-project (folder), always-for-all-projects (file), always-for-all-projects (folder). Persists to `.pi/sandbox.json` or `~/.pi/agent/extensions/sandbox.json`.
|
|
69
|
+
- **Absolute-deny tier** — Credential material (`~/.ssh`, `~/.gnupg`, `~/.aws`, `*.pem`, `*.key`) requires typing `"i understand"` verbatim; "always" is never available for this tier.
|
|
70
|
+
- **`/security` command** — Shows active policy, project-local overrides, and last 10 audit events.
|
|
71
|
+
- **`/sandbox` command** — Shows current bash sandbox config. `/sandbox reload` live-reloads after manual edits to `sandbox.json`.
|
|
72
|
+
- **Audit log** — Append-only JSONL at `~/.pi/agent/audit.log`. One entry per blocked/allowed/always decision.
|
|
73
|
+
- **`sandbox.example.json`** — Documented reference config showing all available fields.
|
|
74
|
+
- **Skill** — `skills/pi-secure-it/SKILL.md` explains the security model and how to configure it.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hannes
|
|
4
|
+
Copyright (c) 2026 Navin009 (fork modifications)
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,259 @@
|
|
|
1
|
-
#
|
|
1
|
+
# auto-permission-system
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/auto-permission-system)
|
|
4
|
+
[](https://www.npmjs.com/package/auto-permission-system)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
[](https://pi.dev/packages)
|
|
7
|
+
[](https://github.com/Navin009/auto-permission-system/actions/workflows/ci.yml)
|
|
8
|
+
|
|
9
|
+
**A security sandbox, permission system and tool guard for the [Pi coding agent](https://pi.dev).**
|
|
10
|
+
It puts allow/deny rules, interactive ask prompts, secret detection and an audit log around every tool the agent can call — file reads and writes, shell commands, searches and network access — so the agent can work in your repository without reaching your credentials or the wider internet by accident.
|
|
11
|
+
|
|
12
|
+
Enforcement happens in three layers:
|
|
13
|
+
|
|
14
|
+
- **Layer 1** — OS-level bash sandbox (`sandbox-exec` on macOS, `bubblewrap` on Linux) that blocks filesystem writes outside an allow-list, reads of sensitive paths, reads outside the project when `outsideProject.read` gates them, and network egress to unlisted domains.
|
|
15
|
+
- **Layer 2** — In-process tool guard applying the same policy to the tools the OS sandbox can't reach: `read`, `grep`, `find`, `ls`, `write`, `edit`, `fetch_content`, `web_search`, `get_search_content`. `grep` output lines from denied files beneath an allowed search root are removed before the model sees them.
|
|
16
|
+
- **Layer 3** — Subagent posture: optionally drop or restrict network access when running headless (`-p`, JSON mode, subagents).
|
|
17
|
+
|
|
18
|
+
When a tool call is blocked you get an interactive prompt — no need to leave pi and hand-edit config files. Choose *this once*, *always for this project*, or *always for all projects* (file or parent-folder granularity). Decisions are persisted and audited.
|
|
19
|
+
|
|
20
|
+
## Contents
|
|
21
|
+
|
|
22
|
+
- [Install](#install)
|
|
23
|
+
- [Requirements](#requirements)
|
|
24
|
+
- [Configuration](#configuration)
|
|
25
|
+
- [Commands](#commands)
|
|
26
|
+
- [Escape hatches](#escape-hatches)
|
|
27
|
+
- [FAQ](#faq)
|
|
28
|
+
- [Audit log](#audit-log)
|
|
29
|
+
- [Development](#development)
|
|
30
|
+
- [Releasing](#releasing)
|
|
31
|
+
- [License](#license)
|
|
32
|
+
|
|
33
|
+
## Install
|
|
34
|
+
|
|
35
|
+
`auto-permission-system` is a [Pi package](https://pi.dev/packages), so it installs with `pi install` from npm or git:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# From npm (recommended)
|
|
39
|
+
pi install npm:auto-permission-system
|
|
40
|
+
|
|
41
|
+
# From git
|
|
42
|
+
pi install git:github.com/Navin009/auto-permission-system
|
|
43
|
+
|
|
44
|
+
# Try it for one run, without installing
|
|
45
|
+
pi -e npm:auto-permission-system
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Browse it on the [Pi package gallery](https://pi.dev/packages). Installing from npm pins the released version; `pi update --extensions` reconciles to the latest.
|
|
49
|
+
|
|
50
|
+
## Requirements
|
|
51
|
+
|
|
52
|
+
- macOS or Linux
|
|
53
|
+
- macOS: `sandbox-exec` is built in
|
|
54
|
+
- Linux: `bubblewrap`, `socat`
|
|
55
|
+
|
|
56
|
+
## Configuration
|
|
57
|
+
|
|
58
|
+
Policy files are merged in order:
|
|
59
|
+
|
|
60
|
+
| File | Scope |
|
|
61
|
+
| ---- | ----- |
|
|
62
|
+
| `sandbox.default.json` (shipped in this package) | Baseline — used when no other file overrides it |
|
|
63
|
+
| `~/.pi/agent/extensions/sandbox.json` | Global (all projects) |
|
|
64
|
+
| `<cwd>/.pi/sandbox.json` | Project-local (auto-written by ask-tier prompts) |
|
|
65
|
+
|
|
66
|
+
A higher layer only states what it changes; absent keys keep the layer below. A **trusted** project may loosen the baseline; an **untrusted** project (ADR-013) may only tighten it. You do **not** need a global file: the shipped default already turns on the project boundary (`outsideProject.read: "ask"`), the credential `modelDenyRead` list and the full `denyRead` / `denyWrite` lists. Copy `sandbox.example.json` only when you want to start customising.
|
|
67
|
+
|
|
68
|
+
### Key fields
|
|
69
|
+
|
|
70
|
+
```jsonc
|
|
71
|
+
{
|
|
72
|
+
"enabled": true, // set false to disable Layer 2 without --yolo
|
|
73
|
+
"mode": "default", // "default" (rules) | "advanced-secure" (secret detection, ADR-018)
|
|
74
|
+
"network": {
|
|
75
|
+
"allowedDomains": [ // domains fetch_content / get_search_content may reach
|
|
76
|
+
"github.com", "*.github.com",
|
|
77
|
+
"registry.npmjs.org"
|
|
78
|
+
],
|
|
79
|
+
"deniedDomains": [] // explicit block-list (checked before allowedDomains)
|
|
80
|
+
},
|
|
81
|
+
"filesystem": {
|
|
82
|
+
"denyRead": ["~/.ssh", "~/.aws", "~/.pi/agent"], // Layer 1 + Layer 2: no read at all
|
|
83
|
+
"askRead": [".env", ".env.*"], // Layer 1 + Layer 2: ask before reading, not hard-denied (ADR-019)
|
|
84
|
+
"modelDenyRead": ["~/.netrc"], // Layer 2 only: model's read tool blocked; subprocesses ok
|
|
85
|
+
"allowWrite": [".", "/tmp"], // Layer 2: writes only inside these roots
|
|
86
|
+
"denyWrite": [".env", "*.pem"] // Layer 1 + Layer 2: write always blocked
|
|
87
|
+
},
|
|
88
|
+
"subagent": {
|
|
89
|
+
"network": "allow" // "allow" | "deny" | "research-only"
|
|
90
|
+
},
|
|
91
|
+
"commands": {
|
|
92
|
+
"ask": ["printenv", "env", "/proc/*/environ"] // bash: ask before these (they can print env tokens)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Project policy files and trust
|
|
98
|
+
|
|
99
|
+
A folder can have its own `.pi/sandbox.json`. It comes with the folder, for example with a repository that you clone. So auto-permission-system does not trust it automatically (ADR-013).
|
|
100
|
+
|
|
101
|
+
- **Block rules in the file always apply.** They are added to your rules.
|
|
102
|
+
- **Changes that make your security weaker do not apply** until you trust the file. Examples: turn off auto-permission-system, let bash write to `/`, allow more websites.
|
|
103
|
+
- auto-permission-system shows a warning that lists these changes in plain words.
|
|
104
|
+
- **Did you write the file?** Type `/security trust`. auto-permission-system shows the changes and asks you. If you say "No", it does not warn again until the file changes.
|
|
105
|
+
- Trust is for the file as it is now. If the file changes, auto-permission-system asks again.
|
|
106
|
+
- Most folders have no `.pi/sandbox.json`, so you see nothing. Your own "always for CURRENT project" answers keep the file trusted.
|
|
107
|
+
- `/security untrust` removes the trust. `/security` shows the status.
|
|
108
|
+
|
|
109
|
+
### Outside the project
|
|
110
|
+
|
|
111
|
+
Reads outside the working directory can ask before they run (ADR-012):
|
|
112
|
+
|
|
113
|
+
```jsonc
|
|
114
|
+
"filesystem": {
|
|
115
|
+
"outsideProject": {
|
|
116
|
+
"read": "ask", // "allow" (default) | "ask" | "deny"
|
|
117
|
+
"allowRead": ["~/repos", "~/.cargo/registry"]
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Never asked about: the project itself, your `allowWrite` roots, pi's own package (docs, examples) and `allowRead`. `~/.pi/agent` is **not** exempt as a whole: it is in the default `denyRead` (it holds `mcp.json`, which can carry API keys, plus sessions and caches), while `auth.json` stays absolute-denied — add specific paths such as `~/.pi/agent/install` to `outsideProject.allowRead` when a tool must read them without asking. Both layers enforce the boundary. Layer 2 prompts. Layer 1 fences the home directory for `bash` (ADR-014); because the OS layer cannot prompt mid-command, `"ask"` pre-flights the command (ADR-015) — a read-like command that plainly names an outside path (`ls`, `cat`, `find`, `grep`, …) prompts **before** it runs, with `yes — this once` (run without saving) and the persistent `always` options, so **allow returns the complete real output and deny runs nothing** (an explicit refusal, never a silently trimmed listing). Reads the pre-flight can't see (variable expansion, nested shells, scripts) still hit the fence and stay masked. In an interactive session a read runs without a prompt when **you named its full path** (`/…` or `~/…`) in one of your own messages; only messages you typed count, never tool output or the agent's text. Otherwise you get the ask-tier prompt, including `yes — for this session`. Headless runs block (set `allowRead` for paths a harness needs). Writes outside the project are governed by `allowWrite` as before.
|
|
123
|
+
|
|
124
|
+
### Ask-tier prompt
|
|
125
|
+
|
|
126
|
+
`no — block` is pre-selected, so Enter alone blocks. Besides `yes — this once` and the persistent `always` options there is `yes — for this session` (this file, its folder, or this domain), kept in memory until the session ends and never saved (ADR-010).
|
|
127
|
+
|
|
128
|
+
Every prompt waits **10 seconds** by default. If you do not answer, it resolves to the safe default: **block / deny**.
|
|
129
|
+
|
|
130
|
+
### File-name patterns
|
|
131
|
+
|
|
132
|
+
An entry without `/` or `~` (`.env`, `*.key`) is a file name. pi's own tools (Layer 2) match it anywhere on disk; bash (Layer 1) matches it anywhere under the project directory, so `packages/api/.env` is covered too. Use a full path (`~/other/.env`) to cover a file outside the project for bash.
|
|
133
|
+
|
|
134
|
+
### Permission modes
|
|
135
|
+
|
|
136
|
+
`mode` selects how much pi inspects, on top of the rules:
|
|
137
|
+
|
|
138
|
+
- **`default`** (shipped) — rules only: sandbox.json paths, domains, and commands. Nothing inspects file contents.
|
|
139
|
+
- **`advanced-secure`** (recommended) — adds secret/credential detection:
|
|
140
|
+
- **File reads:** a filename that looks like a credential store asks before the read.
|
|
141
|
+
- **MCP calls:** `mcp__<server>__<tool>` calls are classified; a risky (mutating/destructive) call asks before it runs.
|
|
142
|
+
- **Tool/command/file output:** before any output reaches the model, a secret-like hit shows `⚠ Sensitive information detected`, the file, and each detected line as `lineNo: text`, and the question **Should the AI be allowed to see it?** with two choices — **No, keep private** or **Yes, allow**. A bare `key` counts only when the value looks machine-generated: `key=<random>` asks, while `key=value`, `key=subagent.network`, and code such as `const key = x` stay clean. No, keep private withholds the output and tells the model plainly that the output was withheld because it may contain sensitive information, so the model does not mistake it for a failure or an empty result. Esc or timeout keeps it private.
|
|
143
|
+
|
|
144
|
+
Detection can only **add** asks or blocks; it never loosens a rule. The mode is layered like every other key: an untrusted project may opt *in* to `advanced-secure`, but only a trusted project (or the global file) may turn it off.
|
|
145
|
+
|
|
146
|
+
Change it with `/permission-mode`; `default` / `advanced-secure` are saved to the global `sandbox.json` and reflected in the footer's single sandbox chip: `Sandbox: 🧠 N domains, M paths` for `advanced-secure`, `Sandbox: 🔒 N domains, M paths` for `default`.
|
|
147
|
+
|
|
148
|
+
The third choice, **YOLO**, turns every layer off. It is a persisted mode like the others — `setPolicyMode()` writes `mode: "yolo"` to the global `sandbox.json`, so the next session starts that way too. The chip reads `⚠️ YOLO — all security layers disabled`, and it is one pick in the same menu. Pick `Default` or `Advanced Secure` to turn the layers back on (ADR-020).
|
|
149
|
+
|
|
150
|
+
### Commands that print secrets
|
|
151
|
+
|
|
152
|
+
Bash commands that dump the environment can print the API tokens pi runs on. `commands.ask` lists them, and Layer 1 asks before running one (`Block` / `Allow once`); deny runs nothing (ADR-017). An entry without `/` is a command name (matched on the head of each `;`/`&&`/`|` segment); an entry with a path is globbed against every path token, so any reader of the per-process environ file is caught. The shipped default is `["printenv", "env", "/proc/*/environ"]`.
|
|
153
|
+
|
|
154
|
+
### Sensitive reads ask by default
|
|
155
|
+
|
|
156
|
+
`askRead` lists paths that **prompt** instead of being hard-denied (ADR-019). The shipped default asks for `.env` and `.env.*`, in both layers: the model's `read` tool asks, and the bash pre-flight asks before a command that plainly reads the file. No answer (Esc or the 10s timeout) blocks, and headless runs block. `denyRead` still wins over `askRead`, so put a path in `denyRead` to hard-deny it. The credential tier (`~/.ssh`, `~/.aws`, `*.pem`, `*.key`, `~/.gnupg`, `auth.json`) stays hard.
|
|
157
|
+
|
|
158
|
+
### Absolute-deny tier
|
|
159
|
+
|
|
160
|
+
Access to `~/.ssh`, `~/.gnupg`, `~/.aws`, `*.pem`, `*.key` and pi's own `~/.pi/agent/auth.json` is always a high-risk block. Allowing one call takes two menus, each with "block" pre-selected: pick *allow this ONE call*, then confirm with *Yes*. Pressing Enter twice blocks. The "always" option is never offered (ADR-009).
|
|
161
|
+
|
|
162
|
+
### A policy file that does not parse
|
|
163
|
+
|
|
164
|
+
`sandbox.json` is strict JSON: no comments, no trailing commas. If a file does not parse, both layers skip it and use the built-in defaults for it. Layer 2 then shows an error at session start and writes `policy-parse-error` to the audit log. The "always" prompts refuse to write to a file they cannot parse, so a hand-written policy is never replaced.
|
|
165
|
+
|
|
166
|
+
## Commands
|
|
167
|
+
|
|
168
|
+
| Command | Description |
|
|
169
|
+
|---------|-------------|
|
|
170
|
+
| `/security` | Show Layer 2 policy, project-local overrides, last 10 audit events |
|
|
171
|
+
| `/sandbox` | Show Layer 1 (bash sandbox) config |
|
|
172
|
+
| `/sandbox reload` | Live-reload sandbox after manual edits to `sandbox.json` |
|
|
173
|
+
| `/permission-mode` | Choose the permission mode: Default (rules), Advanced Secure (secret detection), or YOLO (all layers off). Saved to the global `sandbox.json`. |
|
|
174
|
+
|
|
175
|
+
## Escape hatches
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
pi --yolo # disables ALL layers globally (visible warning banner)
|
|
179
|
+
pi --no-sandbox # alias for --yolo
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Mid-session, `/permission-mode` → **YOLO** disables every layer in place (no restart); it is saved to the global `sandbox.json` like the other modes, and choosing Default or Advanced Secure brings the layers back (ADR-020). `pi --yolo` remains a per-run flag and writes nothing.
|
|
183
|
+
|
|
184
|
+
## Audit log
|
|
185
|
+
|
|
186
|
+
Every block/allow/always decision is appended to `~/.pi/agent/audit.log` as a JSON line:
|
|
187
|
+
|
|
188
|
+
```jsonc
|
|
189
|
+
{
|
|
190
|
+
"ts": "2026-07-15T10:00:00.000Z",
|
|
191
|
+
"layer": 2,
|
|
192
|
+
"tool": "write",
|
|
193
|
+
"subject": "/Users/you/project/secret.pem",
|
|
194
|
+
"reason": "denyWrite matched \"*.pem\"",
|
|
195
|
+
"decision": "no",
|
|
196
|
+
"cwd": "/Users/you/project"
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## FAQ
|
|
201
|
+
|
|
202
|
+
### How do I allow the agent to reach a new domain?
|
|
203
|
+
Add it to `network.allowedDomains` in a policy file (global `~/.pi/agent/extensions/sandbox.json` or project `<cwd>/.pi/sandbox.json`), or just run the tool once and pick an **always** option in the ask prompt — that writes the domain to the project file for you.
|
|
204
|
+
|
|
205
|
+
### How do I allow writes to another folder?
|
|
206
|
+
Add the folder to `filesystem.allowWrite`. Relative paths (`.`, `/tmp`) resolve from the project root.
|
|
207
|
+
|
|
208
|
+
### Why was my tool call or command blocked?
|
|
209
|
+
Run `/security` to see the active Layer 2 policy and the last 10 audit events; run `/sandbox` for the Layer 1 bash sandbox config. The audit log at `~/.pi/agent/audit.log` records the rule that matched (`reason`).
|
|
210
|
+
|
|
211
|
+
### How do I turn the sandbox off temporarily?
|
|
212
|
+
`pi --yolo` (alias `--no-sandbox`) for a single run, or `/permission-mode` → **YOLO** mid-session. YOLO is persisted like the other modes; pick Default or Advanced Secure to re-enable the layers.
|
|
213
|
+
|
|
214
|
+
### Why does `.env` (or my SSH key) get flagged while other files do not?
|
|
215
|
+
`.env` and `.env.*` are in the shipped `askRead` list, so reads **prompt** by default. The absolute-deny tier (`~/.ssh`, `~/.gnupg`, `~/.aws`, `*.pem`, `*.key`, pi's `auth.json`) always needs a two-step confirmation. Add paths to `denyRead` to hard-deny, or to `askRead` to prompt instead of block.
|
|
216
|
+
|
|
217
|
+
### How is this different from just using `--yolo`?
|
|
218
|
+
`--yolo` removes every guard for one run. `auto-permission-system` is the guard: it decides what runs, prompts when it is unsure, and records the decision. Use `/permission-mode` to switch between **Default** (rules only), **Advanced Secure** (rules + secret/credential detection, recommended) and **YOLO**.
|
|
219
|
+
|
|
220
|
+
### Does it work on Windows?
|
|
221
|
+
No. Layer 1 needs `sandbox-exec` (macOS, built in) or `bubblewrap` + `socat` (Linux). Layer 2 is platform-independent.
|
|
222
|
+
|
|
223
|
+
### Where do the prompts persist my answers?
|
|
224
|
+
Project answers go to `<cwd>/.pi/sandbox.json`; global answers go to `~/.pi/agent/extensions/sandbox.json`. Session-only grants live in memory and are never written to disk.
|
|
225
|
+
|
|
226
|
+
## Development
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
git clone https://github.com/Navin009/auto-permission-system
|
|
230
|
+
cd auto-permission-system
|
|
231
|
+
npm install # installs typescript for typecheck
|
|
232
|
+
npm run typecheck # type-checks against pi's bundled .d.ts files
|
|
233
|
+
pi -e . # load extension for the current session only
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Releasing
|
|
237
|
+
|
|
238
|
+
Releases are fully automated with [semantic-release](https://semantic-release.gitbook.io/), driven by [Conventional Commits](https://www.conventionalcommits.org/) on `main`:
|
|
239
|
+
|
|
240
|
+
- `fix: ...` → patch release
|
|
241
|
+
- `feat: ...` → minor release
|
|
242
|
+
- `feat!: ...` or a `BREAKING CHANGE:` footer → major release
|
|
243
|
+
- `chore:`, `docs:`, `refactor:`, `test:`, `ci:` etc. → no release by themselves
|
|
244
|
+
|
|
245
|
+
Commit messages on pull requests are checked by `commitlint` (`.github/workflows/commitlint.yml`). On every push to `main`, `.github/workflows/release.yml` runs `semantic-release`, which:
|
|
246
|
+
|
|
247
|
+
1. Determines the next version from commits since the last release.
|
|
248
|
+
2. Generates release notes and prepends them to `CHANGELOG.md`.
|
|
249
|
+
3. Creates the `vX.Y.Z` git tag and GitHub release.
|
|
250
|
+
4. Bumps `package.json` and commits `CHANGELOG.md`/`package.json` back to `main` (`chore(release): ... [skip ci]`).
|
|
251
|
+
5. Publishes to npm (`npm publish --provenance`) — **only when the repository variable `NPM_PUBLISH` is `true`**.
|
|
252
|
+
|
|
253
|
+
npm publishing is opt-in (`npmPublish: process.env.NPM_PUBLISH === 'true'` in `.releaserc.cjs`, wired through `.github/workflows/release.yml`), and the GitHub plugin runs before the npm plugin so a failing registry publish can never stop the GitHub Release from being created.
|
|
254
|
+
|
|
255
|
+
See **[PUBLISHING.md](https://github.com/Navin009/auto-permission-system/blob/main/PUBLISHING.md)** for the full first-publish and npm Trusted Publishing checklist, and for how the package becomes searchable on the [Pi package gallery](https://pi.dev/packages). Nothing is needed locally beyond writing conventional commit messages — just merge to `main`.
|
|
256
|
+
|
|
257
|
+
## License
|
|
258
|
+
|
|
259
|
+
MIT
|
package/banner.png
ADDED
|
Binary file
|