@zhijiewang/openharness 0.10.1 → 0.11.1

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.
Files changed (313) hide show
  1. package/README.md +83 -13
  2. package/dist/Tool.d.ts.map +1 -1
  3. package/dist/Tool.js +7 -1
  4. package/dist/Tool.js.map +1 -1
  5. package/dist/Tool.test.js +8 -2
  6. package/dist/Tool.test.js.map +1 -1
  7. package/dist/agents/roles.d.ts +25 -0
  8. package/dist/agents/roles.d.ts.map +1 -0
  9. package/dist/agents/roles.js +116 -0
  10. package/dist/agents/roles.js.map +1 -0
  11. package/dist/agents/roles.test.d.ts +2 -0
  12. package/dist/agents/roles.test.d.ts.map +1 -0
  13. package/dist/agents/roles.test.js +38 -0
  14. package/dist/agents/roles.test.js.map +1 -0
  15. package/dist/commands/commands-new.test.d.ts +5 -0
  16. package/dist/commands/commands-new.test.d.ts.map +1 -0
  17. package/dist/commands/commands-new.test.js +132 -0
  18. package/dist/commands/commands-new.test.js.map +1 -0
  19. package/dist/commands/commands.test.js +31 -0
  20. package/dist/commands/commands.test.js.map +1 -1
  21. package/dist/commands/index.d.ts +2 -0
  22. package/dist/commands/index.d.ts.map +1 -1
  23. package/dist/commands/index.js +199 -6
  24. package/dist/commands/index.js.map +1 -1
  25. package/dist/components/REPL.js +1 -1
  26. package/dist/components/REPL.js.map +1 -1
  27. package/dist/git/git.test.js +33 -1
  28. package/dist/git/git.test.js.map +1 -1
  29. package/dist/git/index.d.ts +12 -0
  30. package/dist/git/index.d.ts.map +1 -1
  31. package/dist/git/index.js +47 -2
  32. package/dist/git/index.js.map +1 -1
  33. package/dist/harness/checkpoints.d.ts +36 -0
  34. package/dist/harness/checkpoints.d.ts.map +1 -0
  35. package/dist/harness/checkpoints.js +156 -0
  36. package/dist/harness/checkpoints.js.map +1 -0
  37. package/dist/harness/config.d.ts +3 -0
  38. package/dist/harness/config.d.ts.map +1 -1
  39. package/dist/harness/config.js +35 -2
  40. package/dist/harness/config.js.map +1 -1
  41. package/dist/harness/config.test.js +21 -1
  42. package/dist/harness/config.test.js.map +1 -1
  43. package/dist/harness/hooks-env.test.d.ts +5 -0
  44. package/dist/harness/hooks-env.test.d.ts.map +1 -0
  45. package/dist/harness/hooks-env.test.js +41 -0
  46. package/dist/harness/hooks-env.test.js.map +1 -0
  47. package/dist/harness/hooks.d.ts +7 -0
  48. package/dist/harness/hooks.d.ts.map +1 -1
  49. package/dist/harness/hooks.js +14 -0
  50. package/dist/harness/hooks.js.map +1 -1
  51. package/dist/harness/keybindings.d.ts.map +1 -1
  52. package/dist/harness/keybindings.js +4 -0
  53. package/dist/harness/keybindings.js.map +1 -1
  54. package/dist/harness/memory.d.ts +19 -0
  55. package/dist/harness/memory.d.ts.map +1 -1
  56. package/dist/harness/memory.js +85 -0
  57. package/dist/harness/memory.js.map +1 -1
  58. package/dist/harness/onboarding.d.ts +1 -1
  59. package/dist/harness/onboarding.d.ts.map +1 -1
  60. package/dist/harness/onboarding.js +59 -4
  61. package/dist/harness/onboarding.js.map +1 -1
  62. package/dist/harness/onboarding.test.d.ts +5 -0
  63. package/dist/harness/onboarding.test.d.ts.map +1 -0
  64. package/dist/harness/onboarding.test.js +93 -0
  65. package/dist/harness/onboarding.test.js.map +1 -0
  66. package/dist/harness/rules.d.ts +6 -1
  67. package/dist/harness/rules.d.ts.map +1 -1
  68. package/dist/harness/rules.js +52 -5
  69. package/dist/harness/rules.js.map +1 -1
  70. package/dist/harness/rules.test.js +30 -1
  71. package/dist/harness/rules.test.js.map +1 -1
  72. package/dist/harness/session.d.ts +8 -1
  73. package/dist/harness/session.d.ts.map +1 -1
  74. package/dist/harness/session.js +13 -5
  75. package/dist/harness/session.js.map +1 -1
  76. package/dist/harness/store.d.ts +46 -0
  77. package/dist/harness/store.d.ts.map +1 -0
  78. package/dist/harness/store.js +56 -0
  79. package/dist/harness/store.js.map +1 -0
  80. package/dist/harness/store.test.d.ts +2 -0
  81. package/dist/harness/store.test.d.ts.map +1 -0
  82. package/dist/harness/store.test.js +71 -0
  83. package/dist/harness/store.test.js.map +1 -0
  84. package/dist/harness/submit-handler.d.ts +2 -0
  85. package/dist/harness/submit-handler.d.ts.map +1 -1
  86. package/dist/harness/submit-handler.js +3 -0
  87. package/dist/harness/submit-handler.js.map +1 -1
  88. package/dist/main.js +153 -26
  89. package/dist/main.js.map +1 -1
  90. package/dist/mcp/client.d.ts +2 -0
  91. package/dist/mcp/client.d.ts.map +1 -1
  92. package/dist/mcp/client.js +10 -2
  93. package/dist/mcp/client.js.map +1 -1
  94. package/dist/mcp/loader.d.ts +2 -0
  95. package/dist/mcp/loader.d.ts.map +1 -1
  96. package/dist/mcp/loader.js +34 -18
  97. package/dist/mcp/loader.js.map +1 -1
  98. package/dist/mcp/loader.test.d.ts +7 -0
  99. package/dist/mcp/loader.test.d.ts.map +1 -0
  100. package/dist/mcp/loader.test.js +25 -0
  101. package/dist/mcp/loader.test.js.map +1 -0
  102. package/dist/providers/anthropic-convert.test.d.ts +5 -0
  103. package/dist/providers/anthropic-convert.test.d.ts.map +1 -0
  104. package/dist/providers/anthropic-convert.test.js +98 -0
  105. package/dist/providers/anthropic-convert.test.js.map +1 -0
  106. package/dist/providers/anthropic.d.ts.map +1 -1
  107. package/dist/providers/anthropic.js +23 -4
  108. package/dist/providers/anthropic.js.map +1 -1
  109. package/dist/providers/stream-parsing.test.d.ts +6 -0
  110. package/dist/providers/stream-parsing.test.d.ts.map +1 -0
  111. package/dist/providers/stream-parsing.test.js +174 -0
  112. package/dist/providers/stream-parsing.test.js.map +1 -0
  113. package/dist/query/compress.d.ts +17 -0
  114. package/dist/query/compress.d.ts.map +1 -0
  115. package/dist/query/compress.js +115 -0
  116. package/dist/query/compress.js.map +1 -0
  117. package/dist/query/errors.d.ts +10 -0
  118. package/dist/query/errors.d.ts.map +1 -0
  119. package/dist/query/errors.js +22 -0
  120. package/dist/query/errors.js.map +1 -0
  121. package/dist/query/index.d.ts +15 -0
  122. package/dist/query/index.d.ts.map +1 -0
  123. package/dist/query/index.js +199 -0
  124. package/dist/query/index.js.map +1 -0
  125. package/dist/query/tools.d.ts +17 -0
  126. package/dist/query/tools.d.ts.map +1 -0
  127. package/dist/query/tools.js +129 -0
  128. package/dist/query/tools.js.map +1 -0
  129. package/dist/query/types.d.ts +31 -0
  130. package/dist/query/types.d.ts.map +1 -0
  131. package/dist/query/types.js +5 -0
  132. package/dist/query/types.js.map +1 -0
  133. package/dist/query.d.ts +8 -38
  134. package/dist/query.d.ts.map +1 -1
  135. package/dist/query.js +7 -444
  136. package/dist/query.js.map +1 -1
  137. package/dist/query.test.js +1 -1
  138. package/dist/query.test.js.map +1 -1
  139. package/dist/renderer/cells.d.ts.map +1 -1
  140. package/dist/renderer/cells.js +15 -2
  141. package/dist/renderer/cells.js.map +1 -1
  142. package/dist/renderer/colors.d.ts +8 -0
  143. package/dist/renderer/colors.d.ts.map +1 -0
  144. package/dist/renderer/colors.js +18 -0
  145. package/dist/renderer/colors.js.map +1 -0
  146. package/dist/renderer/diff.test.d.ts +5 -0
  147. package/dist/renderer/diff.test.d.ts.map +1 -0
  148. package/dist/renderer/diff.test.js +140 -0
  149. package/dist/renderer/diff.test.js.map +1 -0
  150. package/dist/renderer/differ.d.ts.map +1 -1
  151. package/dist/renderer/differ.js +1 -10
  152. package/dist/renderer/differ.js.map +1 -1
  153. package/dist/renderer/e2e.test.js +1 -0
  154. package/dist/renderer/e2e.test.js.map +1 -1
  155. package/dist/renderer/image.test.d.ts +5 -0
  156. package/dist/renderer/image.test.d.ts.map +1 -0
  157. package/dist/renderer/image.test.js +66 -0
  158. package/dist/renderer/image.test.js.map +1 -0
  159. package/dist/renderer/index.d.ts +23 -4
  160. package/dist/renderer/index.d.ts.map +1 -1
  161. package/dist/renderer/index.js +203 -118
  162. package/dist/renderer/index.js.map +1 -1
  163. package/dist/renderer/layout.d.ts +5 -1
  164. package/dist/renderer/layout.d.ts.map +1 -1
  165. package/dist/renderer/layout.js +504 -614
  166. package/dist/renderer/layout.js.map +1 -1
  167. package/dist/renderer/markdown.d.ts.map +1 -1
  168. package/dist/renderer/markdown.js +42 -36
  169. package/dist/renderer/markdown.js.map +1 -1
  170. package/dist/renderer/perf.test.js +1 -0
  171. package/dist/renderer/perf.test.js.map +1 -1
  172. package/dist/renderer/session-browser.test.d.ts +6 -0
  173. package/dist/renderer/session-browser.test.d.ts.map +1 -0
  174. package/dist/renderer/session-browser.test.js +95 -0
  175. package/dist/renderer/session-browser.test.js.map +1 -0
  176. package/dist/renderer/ui-ux.test.d.ts +15 -0
  177. package/dist/renderer/ui-ux.test.d.ts.map +1 -0
  178. package/dist/renderer/ui-ux.test.js +470 -0
  179. package/dist/renderer/ui-ux.test.js.map +1 -0
  180. package/dist/repl.d.ts.map +1 -1
  181. package/dist/repl.js +246 -28
  182. package/dist/repl.js.map +1 -1
  183. package/dist/services/StreamingToolExecutor.d.ts.map +1 -1
  184. package/dist/services/StreamingToolExecutor.js +4 -2
  185. package/dist/services/StreamingToolExecutor.js.map +1 -1
  186. package/dist/services/agent-messaging.d.ts +68 -0
  187. package/dist/services/agent-messaging.d.ts.map +1 -0
  188. package/dist/services/agent-messaging.js +121 -0
  189. package/dist/services/agent-messaging.js.map +1 -0
  190. package/dist/services/agent-messaging.test.d.ts +2 -0
  191. package/dist/services/agent-messaging.test.d.ts.map +1 -0
  192. package/dist/services/agent-messaging.test.js +88 -0
  193. package/dist/services/agent-messaging.test.js.map +1 -0
  194. package/dist/services/cron.d.ts +40 -0
  195. package/dist/services/cron.d.ts.map +1 -0
  196. package/dist/services/cron.js +90 -0
  197. package/dist/services/cron.js.map +1 -0
  198. package/dist/services/cron.test.d.ts +2 -0
  199. package/dist/services/cron.test.d.ts.map +1 -0
  200. package/dist/services/cron.test.js +49 -0
  201. package/dist/services/cron.test.js.map +1 -0
  202. package/dist/tools/AgentTool/index.d.ts +9 -0
  203. package/dist/tools/AgentTool/index.d.ts.map +1 -1
  204. package/dist/tools/AgentTool/index.js +89 -6
  205. package/dist/tools/AgentTool/index.js.map +1 -1
  206. package/dist/tools/BashTool/index.d.ts +6 -0
  207. package/dist/tools/BashTool/index.d.ts.map +1 -1
  208. package/dist/tools/BashTool/index.js +39 -1
  209. package/dist/tools/BashTool/index.js.map +1 -1
  210. package/dist/tools/CronTool/index.d.ts +40 -0
  211. package/dist/tools/CronTool/index.d.ts.map +1 -0
  212. package/dist/tools/CronTool/index.js +59 -0
  213. package/dist/tools/CronTool/index.js.map +1 -0
  214. package/dist/tools/EnterWorktreeTool/index.d.ts +12 -0
  215. package/dist/tools/EnterWorktreeTool/index.d.ts.map +1 -0
  216. package/dist/tools/EnterWorktreeTool/index.js +27 -0
  217. package/dist/tools/EnterWorktreeTool/index.js.map +1 -0
  218. package/dist/tools/ExitWorktreeTool/index.d.ts +15 -0
  219. package/dist/tools/ExitWorktreeTool/index.d.ts.map +1 -0
  220. package/dist/tools/ExitWorktreeTool/index.js +33 -0
  221. package/dist/tools/ExitWorktreeTool/index.js.map +1 -0
  222. package/dist/tools/FileEditTool/index.js +4 -4
  223. package/dist/tools/FileEditTool/index.js.map +1 -1
  224. package/dist/tools/FileReadTool/index.d.ts +3 -0
  225. package/dist/tools/FileReadTool/index.d.ts.map +1 -1
  226. package/dist/tools/FileReadTool/index.js +102 -4
  227. package/dist/tools/FileReadTool/index.js.map +1 -1
  228. package/dist/tools/FileWriteTool/index.d.ts.map +1 -1
  229. package/dist/tools/FileWriteTool/index.js +20 -5
  230. package/dist/tools/FileWriteTool/index.js.map +1 -1
  231. package/dist/tools/GlobTool/index.d.ts.map +1 -1
  232. package/dist/tools/GlobTool/index.js +4 -61
  233. package/dist/tools/GlobTool/index.js.map +1 -1
  234. package/dist/tools/GrepTool/index.d.ts +30 -0
  235. package/dist/tools/GrepTool/index.d.ts.map +1 -1
  236. package/dist/tools/GrepTool/index.js +153 -72
  237. package/dist/tools/GrepTool/index.js.map +1 -1
  238. package/dist/tools/KillProcessTool/index.d.ts +18 -0
  239. package/dist/tools/KillProcessTool/index.d.ts.map +1 -0
  240. package/dist/tools/KillProcessTool/index.js +43 -0
  241. package/dist/tools/KillProcessTool/index.js.map +1 -0
  242. package/dist/tools/LSTool/index.d.ts +3 -0
  243. package/dist/tools/LSTool/index.d.ts.map +1 -1
  244. package/dist/tools/LSTool/index.js +44 -29
  245. package/dist/tools/LSTool/index.js.map +1 -1
  246. package/dist/tools/MemoryTool/index.d.ts +30 -0
  247. package/dist/tools/MemoryTool/index.d.ts.map +1 -0
  248. package/dist/tools/MemoryTool/index.js +56 -0
  249. package/dist/tools/MemoryTool/index.js.map +1 -0
  250. package/dist/tools/MultiEditTool/index.d.ts +32 -0
  251. package/dist/tools/MultiEditTool/index.d.ts.map +1 -0
  252. package/dist/tools/MultiEditTool/index.js +53 -0
  253. package/dist/tools/MultiEditTool/index.js.map +1 -0
  254. package/dist/tools/RemoteTriggerTool/index.d.ts +21 -0
  255. package/dist/tools/RemoteTriggerTool/index.d.ts.map +1 -0
  256. package/dist/tools/RemoteTriggerTool/index.js +43 -0
  257. package/dist/tools/RemoteTriggerTool/index.js.map +1 -0
  258. package/dist/tools/SendMessageTool/index.d.ts +18 -0
  259. package/dist/tools/SendMessageTool/index.d.ts.map +1 -0
  260. package/dist/tools/SendMessageTool/index.js +29 -0
  261. package/dist/tools/SendMessageTool/index.js.map +1 -0
  262. package/dist/tools/TaskCreateTool/index.d.ts +6 -0
  263. package/dist/tools/TaskCreateTool/index.d.ts.map +1 -1
  264. package/dist/tools/TaskCreateTool/index.js +8 -2
  265. package/dist/tools/TaskCreateTool/index.js.map +1 -1
  266. package/dist/tools/TaskGetTool/index.d.ts +12 -0
  267. package/dist/tools/TaskGetTool/index.d.ts.map +1 -0
  268. package/dist/tools/TaskGetTool/index.js +50 -0
  269. package/dist/tools/TaskGetTool/index.js.map +1 -0
  270. package/dist/tools/TaskOutputTool/index.d.ts +15 -0
  271. package/dist/tools/TaskOutputTool/index.d.ts.map +1 -0
  272. package/dist/tools/TaskOutputTool/index.js +45 -0
  273. package/dist/tools/TaskOutputTool/index.js.map +1 -0
  274. package/dist/tools/TaskStopTool/index.d.ts +15 -0
  275. package/dist/tools/TaskStopTool/index.d.ts.map +1 -0
  276. package/dist/tools/TaskStopTool/index.js +51 -0
  277. package/dist/tools/TaskStopTool/index.js.map +1 -0
  278. package/dist/tools/TaskUpdateTool/index.d.ts +21 -3
  279. package/dist/tools/TaskUpdateTool/index.d.ts.map +1 -1
  280. package/dist/tools/TaskUpdateTool/index.js +48 -3
  281. package/dist/tools/TaskUpdateTool/index.js.map +1 -1
  282. package/dist/tools/tools-basic.test.js +191 -2
  283. package/dist/tools/tools-basic.test.js.map +1 -1
  284. package/dist/tools.d.ts.map +1 -1
  285. package/dist/tools.js +38 -0
  286. package/dist/tools.js.map +1 -1
  287. package/dist/types/permissions.d.ts +2 -2
  288. package/dist/types/permissions.d.ts.map +1 -1
  289. package/dist/types/permissions.js +59 -13
  290. package/dist/types/permissions.js.map +1 -1
  291. package/dist/types/permissions.test.js +57 -0
  292. package/dist/types/permissions.test.js.map +1 -1
  293. package/dist/utils/bash-safety.d.ts +18 -0
  294. package/dist/utils/bash-safety.d.ts.map +1 -0
  295. package/dist/utils/bash-safety.js +227 -0
  296. package/dist/utils/bash-safety.js.map +1 -0
  297. package/dist/utils/bash-safety.test.d.ts +2 -0
  298. package/dist/utils/bash-safety.test.d.ts.map +1 -0
  299. package/dist/utils/bash-safety.test.js +112 -0
  300. package/dist/utils/bash-safety.test.js.map +1 -0
  301. package/dist/utils/fs.d.ts +15 -0
  302. package/dist/utils/fs.d.ts.map +1 -0
  303. package/dist/utils/fs.js +64 -0
  304. package/dist/utils/fs.js.map +1 -0
  305. package/dist/utils/fs.test.d.ts +5 -0
  306. package/dist/utils/fs.test.d.ts.map +1 -0
  307. package/dist/utils/fs.test.js +82 -0
  308. package/dist/utils/fs.test.js.map +1 -0
  309. package/dist/utils/safe-env.d.ts +10 -0
  310. package/dist/utils/safe-env.d.ts.map +1 -0
  311. package/dist/utils/safe-env.js +40 -0
  312. package/dist/utils/safe-env.js.map +1 -0
  313. package/package.json +4 -1
