@orion-agents/orion-code 0.1.2 → 0.1.4

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 (237) hide show
  1. package/README.md +96 -3
  2. package/README.zh-CN.md +109 -4
  3. package/dist/commands/index.d.ts.map +1 -1
  4. package/dist/commands/index.js +168 -54
  5. package/dist/commands/index.js.map +1 -1
  6. package/dist/commands/types.d.ts +3 -1
  7. package/dist/commands/types.d.ts.map +1 -1
  8. package/dist/commands/types.js.map +1 -1
  9. package/dist/framework/query.d.ts +3 -0
  10. package/dist/framework/query.d.ts.map +1 -1
  11. package/dist/framework/query.js +1 -0
  12. package/dist/framework/query.js.map +1 -1
  13. package/dist/framework/tool-scheduler.d.ts +61 -1
  14. package/dist/framework/tool-scheduler.d.ts.map +1 -1
  15. package/dist/framework/tool-scheduler.js +165 -47
  16. package/dist/framework/tool-scheduler.js.map +1 -1
  17. package/dist/framework/tool.d.ts +9 -0
  18. package/dist/framework/tool.d.ts.map +1 -1
  19. package/dist/framework/tool.js +2 -0
  20. package/dist/framework/tool.js.map +1 -1
  21. package/dist/ink-ui/screens/ReplScreen.d.ts +2 -1
  22. package/dist/ink-ui/screens/ReplScreen.d.ts.map +1 -1
  23. package/dist/ink-ui/screens/ReplScreen.js +65 -0
  24. package/dist/ink-ui/screens/ReplScreen.js.map +1 -1
  25. package/dist/memory/embeddings.d.ts.map +1 -1
  26. package/dist/memory/embeddings.js +3 -2
  27. package/dist/memory/embeddings.js.map +1 -1
  28. package/dist/memory/semantic-search.d.ts.map +1 -1
  29. package/dist/memory/semantic-search.js +2 -1
  30. package/dist/memory/semantic-search.js.map +1 -1
  31. package/dist/memory/vector-store.d.ts.map +1 -1
  32. package/dist/memory/vector-store.js +7 -3
  33. package/dist/memory/vector-store.js.map +1 -1
  34. package/dist/migration/migrate.d.ts.map +1 -1
  35. package/dist/migration/migrate.js +7 -11
  36. package/dist/migration/migrate.js.map +1 -1
  37. package/dist/print-ui/launch.d.ts +2 -1
  38. package/dist/print-ui/launch.d.ts.map +1 -1
  39. package/dist/print-ui/launch.js +7 -0
  40. package/dist/print-ui/launch.js.map +1 -1
  41. package/dist/runtime/agent-runtime-controller.d.ts +1 -0
  42. package/dist/runtime/agent-runtime-controller.d.ts.map +1 -1
  43. package/dist/runtime/agent-runtime-controller.js +24 -3
  44. package/dist/runtime/agent-runtime-controller.js.map +1 -1
  45. package/dist/runtime/agent-runtime-protocol.d.ts +16 -1
  46. package/dist/runtime/agent-runtime-protocol.d.ts.map +1 -1
  47. package/dist/runtime/agent-runtime-protocol.js +12 -0
  48. package/dist/runtime/agent-runtime-protocol.js.map +1 -1
  49. package/dist/runtime/chat-controller.d.ts +6 -0
  50. package/dist/runtime/chat-controller.d.ts.map +1 -1
  51. package/dist/runtime/chat-controller.js +65 -2
  52. package/dist/runtime/chat-controller.js.map +1 -1
  53. package/dist/runtime/goals/tools.d.ts.map +1 -1
  54. package/dist/runtime/goals/tools.js +14 -14
  55. package/dist/runtime/goals/tools.js.map +1 -1
  56. package/dist/runtime/goals/types.d.ts +6 -0
  57. package/dist/runtime/goals/types.d.ts.map +1 -1
  58. package/dist/runtime/goals/types.js.map +1 -1
  59. package/dist/runtime/model-coordinator.d.ts.map +1 -1
  60. package/dist/runtime/model-coordinator.js.map +1 -1
  61. package/dist/runtime/subagents/child-executor-guard.d.ts.map +1 -1
  62. package/dist/runtime/subagents/child-executor-guard.js +4 -0
  63. package/dist/runtime/subagents/child-executor-guard.js.map +1 -1
  64. package/dist/runtime/subagents/index.d.ts +10 -3
  65. package/dist/runtime/subagents/index.d.ts.map +1 -1
  66. package/dist/runtime/subagents/index.js +24 -1
  67. package/dist/runtime/subagents/index.js.map +1 -1
  68. package/dist/runtime/subagents/provider-gate.d.ts.map +1 -1
  69. package/dist/runtime/subagents/provider-gate.js +0 -1
  70. package/dist/runtime/subagents/provider-gate.js.map +1 -1
  71. package/dist/runtime/subagents/research-artifact.d.ts +94 -0
  72. package/dist/runtime/subagents/research-artifact.d.ts.map +1 -0
  73. package/dist/runtime/subagents/research-artifact.js +164 -0
  74. package/dist/runtime/subagents/research-artifact.js.map +1 -0
  75. package/dist/runtime/subagents/research-citation.d.ts +66 -0
  76. package/dist/runtime/subagents/research-citation.d.ts.map +1 -0
  77. package/dist/runtime/subagents/research-citation.js +185 -0
  78. package/dist/runtime/subagents/research-citation.js.map +1 -0
  79. package/dist/runtime/subagents/research-contract.d.ts +69 -0
  80. package/dist/runtime/subagents/research-contract.d.ts.map +1 -0
  81. package/dist/runtime/subagents/research-contract.js +232 -0
  82. package/dist/runtime/subagents/research-contract.js.map +1 -0
  83. package/dist/runtime/subagents/research-quality.d.ts +47 -0
  84. package/dist/runtime/subagents/research-quality.d.ts.map +1 -0
  85. package/dist/runtime/subagents/research-quality.js +125 -0
  86. package/dist/runtime/subagents/research-quality.js.map +1 -0
  87. package/dist/runtime/subagents/research-renderer.d.ts +79 -0
  88. package/dist/runtime/subagents/research-renderer.d.ts.map +1 -0
  89. package/dist/runtime/subagents/research-renderer.js +154 -0
  90. package/dist/runtime/subagents/research-renderer.js.map +1 -0
  91. package/dist/runtime/subagents/research-types.d.ts +105 -0
  92. package/dist/runtime/subagents/research-types.d.ts.map +1 -0
  93. package/dist/runtime/subagents/research-types.js +16 -0
  94. package/dist/runtime/subagents/research-types.js.map +1 -0
  95. package/dist/runtime/subagents/runtime-integration.d.ts +1 -1
  96. package/dist/runtime/subagents/runtime-integration.d.ts.map +1 -1
  97. package/dist/runtime/subagents/runtime-integration.js.map +1 -1
  98. package/dist/runtime/subagents/supervisor.d.ts +1 -1
  99. package/dist/runtime/subagents/supervisor.d.ts.map +1 -1
  100. package/dist/runtime/subagents/supervisor.js +1 -1
  101. package/dist/runtime/subagents/supervisor.js.map +1 -1
  102. package/dist/runtime/subagents/web-research-adapter.d.ts +83 -0
  103. package/dist/runtime/subagents/web-research-adapter.d.ts.map +1 -0
  104. package/dist/runtime/subagents/web-research-adapter.js +262 -0
  105. package/dist/runtime/subagents/web-research-adapter.js.map +1 -0
  106. package/dist/runtime/turn-controller.d.ts.map +1 -1
  107. package/dist/runtime/turn-controller.js +3 -1
  108. package/dist/runtime/turn-controller.js.map +1 -1
  109. package/dist/runtime/ui-events.d.ts +21 -0
  110. package/dist/runtime/ui-events.d.ts.map +1 -1
  111. package/dist/runtime/ui-events.js.map +1 -1
  112. package/dist/services/auth/auth.d.ts.map +1 -1
  113. package/dist/services/auth/auth.js +17 -4
  114. package/dist/services/auth/auth.js.map +1 -1
  115. package/dist/services/concurrent-sessions.d.ts.map +1 -1
  116. package/dist/services/concurrent-sessions.js +33 -17
  117. package/dist/services/concurrent-sessions.js.map +1 -1
  118. package/dist/services/config-dir.d.ts.map +1 -1
  119. package/dist/services/config-dir.js +19 -5
  120. package/dist/services/config-dir.js.map +1 -1
  121. package/dist/services/config.d.ts.map +1 -1
  122. package/dist/services/config.js +2 -1
  123. package/dist/services/config.js.map +1 -1
  124. package/dist/services/global-config.d.ts +31 -0
  125. package/dist/services/global-config.d.ts.map +1 -1
  126. package/dist/services/global-config.js.map +1 -1
  127. package/dist/services/goal-storage.d.ts.map +1 -1
  128. package/dist/services/goal-storage.js +22 -8
  129. package/dist/services/goal-storage.js.map +1 -1
  130. package/dist/services/llm.d.ts +17 -0
  131. package/dist/services/llm.d.ts.map +1 -1
  132. package/dist/services/llm.js +88 -31
  133. package/dist/services/llm.js.map +1 -1
  134. package/dist/services/model-catalog.d.ts +2 -0
  135. package/dist/services/model-catalog.d.ts.map +1 -1
  136. package/dist/services/model-catalog.js +25 -15
  137. package/dist/services/model-catalog.js.map +1 -1
  138. package/dist/services/model-context.d.ts.map +1 -1
  139. package/dist/services/model-context.js +36 -0
  140. package/dist/services/model-context.js.map +1 -1
  141. package/dist/services/model-registry.d.ts.map +1 -1
  142. package/dist/services/model-registry.js +32 -0
  143. package/dist/services/model-registry.js.map +1 -1
  144. package/dist/services/provider-resilience/coordinator.d.ts +1 -1
  145. package/dist/services/provider-resilience/coordinator.d.ts.map +1 -1
  146. package/dist/services/provider-resilience/coordinator.js +4 -4
  147. package/dist/services/provider-resilience/coordinator.js.map +1 -1
  148. package/dist/services/provider-resilience/error-classifier.js +20 -8
  149. package/dist/services/provider-resilience/error-classifier.js.map +1 -1
  150. package/dist/services/provider-resilience/stream-recovery.d.ts +1 -1
  151. package/dist/services/provider-resilience/stream-recovery.d.ts.map +1 -1
  152. package/dist/services/provider-resilience/stream-recovery.js +1 -1
  153. package/dist/services/provider-resilience/stream-recovery.js.map +1 -1
  154. package/dist/services/session-storage.d.ts.map +1 -1
  155. package/dist/services/session-storage.js +45 -14
  156. package/dist/services/session-storage.js.map +1 -1
  157. package/dist/services/storage-maintenance.d.ts.map +1 -1
  158. package/dist/services/storage-maintenance.js +44 -9
  159. package/dist/services/storage-maintenance.js.map +1 -1
  160. package/dist/services/task-manager.d.ts +3 -3
  161. package/dist/services/task-manager.d.ts.map +1 -1
  162. package/dist/services/tool-allowlist.d.ts +100 -0
  163. package/dist/services/tool-allowlist.d.ts.map +1 -0
  164. package/dist/services/tool-allowlist.js +250 -0
  165. package/dist/services/tool-allowlist.js.map +1 -0
  166. package/dist/services/web-search-adapters.d.ts.map +1 -1
  167. package/dist/services/web-search-adapters.js +48 -18
  168. package/dist/services/web-search-adapters.js.map +1 -1
  169. package/dist/services/web-search-mcp.d.ts.map +1 -1
  170. package/dist/services/web-search-mcp.js +27 -11
  171. package/dist/services/web-search-mcp.js.map +1 -1
  172. package/dist/services/yaml-config.d.ts.map +1 -1
  173. package/dist/services/yaml-config.js +2 -1
  174. package/dist/services/yaml-config.js.map +1 -1
  175. package/dist/skills/loader.d.ts.map +1 -1
  176. package/dist/skills/loader.js +3 -2
  177. package/dist/skills/loader.js.map +1 -1
  178. package/dist/terminal-ui/launch.d.ts +22 -2
  179. package/dist/terminal-ui/launch.d.ts.map +1 -1
  180. package/dist/terminal-ui/launch.js +150 -1
  181. package/dist/terminal-ui/launch.js.map +1 -1
  182. package/dist/terminal-ui/raw-editor.js.map +1 -1
  183. package/dist/tools/bash_security.d.ts +50 -18
  184. package/dist/tools/bash_security.d.ts.map +1 -1
  185. package/dist/tools/bash_security.js +394 -61
  186. package/dist/tools/bash_security.js.map +1 -1
  187. package/dist/tools/git.d.ts +4 -0
  188. package/dist/tools/git.d.ts.map +1 -1
  189. package/dist/tools/git.js +310 -3
  190. package/dist/tools/git.js.map +1 -1
  191. package/dist/tools/index.d.ts +1 -1
  192. package/dist/tools/index.d.ts.map +1 -1
  193. package/dist/tools/index.js +87 -25
  194. package/dist/tools/index.js.map +1 -1
  195. package/dist/tools/mcp.d.ts +8 -2
  196. package/dist/tools/mcp.d.ts.map +1 -1
  197. package/dist/tools/mcp.js +44 -23
  198. package/dist/tools/mcp.js.map +1 -1
  199. package/dist/tools/sandbox.d.ts +139 -0
  200. package/dist/tools/sandbox.d.ts.map +1 -0
  201. package/dist/tools/sandbox.js +485 -0
  202. package/dist/tools/sandbox.js.map +1 -0
  203. package/dist/tools/web.d.ts.map +1 -1
  204. package/dist/tools/web.js +113 -42
  205. package/dist/tools/web.js.map +1 -1
  206. package/dist/tui-core/frame.js.map +1 -1
  207. package/dist/tui-ui/launch.d.ts.map +1 -1
  208. package/dist/tui-ui/launch.js +46 -8
  209. package/dist/tui-ui/launch.js.map +1 -1
  210. package/dist/tui-ui/layout.d.ts.map +1 -1
  211. package/dist/tui-ui/layout.js +62 -0
  212. package/dist/tui-ui/layout.js.map +1 -1
  213. package/dist/tui-ui/runner.d.ts +6 -0
  214. package/dist/tui-ui/runner.d.ts.map +1 -1
  215. package/dist/tui-ui/runner.js +81 -1
  216. package/dist/tui-ui/runner.js.map +1 -1
  217. package/dist/tui-ui/state.d.ts +19 -1
  218. package/dist/tui-ui/state.d.ts.map +1 -1
  219. package/dist/tui-ui/state.js +35 -7
  220. package/dist/tui-ui/state.js.map +1 -1
  221. package/dist/tui-ui/terminal-image.d.ts +3 -13
  222. package/dist/tui-ui/terminal-image.d.ts.map +1 -1
  223. package/dist/tui-ui/terminal-image.js +5 -160
  224. package/dist/tui-ui/terminal-image.js.map +1 -1
  225. package/dist/utils/debug-log.d.ts +52 -0
  226. package/dist/utils/debug-log.d.ts.map +1 -0
  227. package/dist/utils/debug-log.js +91 -0
  228. package/dist/utils/debug-log.js.map +1 -0
  229. package/dist/utils/errors.d.ts +25 -0
  230. package/dist/utils/errors.d.ts.map +1 -0
  231. package/dist/utils/errors.js +47 -0
  232. package/dist/utils/errors.js.map +1 -0
  233. package/dist/utils/mask.d.ts +28 -0
  234. package/dist/utils/mask.d.ts.map +1 -0
  235. package/dist/utils/mask.js +54 -0
  236. package/dist/utils/mask.js.map +1 -0
  237. package/package.json +2 -1
