@pushary/agent-hooks 0.27.0 → 0.28.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.
@@ -2,14 +2,14 @@
2
2
  import {
3
3
  removeClaudeMcpServers,
4
4
  removePusharySettings
5
- } from "../chunk-MVNOP5IZ.js";
5
+ } from "../chunk-76F75WQQ.js";
6
6
  import {
7
7
  execNpm,
8
8
  removeCodexHooks,
9
9
  removeGeminiSettings,
10
10
  removeInstructionBlock
11
- } from "../chunk-WXWHRXDK.js";
12
- import "../chunk-FDR5WYT7.js";
11
+ } from "../chunk-QDPUTE2V.js";
12
+ import "../chunk-YRL4ZB4R.js";
13
13
 
14
14
  // bin/pushary-clean.ts
15
15
  import { existsSync, readFileSync, writeFileSync, rmSync } from "fs";
@@ -32,14 +32,14 @@ import {
32
32
  toCodexWire,
33
33
  toPolicyLookup,
34
34
  waitForAnswer
35
- } from "../chunk-TUILTFLS.js";
35
+ } from "../chunk-NFKYZY74.js";
36
36
  import "../chunk-DWED7BS3.js";
37
37
  import {
38
38
  DECISION_LINE_MAX,
39
39
  effectiveWaitSeconds,
40
40
  hookWaitClamped,
41
41
  hookWaitDeadline
42
- } from "../chunk-FDR5WYT7.js";
42
+ } from "../chunk-YRL4ZB4R.js";
43
43
  import {
44
44
  getApiKey
45
45
  } from "../chunk-NKXSILEW.js";
@@ -4,9 +4,9 @@ import {
4
4
  getMachineId,
5
5
  reportEvent,
6
6
  waitForAnswer
7
- } from "../chunk-TUILTFLS.js";
7
+ } from "../chunk-NFKYZY74.js";
8
8
  import "../chunk-DWED7BS3.js";
9
- import "../chunk-FDR5WYT7.js";
9
+ import "../chunk-YRL4ZB4R.js";
10
10
  import {
11
11
  getApiKey
12
12
  } from "../chunk-NKXSILEW.js";
@@ -12,12 +12,12 @@ import {
12
12
  missingGeminiHookEvents,
13
13
  readCodexMcpAuth,
14
14
  untrustedCodexHookEvents
15
- } from "../chunk-WXWHRXDK.js";
15
+ } from "../chunk-QDPUTE2V.js";
16
16
  import {
17
17
  callMcpTool,
18
18
  sendMcpRequest
19
19
  } from "../chunk-DWED7BS3.js";
20
- import "../chunk-FDR5WYT7.js";
20
+ import "../chunk-YRL4ZB4R.js";
21
21
  import {
22
22
  getBaseUrl
23
23
  } from "../chunk-NKXSILEW.js";
@@ -24,14 +24,14 @@ import {
24
24
  savePendingQuestion,
25
25
  sendNotification,
26
26
  waitForAnswer
27
- } from "../chunk-TUILTFLS.js";
27
+ } from "../chunk-NFKYZY74.js";
28
28
  import "../chunk-DWED7BS3.js";
29
29
  import {
30
30
  DECISION_LINE_MAX,
31
31
  effectiveWaitSeconds,
32
32
  hookWaitClamped,
33
33
  hookWaitDeadline
34
- } from "../chunk-FDR5WYT7.js";
34
+ } from "../chunk-YRL4ZB4R.js";
35
35
  import {
36
36
  getApiKey
37
37
  } from "../chunk-NKXSILEW.js";
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handlePreToolUse
4
- } from "../chunk-VHD3GMZ3.js";
4
+ } from "../chunk-2BHYQCF7.js";
5
5
  import "../chunk-KQYIHZ5E.js";
6
- import "../chunk-TUILTFLS.js";
6
+ import "../chunk-NFKYZY74.js";
7
7
  import "../chunk-DWED7BS3.js";
