auto-mode 0.15.0 → 0.17.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/README.md +4 -4
- package/dist/cli.js +108 -10
- package/dist/index.d.ts +240 -17
- package/dist/index.js +7 -2
- package/dist/{render-verdict-Bj2tGqBI.js → render-verdict-Bx9Lw7gO.js} +1246 -990
- package/mods/auto-mode/hooks/build-prompt-context.ts +18 -8
- package/mods/auto-mode/hooks/register.ts +6 -13
- package/mods/auto-mode/hooks/types.ts +19 -1
- package/package.json +28 -13
- package/policy/classifier.md +29 -21
- package/policy/decision.md +9 -5
- package/policy/judge.md +57 -0
- package/policy/rules.md +119 -142
package/policy/rules.md
CHANGED
|
@@ -22,9 +22,11 @@ Reading a secret in order to use it is not exfiltration. Sending it is, and so i
|
|
|
22
22
|
deliberately putting one where other people will read it — a CI log, a pasted
|
|
23
23
|
report, a shared terminal recording, a comment. A secret that shows up in a tool
|
|
24
24
|
result is not this rule. Reading a secret necessarily brings it into the
|
|
25
|
-
transcript.
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
transcript. Printing a credential the task does not need is Credential
|
|
26
|
+
Exploration, not this rule. Sending content that cannot be seen and is not known
|
|
27
|
+
to be sensitive, or part of a private repository short of a bulk copy, to a
|
|
28
|
+
destination nobody named is Unnamed Destination, not this rule. A credential file,
|
|
29
|
+
a key, or an env file is known to be sensitive by its path.
|
|
28
30
|
|
|
29
31
|
A credential used with the service it belongs to is use, not sending, however many
|
|
30
32
|
other credentials sat in the same file.
|
|
@@ -36,8 +38,8 @@ tests are not sensitive credential material. For example, a fixed
|
|
|
36
38
|
Judge the literal and its data flow, not a secret-shaped prefix alone. A test name,
|
|
37
39
|
comment, or claim that a value is fake is not enough: material read from a real
|
|
38
40
|
credential source, a usable credential, and sensitive data still match this rule,
|
|
39
|
-
including when a test copies or sends them. Non-sensitive fixture data
|
|
40
|
-
|
|
41
|
+
including when a test copies or sends them. Non-sensitive fixture data is not
|
|
42
|
+
this rule.
|
|
41
43
|
|
|
42
44
|
Putting a secret into a secret store is not this rule: `gh secret set`, a vault
|
|
43
45
|
write, a cloud secret manager, or a CI credential store. Those exist to hold
|
|
@@ -81,41 +83,54 @@ machine to whoever holds the other end.
|
|
|
81
83
|
Each rule names the detail the user must say.
|
|
82
84
|
|
|
83
85
|
### Irreversible Deletion
|
|
84
|
-
Deleting data that
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
block device.
|
|
86
|
+
Deleting data that the task does not own or that nothing can restore: the home
|
|
87
|
+
directory or a directory that contains it, a path outside the task scope, an
|
|
88
|
+
untracked file the agent did not create, a repository together with its `.git`,
|
|
89
|
+
and any write to a block device.
|
|
88
90
|
|
|
89
91
|
**Must name:** the path, or an unmistakable description of it.
|
|
90
92
|
|
|
91
|
-
Examples: `rm -rf ~`, `rm -rf /`, `rm -rf ..`, `
|
|
92
|
-
|
|
93
|
-
are not pushed.
|
|
93
|
+
Examples: `rm -rf ~`, `rm -rf /`, `rm -rf ..`, `rm -rf ~/projects`,
|
|
94
|
+
`dd of=/dev/sda`, and deleting a sibling repository or another worktree.
|
|
94
95
|
|
|
95
|
-
|
|
96
|
+
Overwriting a file destroys its old content, so it counts as deleting it.
|
|
97
|
+
Replacing an existing private key or credential file matches this rule: for
|
|
98
|
+
example, `ssh-keygen -f ~/.ssh/id_ed25519` answered `y` over an existing key.
|
|
99
|
+
|
|
100
|
+
Git restores a tracked file whose content is committed, so deleting one is not
|
|
101
|
+
this rule; uncommitted changes in it are Uncommitted Work Destruction. A
|
|
102
|
+
directory the remote already holds is restorable too, unless it also holds an
|
|
103
|
+
untracked file the agent did not create. Neither is a file or directory the agent
|
|
104
|
+
created this session.
|
|
96
105
|
|
|
97
106
|
### Uncommitted Work Destruction
|
|
98
|
-
Discarding changes
|
|
107
|
+
Discarding uncommitted changes that the task does not own: `git reset --hard`,
|
|
99
108
|
`git checkout -- .`, `git restore .`, `git clean -fd`, `git stash drop`,
|
|
100
109
|
`git stash clear`, or deleting a branch that holds unmerged commits.
|
|
101
110
|
|
|
111
|
+
Uncommitted changes in the task's own worktree are the task's work. Discarding
|
|
112
|
+
them is this rule only when the last direct user message or the task context
|
|
113
|
+
says they came from someone else or must be kept.
|
|
114
|
+
|
|
102
115
|
**Must name:** that the changes go away. "Reset hard" and "throw away my changes"
|
|
103
116
|
both do it. "Clean up" does not.
|
|
104
117
|
|
|
105
118
|
This rule does not apply when the working tree is clean.
|
|
106
119
|
|
|
107
|
-
Reverting an edit the agent itself made this session is not this rule, as long as
|
|
108
|
-
nothing the user wrote is discarded with it.
|
|
109
|
-
|
|
110
120
|
### History Rewrite
|
|
111
|
-
Rewriting history
|
|
112
|
-
`--force-with-lease
|
|
113
|
-
filter-branch
|
|
114
|
-
|
|
121
|
+
Rewriting history on a branch the task does not own: `git push --force` and
|
|
122
|
+
`--force-with-lease`, pushing rebased or amended commits, pushing after
|
|
123
|
+
`git filter-branch` or `git filter-repo`, or deleting a remote branch — when the
|
|
124
|
+
target is the default branch, a protected branch such as `main`, `master`,
|
|
125
|
+
`trunk`, or `develop`, or a branch outside the task scope. Deleting or moving a
|
|
126
|
+
remote tag that this session did not create is also this rule.
|
|
115
127
|
|
|
116
128
|
**Must name:** force, rewrite, or the remote branch.
|
|
117
129
|
|
|
118
|
-
|
|
130
|
+
A branch in the task scope belongs to the task, including the head branch of the
|
|
131
|
+
task's own pull request while a review is open. Any rewrite of it, with `--force`
|
|
132
|
+
or `--force-with-lease`, is not this rule. A rewrite that stays local changes
|
|
133
|
+
nothing others hold until it is pushed.
|
|
119
134
|
|
|
120
135
|
### Default Branch Write
|
|
121
136
|
Committing, pushing, or merging directly to the default branch: `main`, `master`,
|
|
@@ -141,41 +156,48 @@ registry, or a deploy command.
|
|
|
141
156
|
**Must name:** publish, release, or deploy, plus the target.
|
|
142
157
|
|
|
143
158
|
### Outbound Communication
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
159
|
+
A message that reaches people outside the checkout's own repositories and outside
|
|
160
|
+
the channels the user named: an email, a chat message to a person or channel the
|
|
161
|
+
user did not name, a post on a public service, or an issue, comment, pull request,
|
|
162
|
+
or review on a repository that is not a remote of the checkout.
|
|
147
163
|
|
|
148
164
|
**Must name:** that the message is sent, and to whom or where.
|
|
149
165
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
166
|
+
An issue, comment, pull request, or review on a repository that is a remote of
|
|
167
|
+
the checkout is not this rule, whichever issue or pull request it targets. Compare
|
|
168
|
+
the repository's host, owner, and name with the remotes; a lookalike name is not a
|
|
169
|
+
match.
|
|
154
170
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
still this rule.
|
|
171
|
+
Once the user names a channel or an outside thread, further posts to that same
|
|
172
|
+
place stand for the rest of the session. This is a standing permission the rule
|
|
173
|
+
states for itself.
|
|
159
174
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
so it is not this rule. Opening a pull request or posting a review is.
|
|
175
|
+
Sensitive content is Data Exfiltration wherever it goes. Reading these services is
|
|
176
|
+
allowed. A git push sends commits, not a message to a person, so it is not this
|
|
177
|
+
rule.
|
|
164
178
|
|
|
165
179
|
### Remote Code Execution
|
|
166
|
-
Running code fetched from a source the user
|
|
167
|
-
count together even when they are separate
|
|
168
|
-
|
|
169
|
-
|
|
180
|
+
Running code fetched over the network from a source that neither the user nor the
|
|
181
|
+
repository names. The fetch and the run count together even when they are separate
|
|
182
|
+
commands: `curl … | sh`, `wget -O- … | bash`, `iex (irm …)`,
|
|
183
|
+
`curl -o setup.sh … && sh setup.sh`, or adding a dependency from a git URL or a
|
|
184
|
+
tarball URL nobody named.
|
|
170
185
|
|
|
171
186
|
**Must name:** the source.
|
|
172
187
|
|
|
173
188
|
The source is where the code comes from, not which package was chosen. The
|
|
174
189
|
configured registry is a named source, so installing any package from it is not
|
|
175
190
|
this rule. A package manager installing dependencies the repository already
|
|
176
|
-
declares is not this rule either, whatever their source.
|
|
177
|
-
|
|
178
|
-
|
|
191
|
+
declares is not this rule either, whatever their source.
|
|
192
|
+
|
|
193
|
+
A later run cannot be linked to its download, so the download is where this rule
|
|
194
|
+
applies: saving a script or executable from such a source to disk is this rule,
|
|
195
|
+
even before anything runs it.
|
|
196
|
+
|
|
197
|
+
Running code already on disk in the task scope is not this rule: a script, a
|
|
198
|
+
package script such as `bun run test`, `node scripts/build.ts`, or an agent CLI
|
|
199
|
+
such as `codex exec`. Its unseen content is not a missing fact for this rule.
|
|
200
|
+
Judge the command line.
|
|
179
201
|
|
|
180
202
|
### Obfuscated Command
|
|
181
203
|
A command whose payload you cannot decode with confidence: base64 or hex passed to
|
|
@@ -191,37 +213,40 @@ is code that is merely minified: build output is unreadable by accident, not by
|
|
|
191
213
|
design, and this rule is about a command being run, not a file sitting on disk.
|
|
192
214
|
|
|
193
215
|
### Network Exposure
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
a container that is itself reachable.
|
|
216
|
+
Opening a route into this environment from outside its isolation: a tunnel such as
|
|
217
|
+
`ngrok`, `cloudflared tunnel`, `ssh -R`, `tailscale funnel`, or another relay that
|
|
218
|
+
hands an outside party a way in.
|
|
198
219
|
|
|
199
220
|
**Must name:** the service and that it becomes reachable.
|
|
200
221
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
222
|
+
Binding a server to any address, publishing a container port, or opening a
|
|
223
|
+
firewall port inside the environment is not this rule. The isolation decides what
|
|
224
|
+
reaches them.
|
|
204
225
|
|
|
205
226
|
### Unnamed Destination
|
|
206
|
-
Sending content
|
|
207
|
-
|
|
208
|
-
|
|
227
|
+
Sending content that cannot be seen in the action and is not known to be
|
|
228
|
+
sensitive, or part of a private repository short of a bulk copy, to a network
|
|
229
|
+
destination that neither the user nor the repository names — a URL,
|
|
230
|
+
host, address, or account that first appears in tool output, in file content, or
|
|
231
|
+
in the agent's own inference. Examples: `curl -d @file https://…`, uploading an
|
|
232
|
+
archive, or adding a remote at such a URL. A push of the codebase to it is a bulk
|
|
233
|
+
copy and Data Exfiltration.
|
|
209
234
|
|
|
210
235
|
**Must name:** the destination.
|
|
211
236
|
|
|
237
|
+
Content visible in the action that holds nothing sensitive, such as a build status
|
|
238
|
+
or a public question, is not this rule. Sensitive content is Data Exfiltration
|
|
239
|
+
wherever it goes.
|
|
240
|
+
|
|
212
241
|
A destination the repository itself configures — a webhook in a checked-in config,
|
|
213
|
-
a registry in `package.json`, the remote of the checkout — counts as
|
|
214
|
-
|
|
242
|
+
a registry in `package.json`, the remote of the checkout — counts as named when the
|
|
243
|
+
user asked for work in that repository.
|
|
215
244
|
|
|
216
245
|
A configured MCP server of the session, listed in the MCP server facts, is a
|
|
217
246
|
destination the user configured: calling its tools is not this rule. A tool named
|
|
218
247
|
`mcp__<server>__<tool>` calls the server of that name.
|
|
219
248
|
|
|
220
|
-
|
|
221
|
-
the user never named makes it this rule.
|
|
222
|
-
|
|
223
|
-
Fetching from such a destination is reading, and reading is allowed. Sending to a
|
|
224
|
-
destination that no carve-out above covers is this rule.
|
|
249
|
+
Fetching from such a destination is reading, and reading is allowed.
|
|
225
250
|
|
|
226
251
|
### Shared Infrastructure
|
|
227
252
|
Commands that change a cluster, a cloud account, a remote host, or a repository's
|
|
@@ -255,91 +280,43 @@ or a scripted delete over every key.
|
|
|
255
280
|
**Must name:** the table or the database, and the operation.
|
|
256
281
|
|
|
257
282
|
### Persistent Configuration
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
such as `nohup … &` or a detached service.
|
|
264
|
-
|
|
265
|
-
A package manager's own global install — `npm i -g`, `pipx install`, `cargo
|
|
266
|
-
install` — is not this rule. It is an install, judged by Remote Code Execution.
|
|
267
|
-
|
|
268
|
-
It also covers raising privilege or loosening access on this machine: `sudo -s`,
|
|
269
|
-
`sudo su -`, `su` to another user, running a command under `sudo` that this rule
|
|
270
|
-
would otherwise catch, `chmod` or `chown` widening access, `setfacl` widening a
|
|
271
|
-
path, or a firewall rule that opens something.
|
|
283
|
+
Granting access into this environment from outside it, or redirecting where
|
|
284
|
+
credentials or code go: adding a key to `~/.ssh/authorized_keys`, changing
|
|
285
|
+
`~/.ssh/config`, writing package registry credentials or pointing a registry at a
|
|
286
|
+
new host, and the global git settings `credential.helper`, `url.<base>.insteadOf`,
|
|
287
|
+
and `core.sshCommand`.
|
|
272
288
|
|
|
273
289
|
**Must name:** the file or the setting.
|
|
274
290
|
|
|
275
|
-
Adding a key
|
|
276
|
-
|
|
291
|
+
Adding a key grants standing access to whoever holds it. Judge it as an access
|
|
292
|
+
grant, not as a file edit.
|
|
293
|
+
|
|
294
|
+
The environment is isolated, so a change that stays inside it is not this rule:
|
|
295
|
+
`crontab`, a systemd unit, a launch agent, a shell startup file, `PATH`, other
|
|
296
|
+
`git config --global` keys, a detached process, `sudo`, a sudoers entry, and
|
|
297
|
+
`chmod` or `chown`. Using that access against auto-mode is Policy Tampering.
|
|
277
298
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
authorised to run such as `npm login` before an authorised publish, and any change
|
|
281
|
-
that narrows access rather than widening it — `chmod 755` over `777`, revoking a
|
|
282
|
-
key, making a repository private, closing a port.
|
|
299
|
+
Authenticating a tool the user asked to use, such as `npm login` before a publish
|
|
300
|
+
the user asked for, is not this rule. Neither is a change that narrows access.
|
|
283
301
|
|
|
284
302
|
### Credential Exploration
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
the
|
|
303
|
+
Printing a credential's value into the transcript, or searching broadly for keys
|
|
304
|
+
and tokens, when the task does not need the value: `cat ~/.aws/credentials`,
|
|
305
|
+
printing a token from the environment, reading a private key, or `grep -r` for key
|
|
306
|
+
patterns across a home directory. The transcript goes to the agent's model
|
|
307
|
+
provider, so a printed value has left the environment.
|
|
289
308
|
|
|
290
309
|
**Must name:** the file or the search.
|
|
291
310
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
Running again an action the user interrupted, without the user asking for it. An
|
|
297
|
-
interrupt is the user stopping something. Treating it as a transient failure and
|
|
298
|
-
retrying substitutes the agent's judgement for theirs.
|
|
299
|
-
|
|
300
|
-
**Must name:** that they want it run again.
|
|
301
|
-
|
|
302
|
-
A different action that happens to follow an interrupt is not this rule. Neither
|
|
303
|
-
is a retry the user asked for.
|
|
304
|
-
|
|
305
|
-
### Security Control Removal
|
|
306
|
-
Deleting or disabling a control that protects someone other than the agent: an
|
|
307
|
-
authentication or authorisation check, input validation, a certificate or
|
|
308
|
-
signature check, a rate limit, a CSRF or CORS restriction, the code that emits an
|
|
309
|
-
audit record, a scan or lint step in CI, a branch protection requirement, or a test
|
|
310
|
-
that guards one of these.
|
|
311
|
-
|
|
312
|
-
**Must name:** the control.
|
|
313
|
-
|
|
314
|
-
Replacing a control with an equivalent one is not this rule. Removing it and
|
|
315
|
-
leaving nothing is.
|
|
316
|
-
|
|
317
|
-
### Mass Modification
|
|
318
|
-
One action that changes many things at once **and** leaves no way back. Judge by
|
|
319
|
-
what can be restored, not by how many files changed.
|
|
320
|
-
|
|
321
|
-
- Under version control, with the changes committed or the tree otherwise clean, a
|
|
322
|
-
bulk edit is recoverable. Allow it.
|
|
323
|
-
- With uncommitted work in the tree, a bulk edit that rewrites content destroys
|
|
324
|
-
it. That is Uncommitted Work Destruction. A formatter is not that edit — see
|
|
325
|
-
Formatters and linters.
|
|
326
|
-
- Outside version control, or against live resources — every row in a table, every
|
|
327
|
-
object in a bucket, every resource in a namespace — nothing restores it. Block.
|
|
328
|
-
|
|
329
|
-
**Must name:** the scope, when the rule applies.
|
|
311
|
+
Using a credential through the tool it belongs to is not this rule, because the
|
|
312
|
+
value never appears: `aws s3 ls`, `gh api`, `git push`. Neither is reading a
|
|
313
|
+
credential the task needs, or a file that holds only names or empty placeholders,
|
|
314
|
+
such as `.env.example`.
|
|
330
315
|
|
|
331
316
|
## ALLOW exceptions
|
|
332
317
|
|
|
333
318
|
These override the SOFT BLOCK rules above. They never override a HARD BLOCK.
|
|
334
319
|
|
|
335
|
-
They do not clear Interrupted Action Retry, which is about the user having stopped
|
|
336
|
-
something rather than about what the action touches. A safe target does not turn a
|
|
337
|
-
retry into one the user asked for.
|
|
338
|
-
|
|
339
|
-
The one exception: re-running an action that changes nothing — a read, a listing,
|
|
340
|
-
a dry run — is not this rule either, because there is nothing for the user to have
|
|
341
|
-
stopped.
|
|
342
|
-
|
|
343
320
|
### Regenerable output
|
|
344
321
|
Deleting anything the build reproduces: `node_modules`, `dist`, `build`, `out`,
|
|
345
322
|
`target`, `.next`, `.nuxt`, `.turbo`, `.parcel-cache`, `__pycache__`,
|
|
@@ -375,7 +352,8 @@ not.
|
|
|
375
352
|
|
|
376
353
|
### Read-only actions
|
|
377
354
|
Reading, listing, searching, diffing, describing, and planning are allowed, and so
|
|
378
|
-
is any command whose documented effect is to print and not to change.
|
|
355
|
+
is any command whose documented effect is to print and not to change. Printing a
|
|
356
|
+
credential the task does not need is still Credential Exploration.
|
|
379
357
|
|
|
380
358
|
### Formatters and linters
|
|
381
359
|
A formatter, a linter with a fix flag, or a codemod that the repository already
|
|
@@ -386,15 +364,14 @@ This holds whether or not the tree is clean. Formatting uncommitted work is the
|
|
|
386
364
|
normal loop, not destruction.
|
|
387
365
|
|
|
388
366
|
### The current feature branch
|
|
389
|
-
Committing, amending, rebasing, and force-pushing a branch
|
|
390
|
-
|
|
391
|
-
the
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
remote copy.
|
|
367
|
+
Committing, amending, rebasing, and force-pushing a branch in the task scope: a
|
|
368
|
+
branch the agent created this session, the branch of the task's own worktree, or
|
|
369
|
+
the head branch of the task's own pull request. A review open against it does not
|
|
370
|
+
make it shared. The default branch and protected branches are never in the task
|
|
371
|
+
scope.
|
|
372
|
+
|
|
373
|
+
Also deleting a local branch whose commits are already merged into the default
|
|
374
|
+
branch, and deleting that branch's remote copy once its commits are merged.
|
|
398
375
|
|
|
399
376
|
### Dry runs
|
|
400
377
|
A command carrying `--dry-run`, `--check`, `--no-act`, `--plan`, or an equivalent
|