@@ -8,6 +8,15 @@
8
8
  * These commands only read data and do not modify the filesystem.
9
9
  */
10
10
  export declare const READ_ONLY_COMMANDS: string[];
11
+ /**
12
+ * Sub-commands that only read state, keyed by the driver that runs them.
13
+ *
14
+ * The drivers themselves must never appear in READ_ONLY_COMMANDS: `npm run`,
15
+ * `npm exec`, `yarn <script>`, `pnpm run`, `cargo run` and `npx <pkg>` all
16
+ * execute arbitrary project-defined or freshly downloaded code, so the safe
17
+ * surface has to be enumerated rather than subtracted.
18
+ */
19
+ export declare const READ_ONLY_SUBCOMMANDS: Record<string, readonly string[]>;
11
20
  /**
12
21
  * Validation commands that are safe enough to run without an interactive
13
22
  * confirmation prompt. They may read the project and execute local test code,
@@ -25,14 +34,55 @@ export declare const DANGEROUS_PATTERNS: {
25
34
  * Potentially destructive patterns that should ask for confirmation.
26
35
  */
27
36
  export declare const POTENTIALLY_DESTRUCTIVE_PATTERNS: RegExp[];
37
+ /**
38
+ * Result of a quote-aware scan over a whole command line.
39
+ */
40
+ export interface ShellCommandScan {
41
+ /** The individual commands on the line, split on unquoted separators. */
42
+ segments: string[];
43
+ /**
44
+ * False when the line uses a construct this scanner cannot reason about --
45
+ * command substitution, process substitution or an unbalanced quote. Such a
46
+ * line can hide an arbitrary command and must never be auto-approved.
47
+ */
48
+ supported: boolean;
49
+ /** True when the line redirects output somewhere other than /dev/null. */
50
+ writesFile: boolean;
51
+ }
52
+ /**
53
+ * Split a command line into the individual commands it will actually run.
54
+ *
55
+ * The classifier below hands out "run without confirmation" verdicts, so it has
56
+ * to see every command on the line rather than just the leading token. Quote
57
+ * state is tracked so `echo "a && b"` stays one segment, and substitutions are
58
+ * reported as unsupported instead of being silently skipped over.
59
+ */
60
+ export declare function scanShellCommand(cmd: string): ShellCommandScan;
28
61
  /**
29
62
  * Check if a command is read-only and safe to execute without confirmation.
63
+ *
64
+ * Every command on the line must be independently read-only.
30
65
  */