8
- import "../chunk-FDR5WYT7.js";
8
+ import "../chunk-YRL4ZB4R.js";
9
9
  import "../chunk-NKXSILEW.js";
10
10
 
11
11
  // bin/pushary-hook.ts
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handlePostToolUse
4
- } from "../chunk-TUILTFLS.js";
4
+ } from "../chunk-NFKYZY74.js";
5
5
  import "../chunk-DWED7BS3.js";
6
- import "../chunk-FDR5WYT7.js";
6
+ import "../chunk-YRL4ZB4R.js";
7
7
  import "../chunk-NKXSILEW.js";
8
8
 
9
9
  // bin/pushary-post-hook.ts
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleUserPrompt
4
- } from "../chunk-TUILTFLS.js";
4
+ } from "../chunk-NFKYZY74.js";
5
5
  import "../chunk-DWED7BS3.js";
6
- import "../chunk-FDR5WYT7.js";
6
+ import "../chunk-YRL4ZB4R.js";
7
7
  import "../chunk-NKXSILEW.js";
8
8
 
9
9
  // bin/pushary-prompt-hook.ts
@@ -3,7 +3,7 @@ import {
3
3
  addClaudeMcpServer,
4
4
  addPusharyHooks,
5
5
  addPusharyToolPermissions
6
- } from "../chunk-MVNOP5IZ.js";
6
+ } from "../chunk-76F75WQQ.js";
7
7
  import {
8
8
  GEMINI_HOOK_BINARY,
9
9
  addCodexHookTrust,
@@ -16,14 +16,14 @@ import {
16
16
  renderAgentInstructions,
17
17
  renderProjectAgentInstructions,
18
18
  writeInstructionBlock
19
- } from "../chunk-WXWHRXDK.js";
19
+ } from "../chunk-QDPUTE2V.js";
20
20
  import {
21
21
  reportEvent
22
- } from "../chunk-TUILTFLS.js";
22
+ } from "../chunk-NFKYZY74.js";
23
23
  import "../chunk-DWED7BS3.js";
24
24
  import {
25
25
  isValidApiKey
26
- } from "../chunk-FDR5WYT7.js";
26
+ } from "../chunk-YRL4ZB4R.js";
27
27
  import "../chunk-NKXSILEW.js";
28
28
 
29
29
  // bin/pushary-setup.ts
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  handleStop
4
- } from "../chunk-TUILTFLS.js";
4
+ } from "../chunk-NFKYZY74.js";
5
5
  import "../chunk-DWED7BS3.js";
6
- import "../chunk-FDR5WYT7.js";
6
+ import "../chunk-YRL4ZB4R.js";
7
7
  import "../chunk-NKXSILEW.js";
8
8
 
9
9
  // bin/pushary-stop-hook.ts
@@ -20,12 +20,12 @@ import {
20
20
  savePendingQuestion,
21
21
  sendNotification,
22
22
  waitForAnswer
23
- } from "./chunk-TUILTFLS.js";
23
+ } from "./chunk-NFKYZY74.js";
24
24
  import {
25
25
  effectiveWaitSeconds,
26
26
  hookWaitClamped,
27
27
  hookWaitDeadline
28
- } from "./chunk-FDR5WYT7.js";
28
+ } from "./chunk-YRL4ZB4R.js";
29
29
  import {
30
30
  getApiKey
31
31
  } from "./chunk-NKXSILEW.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  HOOK_BUDGETS
3
- } from "./chunk-FDR5WYT7.js";
3
+ } from "./chunk-YRL4ZB4R.js";
4
4
 
5
5
  // src/claude-config.ts
6
6
  import { join } from "path";
@@ -12,7 +12,7 @@ import {
12
12
  matchToolPattern,
13
13
  redactSecrets,
14
14
  redactSecretsDeep
15
- } from "./chunk-FDR5WYT7.js";
15
+ } from "./chunk-YRL4ZB4R.js";
16
16
  import {
17
17
  getApiKey,
18
18
  getBaseUrl
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  HOOK_BUDGETS
3
- } from "./chunk-FDR5WYT7.js";
3
+ } from "./chunk-YRL4ZB4R.js";
4
4
 