@@ -2,7 +2,7 @@
2
2
  * Permission types — tool permission context and risk-based gating.
3
3
  */
4
4
  import type { ToolPermissionRule } from "../harness/config.js";
5
- export type PermissionMode = "ask" | "trust" | "deny" | "acceptEdits" | "plan";
5
+ export type PermissionMode = "ask" | "trust" | "deny" | "acceptEdits" | "plan" | "auto" | "bypassPermissions";
6
6
  export type RiskLevel = "low" | "medium" | "high";
7
7
  export type PermissionResult = {
8
8
  readonly allowed: boolean;
@@ -11,5 +11,5 @@ export type PermissionResult = {
11
11
  };
12
12
  export type AskUserFn = (toolName: string, description: string, riskLevel?: RiskLevel) => Promise<boolean>;
13
13
  export declare function setToolPermissionRules(rules: ToolPermissionRule[] | undefined): void;
14
- export declare function checkPermission(mode: PermissionMode, riskLevel: RiskLevel, isReadOnly: boolean, toolName?: string): PermissionResult;
14
+ export declare function checkPermission(mode: PermissionMode, riskLevel: RiskLevel, isReadOnly: boolean, toolName?: string, toolInput?: unknown): PermissionResult;
15
15
  //# sourceMappingURL=permissions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/types/permissions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,aAAa,GAAG,MAAM,CAAC;AAE/E,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAElD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,CACtB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,SAAS,KAClB,OAAO,CAAC,OAAO,CAAC,CAAC;AAyBtB,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,kBAAkB,EAAE,GAAG,SAAS,GAAG,IAAI,CAEpF;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,cAAc,EACpB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,OAAO,EACnB,QAAQ,CAAC,EAAE,MAAM,GAChB,gBAAgB,CAwClB"}
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/types/permissions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG/D,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,mBAAmB,CAAC;AAE9G,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAElD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG,CACtB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,SAAS,KAClB,OAAO,CAAC,OAAO,CAAC,CAAC;AAwCtB,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,kBAAkB,EAAE,GAAG,SAAS,GAAG,IAAI,CAEpF;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,cAAc,EACpB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,OAAO,EACnB,QAAQ,CAAC,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,OAAO,GAClB,gBAAgB,CAqElB"}
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Permission types — tool permission context and risk-based gating.
3
3
  */
4
+ import { analyzeBashCommand } from "../utils/bash-safety.js";
4
5
  /** Tools auto-approved in acceptEdits mode */
5
6
  const EDIT_SAFE_TOOLS = new Set([
6
7
  "FileRead", "FileWrite", "FileEdit", "Glob", "Grep", "LS",
@@ -14,20 +15,37 @@ function matchToolPattern(pattern, toolName) {
14
15
  return pattern === toolName;
15
16
  }
16
17
  /** Find the first matching tool permission rule */
17
- function findToolRule(rules, toolName) {
18
+ function findToolRule(rules, toolName, toolInput) {
18
19
  if (!rules || rules.length === 0)
19
20
  return undefined;
20
- return rules.find(r => matchToolPattern(r.tool, toolName));
21
+ return rules.find(r => {
22
+ if (!matchToolPattern(r.tool, toolName))
23
+ return false;
24
+ // If rule has a pattern, match against Bash command content only
25
+ if (r.pattern && toolInput && toolName === "Bash") {
26
+ const command = toolInput?.command;
27
+ if (typeof command === "string") {
28
+ try {
29
+ return new RegExp(r.pattern).test(command);
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ return false;
36
+ }
37
+ return true;
38
+ });
21
39
  }
22
40
  /** Cached tool permission rules — set by the REPL at startup */
23
41
  let toolPermissionRules;
24
42
  export function setToolPermissionRules(rules) {
25
43
  toolPermissionRules = rules;
26
44
  }
27
- export function checkPermission(mode, riskLevel, isReadOnly, toolName) {
45
+ export function checkPermission(mode, riskLevel, isReadOnly, toolName, toolInput) {
28
46
  // Check per-tool permission rules first (highest priority)
29
47
  if (toolName) {
30
- const rule = findToolRule(toolPermissionRules, toolName);
48
+ const rule = findToolRule(toolPermissionRules, toolName, toolInput);
31
49
  if (rule) {
32
50
  if (rule.action === "allow")
33
51
  return { allowed: true, reason: "tool-rule-allow", riskLevel };
@@ -37,29 +55,57 @@ export function checkPermission(mode, riskLevel, isReadOnly, toolName) {
37
55
  return { allowed: false, reason: "needs-approval", riskLevel };
38
56
  }
39
57
  }
58
+ // Bash command safety analysis — detect destructive patterns
59
+ let effectiveRisk = riskLevel;
60
+ if (toolName === "Bash" && toolInput) {
61
+ const command = toolInput?.command;
62
+ if (typeof command === "string") {
63
+ const analysis = analyzeBashCommand(command);
64
+ if (analysis.level === "dangerous") {
65
+ effectiveRisk = "high";
66
+ }
67
+ else if (analysis.level === "moderate" && effectiveRisk !== "high") {
68
+ effectiveRisk = "medium";
69
+ }
70
+ else if (analysis.level === "safe") {
71
+ effectiveRisk = "medium"; // bash is never fully "low" risk
72
+ }
73
+ }
74
+ }
40
75
  // Always allow low-risk read-only
41
- if (riskLevel === "low" && isReadOnly) {
42
- return { allowed: true, reason: "auto-approved", riskLevel };
76
+ if (effectiveRisk === "low" && isReadOnly) {
77
+ return { allowed: true, reason: "auto-approved", riskLevel: effectiveRisk };
78
+ }
79
+ // bypassPermissions — approve everything unconditionally (CI/testing only)
80
+ if (mode === "bypassPermissions") {
81
+ return { allowed: true, reason: "bypass-mode", riskLevel: effectiveRisk };
82
+ }
83
+ // auto — approve everything EXCEPT dangerous bash commands (detected by AST analysis)
84
+ if (mode === "auto") {
85
+ if (effectiveRisk === "high" && toolName === "Bash") {
86
+ return { allowed: false, reason: "auto-mode-dangerous-bash", riskLevel: effectiveRisk };
87
+ }
88
+ return { allowed: true, reason: "auto-mode", riskLevel: effectiveRisk };
43
89
  }
44
90
  if (mode === "trust") {
45
- return { allowed: true, reason: "trust-mode", riskLevel };
91
+ return { allowed: true, reason: "trust-mode", riskLevel: effectiveRisk };
46
92
  }
47
93
  if (mode === "deny") {
48
- return { allowed: false, reason: "deny-mode", riskLevel };
94
+ return { allowed: false, reason: "deny-mode", riskLevel: effectiveRisk };
49
95
  }
50
96
  if (mode === "plan") {
51
97
  if (isReadOnly) {
52
- return { allowed: true, reason: "plan-mode-readonly", riskLevel };
98
+ return { allowed: true, reason: "plan-mode-readonly", riskLevel: effectiveRisk };
53
99
  }
54
- return { allowed: false, reason: "plan-mode-no-writes", riskLevel };
100
+ return { allowed: false, reason: "plan-mode-no-writes", riskLevel: effectiveRisk };
55
101
  }
56
102
  if (mode === "acceptEdits") {
57
103
  if (toolName && EDIT_SAFE_TOOLS.has(toolName)) {
58
- return { allowed: true, reason: "acceptEdits-auto", riskLevel };
104
+ return { allowed: true, reason: "acceptEdits-auto", riskLevel: effectiveRisk };
59
105
  }
60
- return { allowed: false, reason: "needs-approval", riskLevel };
106
+ return { allowed: false, reason: "needs-approval", riskLevel: effectiveRisk };
61
107
  }
62
108
  // ask mode — needs user approval
63
- return { allowed: false, reason: "needs-approval", riskLevel };
109
+ return { allowed: false, reason: "needs-approval", riskLevel: effectiveRisk };
64
110
  }
65
111
  //# sourceMappingURL=permissions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/types/permissions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/types/permissions.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAkB7D,8CAA8C;AAC9C,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI;IACzD,WAAW,EAAE,cAAc;CAC5B,CAAC,CAAC;AAEH,oFAAoF;AACpF,SAAS,gBAAgB,CAAC,OAAe,EAAE,QAAgB;IACzD,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,OAAO,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,OAAO,KAAK,QAAQ,CAAC;AAC9B,CAAC;AAED,mDAAmD;AACnD,SAAS,YAAY,CAAC,KAAuC,EAAE,QAAgB,EAAE,SAAmB;IAClG,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACnD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;QACpB,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC;YAAE,OAAO,KAAK,CAAC;QACtD,iEAAiE;QACjE,IAAI,CAAC,CAAC,OAAO,IAAI,SAAS,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YAClD,MAAM,OAAO,GAAI,SAAqC,EAAE,OAAO,CAAC;YAChE,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;gBAChC,IAAI,CAAC;oBACH,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC7C,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,gEAAgE;AAChE,IAAI,mBAAqD,CAAC;AAE1D,MAAM,UAAU,sBAAsB,CAAC,KAAuC;IAC5E,mBAAmB,GAAG,KAAK,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,IAAoB,EACpB,SAAoB,EACpB,UAAmB,EACnB,QAAiB,EACjB,SAAmB;IAEnB,2DAA2D;IAC3D,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,IAAI,GAAG,YAAY,CAAC,mBAAmB,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;QACpE,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO;gBAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,CAAC;YAC5F,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM;gBAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,CAAC;YAC3F,IAAI,IAAI,CAAC,MAAM,KAAK,KAAK;gBAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,CAAC;QAC5F,CAAC;IACH,CAAC;IAED,6DAA6D;IAC7D,IAAI,aAAa,GAAG,SAAS,CAAC;IAC9B,IAAI,QAAQ,KAAK,MAAM,IAAI,SAAS,EAAE,CAAC;QACrC,MAAM,OAAO,GAAI,SAAqC,EAAE,OAAO,CAAC;QAChE,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;YAC7C,IAAI,QAAQ,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;gBACnC,aAAa,GAAG,MAAM,CAAC;YACzB,CAAC;iBAAM,IAAI,QAAQ,CAAC,KAAK,KAAK,UAAU,IAAI,aAAa,KAAK,MAAM,EAAE,CAAC;gBACrE,aAAa,GAAG,QAAQ,CAAC;YAC3B,CAAC;iBAAM,IAAI,QAAQ,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;gBACrC,aAAa,GAAG,QAAQ,CAAC,CAAC,iCAAiC;YAC7D,CAAC;QACH,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,IAAI,aAAa,KAAK,KAAK,IAAI,UAAU,EAAE,CAAC;QAC1C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;IAC9E,CAAC;IAED,2EAA2E;IAC3E,IAAI,IAAI,KAAK,mBAAmB,EAAE,CAAC;QACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;IAC5E,CAAC;IAED,sFAAsF;IACtF,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,IAAI,aAAa,KAAK,MAAM,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YACpD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,0BAA0B,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;QAC1F,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;IAC1E,CAAC;IAED,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3E,CAAC;IAED,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3E,CAAC;IAED,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,oBAAoB,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;QACnF,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,qBAAqB,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;IACrF,CAAC;IAED,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;QAC3B,IAAI,QAAQ,IAAI,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;QACjF,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;IAChF,CAAC;IAED,iCAAiC;IACjC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;AAChF,CAAC"}
@@ -67,4 +67,61 @@ test("plan mode allows high-risk reads", () => {
67
67
  assert.equal(r.allowed, true);
68
68
  assert.equal(r.reason, "plan-mode-readonly");
69
69
  });
70
+ // ── permission pattern regex matching ──
71
+ import { setToolPermissionRules } from "./permissions.js";
72
+ test("pattern rule allows matching Bash commands", () => {
73
+ setToolPermissionRules([{ tool: "Bash", action: "allow", pattern: "^npm (test|run)" }]);
74
+ const r = checkPermission("ask", "high", false, "Bash", { command: "npm test" });
75
+ assert.equal(r.allowed, true);
76
+ assert.equal(r.reason, "tool-rule-allow");
77
+ setToolPermissionRules(undefined);
78
+ });
79
+ test("pattern rule blocks non-matching Bash commands", () => {
80
+ setToolPermissionRules([{ tool: "Bash", action: "allow", pattern: "^npm test$" }]);
81
+ const r = checkPermission("ask", "high", false, "Bash", { command: "rm -rf /" });
82
+ // Should fall through to ask mode since pattern doesn't match
83
+ assert.equal(r.allowed, false);
84
+ assert.equal(r.reason, "needs-approval");
85
+ setToolPermissionRules(undefined);
86
+ });
87
+ test("pattern only applies to Bash tool, not others", () => {
88
+ setToolPermissionRules([{ tool: "Read", action: "allow", pattern: "etc" }]);
89
+ // Pattern should be ignored for non-Bash tools, rule matches on tool name only
90
+ const r = checkPermission("ask", "low", true, "Read", { file_path: "/etc/passwd" });
91
+ assert.equal(r.allowed, true);
92
+ setToolPermissionRules(undefined);
93
+ });
94
+ test("toolInput parameter passed correctly", () => {
95
+ setToolPermissionRules([{ tool: "Bash", action: "deny", pattern: "^rm " }]);
96
+ const r = checkPermission("trust", "high", false, "Bash", { command: "rm -rf /tmp" });
97
+ assert.equal(r.allowed, false);
98
+ assert.equal(r.reason, "tool-rule-deny");
99
+ setToolPermissionRules(undefined);
100
+ });
101
+ // ── auto mode ──
102
+ test("auto mode approves safe bash commands", () => {
103
+ const r = checkPermission("auto", "high", false, "Bash", { command: "git status" });
104
+ assert.equal(r.allowed, true);
105
+ assert.equal(r.reason, "auto-mode");
106
+ });
107
+ test("auto mode blocks dangerous bash (rm -rf)", () => {
108
+ const r = checkPermission("auto", "high", false, "Bash", { command: "rm -rf /" });
109
+ assert.equal(r.allowed, false);
110
+ assert.equal(r.reason, "auto-mode-dangerous-bash");
111
+ });
112
+ test("auto mode approves non-bash tools", () => {
113
+ const r = checkPermission("auto", "high", false, "FileWrite");
114
+ assert.equal(r.allowed, true);
115
+ assert.equal(r.reason, "auto-mode");
116
+ });
117
+ // ── bypassPermissions mode ──
118
+ test("bypassPermissions approves everything", () => {
119
+ const r = checkPermission("bypassPermissions", "high", false, "Bash", { command: "rm -rf /" });
120
+ assert.equal(r.allowed, true);
121
+ assert.equal(r.reason, "bypass-mode");
122
+ });
123
+ test("bypassPermissions approves even in high-risk writes", () => {
124
+ const r = checkPermission("bypassPermissions", "high", false);
125
+ assert.equal(r.allowed, true);
126
+ });
70
127
  //# sourceMappingURL=permissions.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.test.js","sourceRoot":"","sources":["../../src/types/permissions.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"permissions.test.js","sourceRoot":"","sources":["../../src/types/permissions.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Bash command safety analysis — lightweight AST-style parsing to detect
3
+ * dangerous command patterns. Replaces simple regex matching with structural
4
+ * analysis of shell command syntax.
5
+ *
6
+ * Inspired by Claude Code's bash AST analysis for permission gating.
7
+ */
8
+ export type BashRisk = {
9
+ level: 'safe' | 'moderate' | 'dangerous';
10
+ reasons: string[];
11
+ };
12
+ /**
13
+ * Analyze a bash command string for safety risks.
14
+ * Does lightweight structural parsing — splits on pipes, semicolons,
15
+ * and && / || operators to analyze each sub-command.
16
+ */
17
+ export declare function analyzeBashCommand(command: string): BashRisk;
18
+ //# sourceMappingURL=bash-safety.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash-safety.d.ts","sourceRoot":"","sources":["../../src/utils/bash-safety.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,WAAW,CAAC;IACzC,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAgCF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAoH5D"}
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Bash command safety analysis — lightweight AST-style parsing to detect
3
+ * dangerous command patterns. Replaces simple regex matching with structural
4
+ * analysis of shell command syntax.
5
+ *
6
+ * Inspired by Claude Code's bash AST analysis for permission gating.
7
+ */
8
+ // Commands that destroy data or are hard to reverse
9
+ const DESTRUCTIVE_COMMANDS = new Set([
10
+ 'rm', 'rmdir', 'mkfs', 'dd', 'shred',
11
+ 'truncate', 'wipefs',
12
+ ]);
13
+ // Git commands that are destructive or affect shared state
14
+ const DANGEROUS_GIT = new Set([
15
+ 'push --force', 'push -f', 'reset --hard',
16
+ 'clean -f', 'clean -fd', 'clean -fx',
17
+ 'checkout .', 'checkout --', 'restore .',
18
+ 'branch -D', 'branch -d',
19
+ ]);
20
+ // Commands that change system/file permissions or ownership
21
+ const PERMISSION_COMMANDS = new Set([
22
+ 'chmod', 'chown', 'chgrp', 'setfacl',
23
+ ]);
24
+ // Commands that install or modify system packages
25
+ const INSTALL_COMMANDS = new Set([
26
+ 'apt', 'apt-get', 'yum', 'dnf', 'brew',
27
+ 'pacman', 'snap', 'pip', 'npm', 'yarn', 'pnpm',
28
+ ]);
29
+ // Commands that send data externally
30
+ const NETWORK_EXFIL = new Set([
31
+ 'curl', 'wget', 'nc', 'ncat', 'socat', 'ssh', 'scp', 'rsync',
32
+ ]);
33
+ /**
34
+ * Analyze a bash command string for safety risks.
35
+ * Does lightweight structural parsing — splits on pipes, semicolons,
36
+ * and && / || operators to analyze each sub-command.
37
+ */
38
+ export function analyzeBashCommand(command) {
39
+ const reasons = [];
40
+ const trimmed = command.trim();
41
+ // Split into sub-commands (pipes, semicolons, &&, ||)
42
+ const subCommands = splitCommands(trimmed);
43
+ for (const sub of subCommands) {
44
+ const tokens = tokenize(sub);
45
+ if (tokens.length === 0)
46
+ continue;
47
+ const cmd = tokens[0];
48
+ const args = tokens.slice(1).join(' ');
49
+ const fullCmd = `${cmd} ${args}`.trim();
50
+ // 1. Destructive commands (also check xargs + destructive)
51
+ const effectiveCmd = cmd === 'xargs' && tokens[1] ? tokens[1] : cmd;
52
+ if (DESTRUCTIVE_COMMANDS.has(effectiveCmd)) {
53
+ reasons.push(`destructive command: ${effectiveCmd}`);
54
+ // rm -rf / is especially dangerous
55
+ const fullArgs = tokens.slice(1).join(' ');
56
+ if (effectiveCmd === 'rm' && /\s-[a-zA-Z]*r[a-zA-Z]*f|\s-[a-zA-Z]*f[a-zA-Z]*r/.test(` ${fullArgs}`)) {
57
+ reasons.push('recursive force delete (rm -rf)');
58
+ }
59
+ }
60
+ // 2. Dangerous git operations
61
+ if (cmd === 'git') {
62
+ for (const pattern of DANGEROUS_GIT) {
63
+ if (args.includes(pattern.replace('git ', ''))) {
64
+ reasons.push(`dangerous git operation: git ${pattern}`);
65
+ }
66
+ }
67
+ // git push to main/master
68
+ if (args.includes('push') && (/\bmain\b/.test(args) || /\bmaster\b/.test(args))) {
69
+ if (args.includes('--force') || args.includes('-f')) {
70
+ reasons.push('force push to main/master');
71
+ }
72
+ }
73
+ }
74
+ // 3. Pipe to execution (curl | bash, wget | sh)
75
+ if (NETWORK_EXFIL.has(cmd)) {
76
+ // Check if this command's output is piped to an executor
77
+ const pipeIdx = subCommands.indexOf(sub);
78
+ if (pipeIdx < subCommands.length - 1) {
79
+ const nextCmd = tokenize(subCommands[pipeIdx + 1])[0];
80
+ if (nextCmd && ['bash', 'sh', 'zsh', 'eval', 'source', '.', 'python', 'node', 'perl', 'ruby'].includes(nextCmd)) {
81
+ reasons.push(`pipe to execution: ${cmd} | ${nextCmd}`);
82
+ }
83
+ }
84
+ }
85
+ // 4. Command substitution with execution
86
+ if (/\$\(.*\)/.test(sub) || /`[^`]+`/.test(sub)) {
87
+ // Command substitution is common and usually fine, only flag if combined with destructive
88
+ const innerCmd = sub.match(/\$\((.+?)\)/)?.[1] ?? sub.match(/`([^`]+)`/)?.[1];
89
+ if (innerCmd) {
90
+ const innerTokens = tokenize(innerCmd);
91
+ if (innerTokens[0] && DESTRUCTIVE_COMMANDS.has(innerTokens[0])) {
92
+ reasons.push(`command substitution with destructive command: $(${innerCmd})`);
93
+ }
94
+ }
95
+ }
96
+ // 5. Permission/ownership changes
97
+ if (PERMISSION_COMMANDS.has(cmd)) {
98
+ reasons.push(`permission change: ${cmd}`);
99
+ if (args.includes('777') || args.includes('+s') || args.includes('u+s')) {
100
+ reasons.push('dangerous permission mode');
101
+ }
102
+ }
103
+ // 6. Package installation (moderate risk)
104
+ if (INSTALL_COMMANDS.has(cmd) && (args.includes('install') || args.includes('add') || args.includes('-S'))) {
105
+ reasons.push(`package installation: ${cmd}`);
106
+ }
107
+ // 7. Environment variable manipulation that could affect security
108
+ if (cmd === 'export' && /PATH|LD_PRELOAD|LD_LIBRARY_PATH/.test(args)) {
109
+ reasons.push(`modifying security-sensitive env var: ${args.split('=')[0]}`);
110
+ }
111
+ // 8. Process killing
112
+ if ((cmd === 'kill' || cmd === 'killall' || cmd === 'pkill') && args.includes('-9')) {
113
+ reasons.push(`force kill: ${cmd} -9`);
114
+ }
115
+ // 9. Disk operations
116
+ if (cmd === 'dd' || cmd === 'mkfs' || cmd === 'fdisk' || cmd === 'parted') {
117
+ reasons.push(`disk operation: ${cmd}`);
118
+ }
119
+ // 10. Redirect overwrite to important files
120
+ if (/>\s*\/etc\/|>\s*~\/\.\w/.test(sub)) {
121
+ reasons.push('redirect to system/dotfile');
122
+ }
123
+ }
124
+ if (reasons.length === 0) {
125
+ return { level: 'safe', reasons: [] };
126
+ }
127
+ // Classify: any pipe-to-exec, destructive, or force-push is 'dangerous'; rest is 'moderate'
128
+ const isDangerous = reasons.some(r => r.includes('pipe to execution') ||
129
+ r.includes('recursive force delete') ||
130
+ r.includes('force push to main') ||
131
+ r.includes('disk operation') ||
132
+ r.includes('dangerous permission mode'));
133
+ return {
134
+ level: isDangerous ? 'dangerous' : 'moderate',
135
+ reasons,
136
+ };
137
+ }
138
+ /**
139
+ * Split a command string into sub-commands on |, ;, &&, ||
140
+ * Respects quoted strings and command substitutions.
141
+ */
142
+ function splitCommands(cmd) {
143
+ const parts = [];
144
+ let current = '';
145
+ let inSingle = false;
146
+ let inDouble = false;
147
+ let depth = 0; // $() nesting
148
+ for (let i = 0; i < cmd.length; i++) {
149
+ const ch = cmd[i];
150
+ const next = cmd[i + 1];
151
+ if (ch === "'" && !inDouble && depth === 0) {
152
+ inSingle = !inSingle;
153
+ current += ch;
154
+ continue;
155
+ }
156
+ if (ch === '"' && !inSingle && depth === 0) {
157
+ inDouble = !inDouble;
158
+ current += ch;
159
+ continue;
160
+ }
161
+ if (inSingle || inDouble) {
162
+ current += ch;
163
+ continue;
164
+ }
165
+ if (ch === '$' && next === '(') {
166
+ depth++;
167
+ current += ch;
168
+ continue;
169
+ }
170
+ if (ch === ')' && depth > 0) {
171
+ depth--;
172
+ current += ch;
173
+ continue;
174
+ }
175
+ if (depth > 0) {
176
+ current += ch;
177
+ continue;
178
+ }
179
+ // Split on pipe, semicolon, &&, ||
180
+ if (ch === '|' && next !== '|') {
181
+ parts.push(current.trim());
182
+ current = '';
183
+ continue;
184
+ }
185
+ if (ch === ';' || (ch === '&' && next === '&') || (ch === '|' && next === '|')) {
186
+ parts.push(current.trim());
187
+ current = '';
188
+ if (next === '&' || next === '|')
189
+ i++; // skip second char of && or ||
190
+ continue;
191
+ }
192
+ current += ch;
193
+ }
194
+ if (current.trim())
195
+ parts.push(current.trim());
196
+ return parts;
197
+ }
198
+ /**
199
+ * Tokenize a simple command into words, respecting quotes.
200
+ */
201
+ function tokenize(cmd) {
202
+ const tokens = [];
203
+ let current = '';
204
+ let inSingle = false;
205
+ let inDouble = false;
206
+ for (const ch of cmd) {
207
+ if (ch === "'" && !inDouble) {
208
+ inSingle = !inSingle;
209
+ continue;
210
+ }
211
+ if (ch === '"' && !inSingle) {
212
+ inDouble = !inDouble;
213
+ continue;
214
+ }
215
+ if (ch === ' ' && !inSingle && !inDouble) {
216
+ if (current)
217
+ tokens.push(current);
218
+ current = '';
219
+ continue;
220
+ }
221
+ current += ch;
222
+ }
223
+ if (current)
224
+ tokens.push(current);
225
+ return tokens;
226
+ }
227
+ //# sourceMappingURL=bash-safety.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash-safety.js","sourceRoot":"","sources":["../../src/utils/bash-safety.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=bash-safety.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash-safety.test.d.ts","sourceRoot":"","sources":["../../src/utils/bash-safety.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,112 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import { analyzeBashCommand } from './bash-safety.js';
4
+ describe('analyzeBashCommand', () => {
5
+ describe('safe commands', () => {
6
+ it('marks simple read commands as safe', () => {
7
+ assert.strictEqual(analyzeBashCommand('ls -la').level, 'safe');
8
+ assert.strictEqual(analyzeBashCommand('cat file.txt').level, 'safe');
9
+ assert.strictEqual(analyzeBashCommand('echo hello').level, 'safe');
10
+ assert.strictEqual(analyzeBashCommand('git status').level, 'safe');
11
+ assert.strictEqual(analyzeBashCommand('git log --oneline -10').level, 'safe');
12
+ assert.strictEqual(analyzeBashCommand('grep -r pattern .').level, 'safe');
13
+ assert.strictEqual(analyzeBashCommand('find . -name "*.ts"').level, 'safe');
14
+ assert.strictEqual(analyzeBashCommand('node --version').level, 'safe');
15
+ });
16
+ });
17
+ describe('destructive commands', () => {
18
+ it('detects rm -rf as dangerous', () => {
19
+ const result = analyzeBashCommand('rm -rf /tmp/foo');
20
+ assert.strictEqual(result.level, 'dangerous');
21
+ assert.ok(result.reasons.some(r => r.includes('recursive force delete')));
22
+ });
23
+ it('detects rm -fr as dangerous', () => {
24
+ const result = analyzeBashCommand('rm -fr .');
25
+ assert.strictEqual(result.level, 'dangerous');
26
+ });
27
+ it('detects rm without -rf as moderate', () => {
28
+ const result = analyzeBashCommand('rm file.txt');
29
+ assert.strictEqual(result.level, 'moderate');
30
+ assert.ok(result.reasons.some(r => r.includes('destructive')));
31
+ });
32
+ it('detects dd as dangerous', () => {
33
+ const result = analyzeBashCommand('dd if=/dev/zero of=/dev/sda');
34
+ assert.strictEqual(result.level, 'dangerous');
35
+ });
36
+ });
37
+ describe('dangerous git operations', () => {
38
+ it('detects git push --force', () => {
39
+ const result = analyzeBashCommand('git push --force origin main');
40
+ assert.strictEqual(result.level, 'dangerous');
41
+ assert.ok(result.reasons.some(r => r.includes('force push to main')));
42
+ });
43
+ it('detects git reset --hard', () => {
44
+ const result = analyzeBashCommand('git reset --hard HEAD~3');
45
+ assert.strictEqual(result.level, 'moderate');
46
+ assert.ok(result.reasons.some(r => r.includes('dangerous git')));
47
+ });
48
+ it('detects git clean -f', () => {
49
+ const result = analyzeBashCommand('git clean -fd');
50
+ assert.strictEqual(result.level, 'moderate');
51
+ });
52
+ it('allows safe git operations', () => {
53
+ assert.strictEqual(analyzeBashCommand('git add .').level, 'safe');
54
+ assert.strictEqual(analyzeBashCommand('git commit -m "fix"').level, 'safe');
55
+ assert.strictEqual(analyzeBashCommand('git push origin feature').level, 'safe');
56
+ });
57
+ });
58
+ describe('pipe to execution', () => {
59
+ it('detects curl | bash as dangerous', () => {
60
+ const result = analyzeBashCommand('curl https://example.com/install.sh | bash');
61
+ assert.strictEqual(result.level, 'dangerous');
62
+ assert.ok(result.reasons.some(r => r.includes('pipe to execution')));
63
+ });
64
+ it('detects wget | sh as dangerous', () => {
65
+ const result = analyzeBashCommand('wget -O - https://example.com | sh');
66
+ assert.strictEqual(result.level, 'dangerous');
67
+ });
68
+ it('allows curl without pipe to exec', () => {
69
+ const result = analyzeBashCommand('curl https://api.example.com/data');
70
+ assert.strictEqual(result.level, 'safe');
71
+ });
72
+ it('allows curl piped to jq (not execution)', () => {
73
+ const result = analyzeBashCommand('curl https://api.example.com | jq .');
74
+ assert.strictEqual(result.level, 'safe');
75
+ });
76
+ });
77
+ describe('permission changes', () => {
78
+ it('detects chmod 777 as dangerous', () => {
79
+ const result = analyzeBashCommand('chmod 777 /usr/bin/app');
80
+ assert.strictEqual(result.level, 'dangerous');
81
+ });
82
+ it('detects chmod as moderate', () => {
83
+ const result = analyzeBashCommand('chmod +x script.sh');
84
+ assert.strictEqual(result.level, 'moderate');
85
+ });
86
+ });
87
+ describe('package installation', () => {
88
+ it('detects npm install as moderate', () => {
89
+ const result = analyzeBashCommand('npm install lodash');
90
+ assert.strictEqual(result.level, 'moderate');
91
+ });
92
+ it('detects pip install as moderate', () => {
93
+ const result = analyzeBashCommand('pip install requests');
94
+ assert.strictEqual(result.level, 'moderate');
95
+ });
96
+ });
97
+ describe('compound commands', () => {
98
+ it('detects dangerous commands in pipelines', () => {
99
+ const result = analyzeBashCommand('find . -name "*.log" | xargs rm -rf');
100
+ assert.strictEqual(result.level, 'dangerous');
101
+ });
102
+ it('detects dangerous commands after &&', () => {
103
+ const result = analyzeBashCommand('cd /tmp && rm -rf *');
104
+ assert.strictEqual(result.level, 'dangerous');
105
+ });
106
+ it('handles quoted strings with special chars', () => {
107
+ const result = analyzeBashCommand('echo "hello | world && foo"');
108
+ assert.strictEqual(result.level, 'safe');
109
+ });
110
+ });
111
+ });
112
+ //# sourceMappingURL=bash-safety.test.js.map