31
66
  export declare function isReadOnlyCommand(cmd: string): boolean;
32
67
  /**
33
68
  * Check if a command is a bounded validation command.
69
+ *
70
+ * Segment-aware for the same reason as `isReadOnlyCommand`: without it,
71
+ * `npm test && rm -rf /tmp/x` matches the leading validation pattern and is
72
+ * auto-approved in full.
34
73
  */
35
74
  export declare function isValidationCommand(cmd: string): boolean;
75
+ /**
76
+ * Structured replacement for the literal `rm -rf /` patterns.
77
+ *
78
+ * Returns the normalised target that makes the command catastrophic, or null.
79
+ * Matching on parsed flags and canonicalised operands closes the rewrites that
80
+ * defeat the anchored patterns: `rm -fr /`, `rm -r -f /`,
81
+ * `rm --recursive --force /`, `rm -rf /*` and, most importantly,
82
+ * `rm -rf / --no-preserve-root` -- the only form that actually deletes anything
83
+ * on GNU coreutils.
84
+ */
85
+ export declare function findDestructiveRmTarget(cmd: string): string | null;
36
86
  /**
37
87
  * Check if a command matches dangerous patterns.
38
88
  * Returns the first matched dangerous pattern, or null if safe.
@@ -53,22 +103,4 @@ export declare function assessCommandSecurity(cmd: string): {
53
103
  reason?: string;
54
104
  isReadOnly: boolean;
55
105
  };
56
- /**
57
- * Sandbox execution options.
58
- */
59
- export interface SandboxOptions {
60
- mode: 'none' | 'docker' | 'bubblewrap';
61
- container?: string;
62
- timeout?: number;
63
- network?: boolean;
64
- }
65
- /**
66
- * Default sandbox options (disabled).
67
- */
68
- export declare const DEFAULT_SANDBOX_OPTIONS: SandboxOptions;
69
- /**
70
- * Wrap command for sandbox execution.
71
- * Returns the modified command for sandbox execution.
72
- */
73
- export declare function wrapForSandbox(cmd: string, options: SandboxOptions): string;
74
106
  //# sourceMappingURL=bash_security.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bash_security.d.ts","sourceRoot":"","sources":["../../src/tools/bash_security.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,eAAO,MAAM,kBAAkB,UAiI9B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,UAOvC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;GAiC9B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gCAAgC,UAW5C,CAAC;AAEF;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CA2DtD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAO7F;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO7D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG;IAClD,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;CACrB,CA2CA;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,YAAY,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,EAAE,cAErC,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,MAAM,CAkB3E"}