5
5
  // src/codex-config.ts
6
6
  import { createHash } from "crypto";
@@ -107,11 +107,101 @@ var SAFE_GIT_SUBCOMMANDS = /* @__PURE__ */ new Set([
107
107
  "count-objects"
108
108
  ]);
109
109
  var GIT_WRITE_FLAGS = (token) => token === "--output" || token.startsWith("--output=");
110
- var UNSAFE_SHELL_CHARS = /[;&|<>(){}`\\\n\r]/;
110
+ var DANGEROUS_FIND_ACTIONS = /* @__PURE__ */ new Set([
111
+ "-exec",
112
+ "-execdir",
113
+ "-ok",
114
+ "-okdir",
115
+ "-delete",
116
+ "-fprintf",
117
+ "-fprint",
118
+ "-fprint0",
119
+ "-fls"
120
+ ]);
121
+ var SAFE_FIND_TOKENS = /* @__PURE__ */ new Set([
122
+ "-name",
123
+ "-iname",
124
+ "-path",
125
+ "-ipath",
126
+ "-wholename",
127
+ "-iwholename",
128
+ "-lname",
129
+ "-ilname",
130
+ "-regex",
131
+ "-iregex",
132
+ "-type",
133
+ "-xtype",
134
+ "-maxdepth",
135
+ "-mindepth",
136
+ "-depth",
137
+ "-mount",
138
+ "-xdev",
139
+ "-size",
140
+ "-empty",
141
+ "-perm",
142
+ "-readable",
143
+ "-writable",
144
+ "-executable",
145
+ "-mtime",
146
+ "-mmin",
147
+ "-atime",
148
+ "-amin",
149
+ "-ctime",
150
+ "-cmin",
151
+ "-newer",
152
+ "-newermt",
153
+ "-anewer",
154
+ "-cnewer",
155
+ "-user",
156
+ "-uid",
157
+ "-group",
158
+ "-gid",
159
+ "-nouser",
160
+ "-nogroup",
161
+ "-samefile",
162
+ "-inum",
163
+ "-links",
164
+ "-print",
165
+ "-print0",
166
+ "-printf",
167
+ "-ls",
168
+ "-quit",
169
+ "-prune",
170
+ "-follow",
171
+ "-noleaf",
172
+ "-ignore_readdir_race",
173
+ "-noignore_readdir_race",
174
+ "-true",
175
+ "-false",
176
+ "-not",
177
+ "-and",
178
+ "-or",
179
+ "-o",
180
+ "-a",
181
+ "-P",
182
+ "-L",
183
+ "-H",
184
+ "-D",
185
+ "-O"
186
+ ]);
187
+ var SAFE_REDIRECTION = /\s*(?:[0-9]*>&[0-9-]+|(?:[0-9]*|&)>>?\s*\/dev\/null)/g;
111
188
  var basenameOf = (token) => {
112
189
  const slash = Math.max(token.lastIndexOf("/"), token.lastIndexOf("\\"));
113
190
  return slash === -1 ? token : token.slice(slash + 1);
114
191
  };
192
+ var TRUSTED_EXE_PREFIXES = [
193
+ "/bin/",
194
+ "/sbin/",
195
+ "/usr/bin/",
196
+ "/usr/sbin/",
197
+ "/usr/local/bin/",
198
+ "/opt/homebrew/bin/"
199
+ ];
200
+ var isTrustedExecutable = (first) => {
201
+ if (!first.includes("/")) return true;
202
+ if (first.includes("..")) return false;
203
+ return TRUSTED_EXE_PREFIXES.some((prefix) => first.startsWith(prefix));
204
+ };
115
205
  var tokenizeShellCommand = (command) => {
116
206
  const tokens = [];
117
207
  let current = "";
@@ -144,14 +234,12 @@ var tokenizeShellCommand = (command) => {
144
234
  if (started) tokens.push(current);
145
235
  return tokens;
146
236
  };
147
- var isSafeReadOnlyCommand = (command) => {
148
- const trimmed = command.trim();
149
- if (!trimmed || trimmed.length > 2e3) return false;
150
- if (UNSAFE_SHELL_CHARS.test(trimmed)) return false;
151
- const tokens = tokenizeShellCommand(trimmed);
237
+ var isSafeSimpleCommand = (segment) => {
238
+ const tokens = tokenizeShellCommand(segment.trim());
152
239
  if (!tokens || tokens.length === 0) return false;
153
240
  const first = tokens[0];
154
241
  if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(first) || first.includes("$")) return false;
242
+ if (!isTrustedExecutable(first)) return false;
155
243
  const exe = basenameOf(first);
156
244
  if (exe === "git") {
157
245
  const sub = tokens[1];
@@ -159,8 +247,34 @@ var isSafeReadOnlyCommand = (command) => {
159
247
  if (!SAFE_GIT_SUBCOMMANDS.has(sub)) return false;
160
248
  return !tokens.some(GIT_WRITE_FLAGS);
161
249
  }
250
+ if (exe === "find") {
251
+ for (let i = 1; i < tokens.length; i += 1) {
252
+ const t = tokens[i];
253
+ if (t === "(" || t === ")" || t === "!" || t === "\\(" || t === "\\)" || t === "\\!") continue;
254
+ if (t.startsWith("-") && (DANGEROUS_FIND_ACTIONS.has(t) || !SAFE_FIND_TOKENS.has(t))) return false;
255
+ }
256
+ return true;
257
+ }
162
258
  return SAFE_SHELL_COMMANDS.has(exe);
163
259
  };
260
+ var isSafeReadOnlyCommand = (command) => {
261
+ const trimmed = command.trim();
262
+ if (!trimmed || trimmed.length > 2e3) return false;
263
+ if (/[`\n\r{}]/.test(trimmed)) return false;
264
+ if (/;|\|\|/.test(trimmed)) return false;
265
+ if (/\\(?![()!])/.test(trimmed)) return false;
266
+ if (/(?<!\\)[()]/.test(trimmed)) return false;
267
+ const noRedir = trimmed.replace(SAFE_REDIRECTION, " ");
268
+ if (/[<>]/.test(noRedir)) return false;
269
+ if (noRedir.replace(/&&/g, " ").includes("&")) return false;
270
+ for (const andPart of noRedir.split("&&")) {
271
+ if (!andPart.trim()) return false;
272
+ for (const segment of andPart.split("|")) {
273
+ if (!isSafeSimpleCommand(segment)) return false;
274
+ }
275
+ }
276
+ return true;
277
+ };
164
278
  var API_KEY_PATTERN = /^pk_[a-f0-9]+\.[a-f0-9]+$/;
165
279
  var isValidApiKey = (value) => API_KEY_PATTERN.test(value);
166
280
  var ACTION_BODY_MAX = 4e3;
package/dist/src/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  handlePreToolUse
3
- } from "../chunk-VHD3GMZ3.js";
3
+ } from "../chunk-2BHYQCF7.js";
4
4
  import "../chunk-KQYIHZ5E.js";
5
5
  import {
6
6
  askUser,
@@ -14,9 +14,9 @@ import {
14
14
  reportEvent,
15
15
  resolvePolicy,
16
16
  waitForAnswer
17
- } from "../chunk-TUILTFLS.js";
17
+ } from "../chunk-NFKYZY74.js";
18
18
  import "../chunk-DWED7BS3.js";
19
- import "../chunk-FDR5WYT7.js";
19
+ import "../chunk-YRL4ZB4R.js";
20
20
  import {
21
21
  getApiKey,
22
22
  getBaseUrl
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushary/agent-hooks",
3
- "version": "0.27.0",
3
+ "version": "0.28.0",
4
4
  "description": "Permission hooks for AI coding agents: route tool approvals through Pushary push notifications",
5
5
  "author": "Pushary <business@pushary.com>",
6
6
  "homepage": "https://pushary.com",