1
+ {"version":3,"file":"bash_security.d.ts","sourceRoot":"","sources":["../../src/tools/bash_security.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,eAAO,MAAM,kBAAkB,UA4H9B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAmBnE,CAAC;AAuBF;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,UAOvC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB;;;GAoC9B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gCAAgC,UAW5C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yEAAyE;IACzE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB,0EAA0E;IAC1E,UAAU,EAAE,OAAO,CAAC;CACrB;AAKD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAuG9D;AAgBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEtD;AAuFD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAIxD;AAkID;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBlE;AAiBD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAe7F;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO7D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG;IAClD,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;CACrB,CA2CA"}
@@ -5,13 +5,14 @@
5
5
  * Provides safety checks and sandbox options for command execution.
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.DEFAULT_SANDBOX_OPTIONS = exports.POTENTIALLY_DESTRUCTIVE_PATTERNS = exports.DANGEROUS_PATTERNS = exports.VALIDATION_COMMAND_PATTERNS = exports.READ_ONLY_COMMANDS = void 0;
8
+ exports.POTENTIALLY_DESTRUCTIVE_PATTERNS = exports.DANGEROUS_PATTERNS = exports.VALIDATION_COMMAND_PATTERNS = exports.READ_ONLY_SUBCOMMANDS = exports.READ_ONLY_COMMANDS = void 0;
9
+ exports.scanShellCommand = scanShellCommand;
9
10
  exports.isReadOnlyCommand = isReadOnlyCommand;
10
11
  exports.isValidationCommand = isValidationCommand;
12
+ exports.findDestructiveRmTarget = findDestructiveRmTarget;
11
13
  exports.checkDangerousCommand = checkDangerousCommand;
12
14
  exports.isPotentiallyDestructive = isPotentiallyDestructive;
13
15
  exports.assessCommandSecurity = assessCommandSecurity;
14
- exports.wrapForSandbox = wrapForSandbox;
15
16
  /**
16
17
  * Commands that are considered read-only and safe to execute without confirmation.
17
18
  * These commands only read data and do not modify the filesystem.
@@ -112,16 +113,11 @@ exports.READ_ONLY_COMMANDS = [
112
113
  'htop',
113
114
  'lsof',
114
115
  'pgrep',
115
- // Package managers (checking/listing is read-only)
116
- 'npm',
117
- 'npx',
118
- 'yarn',
119
- 'pnpm',
120
- 'pip',
121
- 'pip3',
122
- 'cargo',
123
- 'top',
124
- 'htop',
116
+ // Job control
117
+ // NOTE: the package-manager drivers (npm/npx/yarn/pnpm/pip/cargo) are
118
+ // deliberately NOT listed here. Whether they read or execute depends entirely
119
+ // on the sub-command, so they are allow-listed per sub-command in
120
+ // READ_ONLY_SUBCOMMANDS instead.
125
121
  'jobs',
126
122
  // JSON/YAML processing (read-only when no file write)
127
123
  'jq',
@@ -136,6 +132,51 @@ exports.READ_ONLY_COMMANDS = [
136
132
  '--version',
137
133
  '-V',
138
134
  ];
135
+ /**
136
+ * Sub-commands that only read state, keyed by the driver that runs them.
137
+ *
138
+ * The drivers themselves must never appear in READ_ONLY_COMMANDS: `npm run`,
139
+ * `npm exec`, `yarn <script>`, `pnpm run`, `cargo run` and `npx <pkg>` all
140
+ * execute arbitrary project-defined or freshly downloaded code, so the safe
141
+ * surface has to be enumerated rather than subtracted.
142
+ */
143
+ exports.READ_ONLY_SUBCOMMANDS = {
144
+ git: [
145
+ 'status',
146
+ 'log',
147
+ 'diff',
148
+ 'show',
149
+ 'branch',
150
+ 'tag',
151
+ 'remote',
152
+ 'rev-parse',
153
+ 'ls-files',
154
+ 'ls-tree',
155
+ ],
156
+ npm: ['list', 'ls', 'info', 'view', 'search', 'outdated', 'why'],
157
+ yarn: ['list', 'info', 'why'],
158
+ pnpm: ['list', 'ls', 'info', 'why', 'outdated'],
159
+ cargo: ['tree', 'metadata', 'search'],
160
+ pip: ['list', 'show', 'freeze'],
161
+ pip3: ['list', 'show', 'freeze'],
162
+ };
163
+ /**
164
+ * git options that hand execution to an external program or write a file,
165
+ * whichever sub-command they are attached to.
166
+ */
167
+ const GIT_UNSAFE_OPTIONS = /(^|\s)--(ext-diff|extcmd|output|exec-path|upload-pack|receive-pack)\b/;
168
+ /**
169
+ * `git branch` / `git tag` only list when they are given nothing but these
170
+ * flags. Any other argument may create, move or delete a ref, so the allow-list
171
+ * is deliberately valueless flags only -- `git branch --contains HEAD` reads,
172
+ * but prompting for it is far cheaper than letting `git branch -D main` through.
173
+ */
174
+ const GIT_LISTING_FLAGS = {
175
+ branch: /^(-a|--all|-r|--remotes|-v|-vv|--verbose|-l|--list|--no-color|--color(=.+)?|--sort=.+|--format=.+)$/,
176
+ tag: /^(-l|--list|-n\d*|-i|--ignore-case|--no-color|--color(=.+)?|--sort=.+|--format=.+)$/,
177
+ };
178
+ /** `git remote` reads with no argument, or via these two sub-sub-commands. */
179
+ const GIT_REMOTE_READ_ONLY_ACTIONS = new Set(['show', 'get-url']);
139
180
  /**
140
181
  * Validation commands that are safe enough to run without an interactive
141
182
  * confirmation prompt. They may read the project and execute local test code,
@@ -153,7 +194,10 @@ exports.VALIDATION_COMMAND_PATTERNS = [
153
194
  * Dangerous command patterns that should always be blocked or require confirmation.
154
195
  */
155
196
  exports.DANGEROUS_PATTERNS = [
156
- // Filesystem destruction
197
+ // Filesystem destruction.
198
+ // NOTE: these literal forms are a backstop only. Flag order, long options and
199
+ // trailing arguments all defeat them, so the authoritative check is the
200
+ // structured one in findDestructiveRmTarget(); see checkDangerousCommand().
157
201
  { pattern: /rm\s+-rf\s+\/$/, reason: 'Attempting to delete root directory' },
158
202
  { pattern: /rm\s+-rf\s+~$/, reason: 'Attempting to delete home directory' },
159
203
  { pattern: /rm\s+-rf\s+\*/, reason: 'Attempting to delete all files in current directory' },
@@ -195,11 +239,136 @@ exports.POTENTIALLY_DESTRUCTIVE_PATTERNS = [
195
239
  /curl.*>\s*\//,
196
240
  /wget.*-O\s*\//,
197
241
  ];
242
+ /** The one redirect target that does not count as writing to the filesystem. */
243
+ const DISCARD_REDIRECT_TARGET = '/dev/null';
244
+ /**
245
+ * Split a command line into the individual commands it will actually run.
246
+ *
247
+ * The classifier below hands out "run without confirmation" verdicts, so it has
248
+ * to see every command on the line rather than just the leading token. Quote
249
+ * state is tracked so `echo "a && b"` stays one segment, and substitutions are
250
+ * reported as unsupported instead of being silently skipped over.
251
+ */
252
+ function scanShellCommand(cmd) {
253
+ const segments = [];
254
+ let current = '';
255
+ let supported = true;
256
+ let writesFile = false;
257
+ let inSingleQuote = false;
258
+ let inDoubleQuote = false;
259
+ const pushSegment = () => {
260
+ const segment = current.trim();
261
+ if (segment.length > 0) {
262
+ segments.push(segment);
263
+ }
264
+ current = '';
265
+ };
266
+ for (let i = 0; i < cmd.length; i++) {
267
+ const ch = cmd[i];
268
+ const next = cmd[i + 1];
269
+ if (ch === '\\' && !inSingleQuote && next !== undefined) {
270
+ current += ch + next;
271
+ i++;
272
+ continue;
273
+ }
274
+ if (ch === "'" && !inDoubleQuote) {
275
+ inSingleQuote = !inSingleQuote;
276
+ current += ch;
277
+ continue;
278
+ }
279
+ if (ch === '"' && !inSingleQuote) {
280
+ inDoubleQuote = !inDoubleQuote;
281
+ current += ch;
282
+ continue;
283
+ }
284
+ if (inSingleQuote || inDoubleQuote) {
285
+ current += ch;
286
+ continue;
287
+ }
288
+ // Command and process substitution can hide an arbitrary command inside an
289
+ // otherwise innocent-looking line, and neither is worth modelling here.
290
+ if (ch === '`' || (ch === '$' && next === '(') || ((ch === '<' || ch === '>') && next === '(')) {
291
+ supported = false;
292
+ current += ch;
293
+ continue;
294
+ }
295
+ if (ch === ';' || ch === '\n') {
296
+ pushSegment();
297
+ continue;
298
+ }
299
+ if ((ch === '&' && next === '&') || (ch === '|' && next === '|')) {
300
+ pushSegment();
301
+ i++;
302
+ continue;
303
+ }
304
+ if (ch === '&' || ch === '|') {
305
+ pushSegment();
306
+ continue;
307
+ }
308
+ if (ch === '>') {
309
+ let cursor = i + 1;
310
+ if (cmd[cursor] === '>') {
311
+ cursor++;
312
+ }
313
+ if (cmd[cursor] === '&') {
314
+ // `>&1` / `2>&1` duplicate a descriptor and `>&-` closes one; nothing
315
+ // reaches the filesystem. Consume the whole reference so its `&` is not
316
+ // mistaken for a background-job separator.
317
+ let end = cursor + 1;
318
+ while (end < cmd.length && cmd[end] >= '0' && cmd[end] <= '9') {
319
+ end++;
320
+ }
321
+ if (cmd[end] === '-') {
322
+ end++;
323
+ }
324
+ current += cmd.slice(i, end);
325
+ i = end - 1;
326
+ continue;
327
+ }
328
+ while (cursor < cmd.length && (cmd[cursor] === ' ' || cmd[cursor] === '\t')) {
329
+ cursor++;
330
+ }
331
+ const target = cmd.slice(cursor).split(/[\s;&|<>]/)[0];
332
+ if (target !== DISCARD_REDIRECT_TARGET) {
333
+ writesFile = true;
334
+ }
335
+ current += ch;
336
+ continue;
337
+ }
338
+ current += ch;
339
+ }
340
+ pushSegment();
341
+ return {
342
+ segments,
343
+ supported: supported && !inSingleQuote && !inDoubleQuote,
344
+ writesFile,
345
+ };
346
+ }
347
+ /**
348
+ * Require every command on the line to satisfy `predicate`.
349
+ *
350
+ * A single unrecognised segment is enough to withhold the auto-approval, which
351
+ * is what stops `echo hi && rm -rf ~` from inheriting `echo`'s verdict.
352
+ */
353
+ function everySegmentSatisfies(cmd, predicate) {
354
+ const scan = scanShellCommand(cmd.trim());
355
+ if (!scan.supported || scan.writesFile || scan.segments.length === 0) {
356
+ return false;
357
+ }
358
+ return scan.segments.every(predicate);
359
+ }
198
360
  /**
199
361
  * Check if a command is read-only and safe to execute without confirmation.
362
+ *
363
+ * Every command on the line must be independently read-only.
200
364
  */
201
365
  function isReadOnlyCommand(cmd) {
202
- const trimmedCmd = cmd.trim();
366
+ return everySegmentSatisfies(cmd, isReadOnlySegment);
367
+ }
368
+ /**
369
+ * Check whether a single command -- with no separators left in it -- is read-only.
370
+ */
371
+ function isReadOnlySegment(trimmedCmd) {
203
372
  // Check exact matches first
204
373
  if (exports.READ_ONLY_COMMANDS.includes(trimmedCmd)) {
205
374
  return true;
@@ -230,42 +399,217 @@ function isReadOnlyCommand(cmd) {
230
399
  if (baseCmd === 'sort' && (/(^|\s)-o\b/.test(trimmedCmd) || trimmedCmd.includes('>'))) {
231
400
  return false; // sort -o / redirect writes a file
232
401
  }
233
- // npm/pip/cargo/yarn install commands have side effects
234
- if ((baseCmd === 'npm' || baseCmd === 'yarn' || baseCmd === 'pnpm') &&
235
- /\b(install|add|remove|uninstall|publish|link|unlink|deprecate|audit fix|fund)\b/.test(trimmedCmd)) {
236
- return false;
237
- }
238
- if ((baseCmd === 'pip' || baseCmd === 'pip3') && /\binstall\b/.test(trimmedCmd)) {
239
- return false; // pip install modifies system
240
- }
241
- if (baseCmd === 'cargo' && /\b(install|publish|update|remove)\b/.test(trimmedCmd)) {
242
- return false;
243
- }
244
402
  return true;
245
403
  }
246
- // Check for git read commands
247
- if (trimmedCmd.startsWith('git ')) {
248
- const gitCmd = trimmedCmd.slice(4).trim();
249
- for (const roGitCmd of exports.READ_ONLY_COMMANDS.filter(c => c.startsWith('git '))) {
250
- if (gitCmd.startsWith(roGitCmd.slice(4))) {
251
- return true;
252
- }
253
- }
404
+ // Driver commands are read-only only for an explicitly allow-listed
405
+ // sub-command, matched on the exact token.
406
+ return isReadOnlyDriverInvocation(trimmedCmd);
407
+ }
408
+ /**
409
+ * Classify `git`, `npm`, `cargo` and friends by their sub-command.
410
+ *
411
+ * Matching is on the exact sub-command token. The previous implementation used
412
+ * `startsWith`, which let `git difftool --extcmd=...` match the `git diff`
413
+ * entry and run an arbitrary program.
414
+ */
415
+ function isReadOnlyDriverInvocation(segment) {
416
+ const tokens = segment.split(/\s+/).filter(token => token.length > 0);
417
+ const driver = tokens[0];
418
+ const subcommand = tokens[1];
419
+ const allowed = driver ? exports.READ_ONLY_SUBCOMMANDS[driver] : undefined;
420
+ if (!allowed || !subcommand || !allowed.includes(subcommand)) {
421
+ return false;
254
422
  }
255
- return false;
423
+ if (driver !== 'git') {
424
+ return true;
425
+ }
426
+ if (GIT_UNSAFE_OPTIONS.test(segment)) {
427
+ return false;
428
+ }
429
+ const args = tokens.slice(2);
430
+ if (subcommand === 'remote') {
431
+ // `git remote [-v]` lists; `git remote show|get-url <name>` reads.
432
+ // Everything else -- add, remove, rename, set-url, prune -- mutates.
433
+ const positional = args.filter(arg => arg !== '-v' && arg !== '--verbose');
434
+ return positional.length === 0 || GIT_REMOTE_READ_ONLY_ACTIONS.has(positional[0]);
435
+ }
436
+ const listingFlags = GIT_LISTING_FLAGS[subcommand];
437
+ if (listingFlags) {
438
+ return args.every(arg => listingFlags.test(arg));
439
+ }
440
+ return true;
256
441
  }
257
442
  /**
258
443
  * Check if a command is a bounded validation command.
444
+ *
445
+ * Segment-aware for the same reason as `isReadOnlyCommand`: without it,
446
+ * `npm test && rm -rf /tmp/x` matches the leading validation pattern and is
447
+ * auto-approved in full.
259
448
  */
260
449
  function isValidationCommand(cmd) {
261
- const trimmedCmd = cmd.trim();
262
- return exports.VALIDATION_COMMAND_PATTERNS.some(pattern => pattern.test(trimmedCmd));
450
+ return everySegmentSatisfies(cmd, segment => exports.VALIDATION_COMMAND_PATTERNS.some(pattern => pattern.test(segment)));
451
+ }
452
+ /** Wrappers that may precede `rm` without changing what it deletes. */
453
+ const COMMAND_WRAPPERS = new Set(['sudo', 'doas', 'command', 'builtin', 'nohup', 'time', 'exec']);
454
+ /**
455
+ * Targets whose deletion is never a legitimate agent action, in the normalised
456
+ * form produced by {@link normalizeRmTarget}.
457
+ */
458
+ const CATASTROPHIC_RM_TARGETS = new Set([
459
+ '/',
460
+ '~',
461
+ '.',
462
+ '..',
463
+ '*',
464
+ // System roots: wiping any of these bricks the machine just as thoroughly as
465
+ // `/` does, and no build or cleanup step has a reason to touch them.
466
+ '/bin',
467
+ '/boot',
468
+ '/dev',
469
+ '/etc',
470
+ '/lib',
471
+ '/lib64',
472
+ '/opt',
473
+ '/proc',
474
+ '/root',
475
+ '/sbin',
476
+ '/srv',
477
+ '/sys',
478
+ '/usr',
479
+ '/var',
480
+ '/home',
481
+ '/Users',
482
+ '/System',
483
+ '/Library',
484
+ '/Applications',
485
+ ]);
486
+ /**
487
+ * Reduce an `rm` operand to a canonical path so that every spelling of the same
488
+ * catastrophic target collapses onto one key: `/`, `/*`, `/**` and `///` all
489
+ * become `/`, and `~/`, `~/*`, `$HOME`, `${HOME}/` all become `~`.
490
+ */
491
+ function normalizeRmTarget(raw) {
492
+ let target = raw.trim();
493
+ const quote = target[0];
494
+ if ((quote === "'" || quote === '"') && target.endsWith(quote) && target.length > 1) {
495
+ target = target.slice(1, -1).trim();
496
+ }
497
+ target = target.replace(/^\$\{HOME\}/, '~').replace(/^\$HOME/, '~');
498
+ // A trailing glob deletes the directory's contents, which is the same disaster
499
+ // as deleting the directory itself.
500
+ target = target.replace(/\/\*+$/, '/');
501
+ target = target.replace(/\/{2,}/g, '/');
502
+ if (target.length > 1) {
503
+ target = target.replace(/\/+$/, '');
504
+ }
505
+ return target;
506
+ }
507
+ /**
508
+ * Parse a single command segment as an `rm` invocation.
509
+ *
510
+ * Returns null when the segment does not run `rm`. Flags are collected
511
+ * order-independently, so `-rf`, `-fr`, `-r -f` and `--recursive --force` are
512
+ * all recognised as the same request.
513
+ */
514
+ function parseRmInvocation(segment) {
515
+ const tokens = segment.split(/\s+/).filter(token => token.length > 0);
516
+ let index = 0;
517
+ while (index < tokens.length && COMMAND_WRAPPERS.has(tokens[index])) {
518
+ index++;
519
+ }
520
+ const binary = tokens[index];
521
+ if (!binary || !/(^|\/)rm$/.test(binary)) {
522
+ return null;
523
+ }
524
+ index++;
525
+ const invocation = {
526
+ recursive: false,
527
+ force: false,
528
+ noPreserveRoot: false,
529
+ targets: [],
530
+ };
531
+ let endOfOptions = false;
532
+ for (; index < tokens.length; index++) {
533
+ const token = tokens[index];
534
+ if (!endOfOptions && token === '--') {
535
+ endOfOptions = true;
536
+ continue;
537
+ }
538
+ if (!endOfOptions && token.startsWith('--')) {
539
+ if (token === '--recursive')
540
+ invocation.recursive = true;
541
+ else if (token === '--force')
542
+ invocation.force = true;
543
+ else if (token === '--no-preserve-root')
544
+ invocation.noPreserveRoot = true;
545
+ continue;
546
+ }
547
+ if (!endOfOptions && token.length > 1 && token.startsWith('-')) {
548
+ for (const flag of token.slice(1)) {
549
+ if (flag === 'r' || flag === 'R')
550
+ invocation.recursive = true;
551
+ else if (flag === 'f')
552
+ invocation.force = true;
553
+ }
554
+ continue;
555
+ }
556
+ invocation.targets.push(token);
557
+ }
558
+ return invocation;
559
+ }
560
+ /**
561
+ * Structured replacement for the literal `rm -rf /` patterns.
562
+ *
563
+ * Returns the normalised target that makes the command catastrophic, or null.
564
+ * Matching on parsed flags and canonicalised operands closes the rewrites that
565
+ * defeat the anchored patterns: `rm -fr /`, `rm -r -f /`,
566
+ * `rm --recursive --force /`, `rm -rf /*` and, most importantly,
567
+ * `rm -rf / --no-preserve-root` -- the only form that actually deletes anything
568
+ * on GNU coreutils.
569
+ */
570
+ function findDestructiveRmTarget(cmd) {
571
+ for (const segment of scanShellCommand(cmd).segments) {
572
+ const invocation = parseRmInvocation(segment);
573
+ if (!invocation)
574
+ continue;
575
+ // `rm /` without -r or -f cannot remove a directory, so it is noise rather
576
+ // than a threat. Either flag turns the same operand into a real deletion.
577
+ if (!invocation.recursive && !invocation.force)
578
+ continue;
579
+ for (const target of invocation.targets) {
580
+ if (CATASTROPHIC_RM_TARGETS.has(normalizeRmTarget(target))) {
581
+ return target;
582
+ }
583
+ }
584
+ }
585
+ return null;
586
+ }
587
+ /** Reported when the structured `rm` check fires rather than a literal pattern. */
588
+ const DESTRUCTIVE_RM_PATTERN = /\brm\b/;
589
+ /** Human-readable description of why a normalised target is off-limits. */
590
+ function describeCatastrophicTarget(raw) {
591
+ const normalized = normalizeRmTarget(raw);
592
+ if (normalized === '/')
593
+ return 'the root directory';
594
+ if (normalized === '~')
595
+ return 'the home directory';
596
+ if (normalized === '.' || normalized === '..' || normalized === '*') {
597
+ return 'the current directory contents';
598
+ }
599
+ return `the system directory ${normalized}`;
263
600
  }
264
601
  /**
265
602
  * Check if a command matches dangerous patterns.
266
603
  * Returns the first matched dangerous pattern, or null if safe.
267
604
  */
268
605
  function checkDangerousCommand(cmd) {
606
+ const rmTarget = findDestructiveRmTarget(cmd);
607
+ if (rmTarget) {
608
+ return {
609
+ pattern: DESTRUCTIVE_RM_PATTERN,
610
+ reason: `Attempting to delete ${describeCatastrophicTarget(rmTarget)} (${rmTarget})`,
611
+ };
612
+ }
269
613
  for (const { pattern, reason } of exports.DANGEROUS_PATTERNS) {
270
614
  if (pattern.test(cmd)) {
271
615
  return { pattern, reason };
@@ -327,30 +671,19 @@ function assessCommandSecurity(cmd) {
327
671
  isReadOnly: false,
328
672
  };
329
673
  }
330
- /**
331
- * Default sandbox options (disabled).
332
- */
333
- exports.DEFAULT_SANDBOX_OPTIONS = {
334
- mode: 'none',
335
- };
336
- /**
337
- * Wrap command for sandbox execution.
338
- * Returns the modified command for sandbox execution.
674
+ /*
675
+ * The `SandboxOptions` / `DEFAULT_SANDBOX_OPTIONS` / `wrapForSandbox` trio that
676
+ * used to live here has been removed.
677
+ *
678
+ * `wrapForSandbox` advertised network isolation it never delivered: it emitted
679
+ * `docker exec --network none <container> sh -c '<cmd>'`, but `--network` is a
680
+ * `docker run` flag and `docker exec` rejects it with `unknown flag`. With
681
+ * `network: true` the flag was dropped altogether, so neither configuration
682
+ * isolated anything. Building the wrapper as a shell string was unsound anyway:
683
+ * every layer re-parses the command, so a quoting bug becomes a sandbox escape.
684
+ *
685
+ * `src/tools/sandbox.ts` supersedes it with an argv-based implementation that
686
+ * probes backend availability and fails closed. Use `planSandboxedCommand()`
687
+ * from there instead.
339
688
  */
340
- function wrapForSandbox(cmd, options) {
341
- if (options.mode === 'none') {
342
- return cmd;
343
- }
344
- if (options.mode === 'docker') {
345
- const container = options.container || 'orion-code-sandbox';
346
- const networkFlag = options.network ? '' : '--network none';
347
- return `docker exec ${networkFlag} ${container} sh -c '${cmd.replace(/'/g, "'\\''")}'`;
348
- }
349
- if (options.mode === 'bubblewrap') {
350
- // bubblewrap (bwrap) for Linux sandboxing
351
- const networkFlag = options.network ? '' : '--unshare-net';
352
- return `bwrap ${networkFlag} --ro-bind /usr /usr --ro-bind /lib /lib --ro-bind /bin /bin --bind /tmp /tmp --proc /proc --dev-bind /dev /dev sh -c '${cmd.replace(/'/g, "'\\''")}'`;
353
- }
354
- return cmd;
355
- }
356
689
  //# sourceMappingURL=bash_security.js.map