@machina.ai/cell-cli 1.60.0-rc1 → 1.64.0-rc1

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 (270) hide show
  1. package/dist/index.js +7 -0
  2. package/dist/index.js.map +1 -1
  3. package/dist/package.json +3 -3
  4. package/dist/src/acp/acpResume.test.js +50 -0
  5. package/dist/src/acp/acpResume.test.js.map +1 -1
  6. package/dist/src/acp/acpRpcDispatcher.d.ts +1 -1
  7. package/dist/src/acp/acpRpcDispatcher.js +2 -2
  8. package/dist/src/acp/acpRpcDispatcher.js.map +1 -1
  9. package/dist/src/acp/acpRpcDispatcher.test.js +9 -0
  10. package/dist/src/acp/acpRpcDispatcher.test.js.map +1 -1
  11. package/dist/src/acp/acpSession.d.ts +1 -1
  12. package/dist/src/acp/acpSession.js +90 -80
  13. package/dist/src/acp/acpSession.js.map +1 -1
  14. package/dist/src/acp/acpSession.test.js +279 -2
  15. package/dist/src/acp/acpSession.test.js.map +1 -1
  16. package/dist/src/acp/acpSessionManager.d.ts +2 -2
  17. package/dist/src/acp/acpSessionManager.js +165 -73
  18. package/dist/src/acp/acpSessionManager.js.map +1 -1
  19. package/dist/src/acp/acpSessionManager.test.js +204 -1
  20. package/dist/src/acp/acpSessionManager.test.js.map +1 -1
  21. package/dist/src/acp/acpUtils.js +5 -3
  22. package/dist/src/acp/acpUtils.js.map +1 -1
  23. package/dist/src/config/config.js +1 -0
  24. package/dist/src/config/config.js.map +1 -1
  25. package/dist/src/config/extension-manager.js +8 -5
  26. package/dist/src/config/extension-manager.js.map +1 -1
  27. package/dist/src/config/extension-manager.test.js +27 -0
  28. package/dist/src/config/extension-manager.test.js.map +1 -1
  29. package/dist/src/config/extensions/update.js +7 -2
  30. package/dist/src/config/extensions/update.js.map +1 -1
  31. package/dist/src/config/extensions/update.test.js +21 -0
  32. package/dist/src/config/extensions/update.test.js.map +1 -1
  33. package/dist/src/config/mcp/mcpServerEnablement.d.ts +5 -0
  34. package/dist/src/config/mcp/mcpServerEnablement.js +26 -3
  35. package/dist/src/config/mcp/mcpServerEnablement.js.map +1 -1
  36. package/dist/src/config/mcp/mcpServerEnablement.test.js +27 -0
  37. package/dist/src/config/mcp/mcpServerEnablement.test.js.map +1 -1
  38. package/dist/src/config/settings.test.js +22 -0
  39. package/dist/src/config/settings.test.js.map +1 -1
  40. package/dist/src/config/settingsSchema.d.ts +9 -0
  41. package/dist/src/config/settingsSchema.js +37 -1
  42. package/dist/src/config/settingsSchema.js.map +1 -1
  43. package/dist/src/core/auth.test.js +1 -1
  44. package/dist/src/core/auth.test.js.map +1 -1
  45. package/dist/src/gemini.js +110 -18
  46. package/dist/src/gemini.js.map +1 -1
  47. package/dist/src/gemini_uncaught.test.d.ts +6 -0
  48. package/dist/src/gemini_uncaught.test.js +91 -0
  49. package/dist/src/gemini_uncaught.test.js.map +1 -0
  50. package/dist/src/generated/git-commit.d.ts +2 -2
  51. package/dist/src/generated/git-commit.js +2 -2
  52. package/dist/src/patches/http-proxy-agent.d.ts +4 -1
  53. package/dist/src/patches/http-proxy-agent.js +38 -2
  54. package/dist/src/patches/http-proxy-agent.js.map +1 -1
  55. package/dist/src/patches/https-proxy-agent.d.ts +4 -1
  56. package/dist/src/patches/https-proxy-agent.js +38 -2
  57. package/dist/src/patches/https-proxy-agent.js.map +1 -1
  58. package/dist/src/services/FileCommandLoader.js +3 -5
  59. package/dist/src/services/FileCommandLoader.js.map +1 -1
  60. package/dist/src/services/FileCommandLoader.test.js +68 -6
  61. package/dist/src/services/FileCommandLoader.test.js.map +1 -1
  62. package/dist/src/ui/AppContainer.js +42 -39
  63. package/dist/src/ui/AppContainer.js.map +1 -1
  64. package/dist/src/ui/AppContainer.test.js +30 -0
  65. package/dist/src/ui/AppContainer.test.js.map +1 -1
  66. package/dist/src/ui/auth/AuthDialog.js +11 -3
  67. package/dist/src/ui/auth/AuthDialog.js.map +1 -1
  68. package/dist/src/ui/auth/useAuth.test.js +1 -1
  69. package/dist/src/ui/auth/useAuth.test.js.map +1 -1
  70. package/dist/src/ui/commands/bugCommand.js +3 -3
  71. package/dist/src/ui/commands/bugCommand.js.map +1 -1
  72. package/dist/src/ui/commands/bugCommand.test.js +44 -0
  73. package/dist/src/ui/commands/bugCommand.test.js.map +1 -1
  74. package/dist/src/ui/commands/bugMemoryCommand.js +2 -2
  75. package/dist/src/ui/commands/bugMemoryCommand.js.map +1 -1
  76. package/dist/src/ui/commands/bugMemoryCommand.test.js +12 -0
  77. package/dist/src/ui/commands/bugMemoryCommand.test.js.map +1 -1
  78. package/dist/src/ui/components/AsciiArt.d.ts +6 -6
  79. package/dist/src/ui/components/AsciiArt.js +6 -6
  80. package/dist/src/ui/components/AskUserDialog.js +7 -2
  81. package/dist/src/ui/components/AskUserDialog.js.map +1 -1
  82. package/dist/src/ui/components/AskUserDialog.test.js +33 -0
  83. package/dist/src/ui/components/AskUserDialog.test.js.map +1 -1
  84. package/dist/src/ui/components/Composer.js +4 -4
  85. package/dist/src/ui/components/Composer.js.map +1 -1
  86. package/dist/src/ui/components/Composer.test.js +50 -2
  87. package/dist/src/ui/components/Composer.test.js.map +1 -1
  88. package/dist/src/ui/components/InputPrompt.js +16 -10
  89. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  90. package/dist/src/ui/components/InputPrompt.test.js +103 -7
  91. package/dist/src/ui/components/InputPrompt.test.js.map +1 -1
  92. package/dist/src/ui/components/LoadingIndicator.d.ts +1 -0
  93. package/dist/src/ui/components/LoadingIndicator.js +13 -11
  94. package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
  95. package/dist/src/ui/components/LoadingIndicator.test.js +29 -0
  96. package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -1
  97. package/dist/src/ui/components/MainContent.js +79 -14
  98. package/dist/src/ui/components/MainContent.js.map +1 -1
  99. package/dist/src/ui/components/MainContent.test.js +218 -5
  100. package/dist/src/ui/components/MainContent.test.js.map +1 -1
  101. package/dist/src/ui/components/ProgressBar.js +4 -3
  102. package/dist/src/ui/components/ProgressBar.js.map +1 -1
  103. package/dist/src/ui/components/ProgressBar.test.js +12 -0
  104. package/dist/src/ui/components/ProgressBar.test.js.map +1 -1
  105. package/dist/src/ui/components/RewindViewer.js +2 -1
  106. package/dist/src/ui/components/RewindViewer.js.map +1 -1
  107. package/dist/src/ui/components/RewindViewer.test.js +38 -0
  108. package/dist/src/ui/components/RewindViewer.test.js.map +1 -1
  109. package/dist/src/ui/components/StatusRow.d.ts +2 -0
  110. package/dist/src/ui/components/StatusRow.js +11 -6
  111. package/dist/src/ui/components/StatusRow.js.map +1 -1
  112. package/dist/src/ui/components/StatusRow.test.js +158 -0
  113. package/dist/src/ui/components/StatusRow.test.js.map +1 -1
  114. package/dist/src/ui/components/ToolConfirmationQueue.js +4 -2
  115. package/dist/src/ui/components/ToolConfirmationQueue.js.map +1 -1
  116. package/dist/src/ui/components/ToolConfirmationQueue.test.js +30 -0
  117. package/dist/src/ui/components/ToolConfirmationQueue.test.js.map +1 -1
  118. package/dist/src/ui/components/messages/DenseToolMessage.js +5 -5
  119. package/dist/src/ui/components/messages/DenseToolMessage.js.map +1 -1
  120. package/dist/src/ui/components/messages/DenseToolMessage.test.js +13 -0
  121. package/dist/src/ui/components/messages/DenseToolMessage.test.js.map +1 -1
  122. package/dist/src/ui/components/messages/DiffRenderer.d.ts +1 -0
  123. package/dist/src/ui/components/messages/DiffRenderer.js +16 -8
  124. package/dist/src/ui/components/messages/DiffRenderer.js.map +1 -1
  125. package/dist/src/ui/components/messages/DiffRenderer.test.js +42 -0
  126. package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -1
  127. package/dist/src/ui/components/messages/ShellToolMessage.js +4 -3
  128. package/dist/src/ui/components/messages/ShellToolMessage.js.map +1 -1
  129. package/dist/src/ui/components/messages/ToolConfirmationMessage.js +74 -16
  130. package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
  131. package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js +80 -7
  132. package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js.map +1 -1
  133. package/dist/src/ui/components/messages/ToolGroupMessage.js +6 -5
  134. package/dist/src/ui/components/messages/ToolGroupMessage.js.map +1 -1
  135. package/dist/src/ui/components/messages/ToolMessage.js +2 -1
  136. package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
  137. package/dist/src/ui/components/messages/ToolResultDisplay.js +11 -8
  138. package/dist/src/ui/components/messages/ToolResultDisplay.js.map +1 -1
  139. package/dist/src/ui/components/messages/ToolShared.js +5 -4
  140. package/dist/src/ui/components/messages/ToolShared.js.map +1 -1
  141. package/dist/src/ui/components/shared/HalfLinePaddedBox.js +4 -2
  142. package/dist/src/ui/components/shared/HalfLinePaddedBox.js.map +1 -1
  143. package/dist/src/ui/components/shared/HalfLinePaddedBox.test.js +8 -0
  144. package/dist/src/ui/components/shared/HalfLinePaddedBox.test.js.map +1 -1
  145. package/dist/src/ui/components/shared/SearchableList.js +1 -1
  146. package/dist/src/ui/components/shared/SearchableList.js.map +1 -1
  147. package/dist/src/ui/components/shared/SearchableList.test.js +13 -0
  148. package/dist/src/ui/components/shared/SearchableList.test.js.map +1 -1
  149. package/dist/src/ui/components/shared/TextInput.js +2 -2
  150. package/dist/src/ui/components/shared/TextInput.js.map +1 -1
  151. package/dist/src/ui/components/views/ExtensionRegistryView.test.js +2 -0
  152. package/dist/src/ui/components/views/ExtensionRegistryView.test.js.map +1 -1
  153. package/dist/src/ui/contexts/KeypressContext.js +20 -2
  154. package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
  155. package/dist/src/ui/contexts/KeypressContext.test.js +24 -0
  156. package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
  157. package/dist/src/ui/contexts/UIStateContext.d.ts +1 -0
  158. package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
  159. package/dist/src/ui/emergency-stop.test.d.ts +6 -0
  160. package/dist/src/ui/emergency-stop.test.js +116 -0
  161. package/dist/src/ui/emergency-stop.test.js.map +1 -0
  162. package/dist/src/ui/hooks/atCommandProcessor.d.ts +8 -5
  163. package/dist/src/ui/hooks/atCommandProcessor.js +47 -16
  164. package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
  165. package/dist/src/ui/hooks/atCommandProcessor.test.js +160 -0
  166. package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -1
  167. package/dist/src/ui/hooks/useComposerStatus.d.ts +1 -0
  168. package/dist/src/ui/hooks/useComposerStatus.js +1 -0
  169. package/dist/src/ui/hooks/useComposerStatus.js.map +1 -1
  170. package/dist/src/ui/hooks/useFocus.js +1 -0
  171. package/dist/src/ui/hooks/useFocus.js.map +1 -1
  172. package/dist/src/ui/hooks/useFolderTrust.js +16 -16
  173. package/dist/src/ui/hooks/useFolderTrust.js.map +1 -1
  174. package/dist/src/ui/hooks/useFolderTrust.test.js +186 -3
  175. package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -1
  176. package/dist/src/ui/hooks/useGeminiStream.js +4 -12
  177. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  178. package/dist/src/ui/hooks/useGeminiStream.test.js +134 -2
  179. package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -1
  180. package/dist/src/ui/hooks/useLoadingIndicator.d.ts +1 -0
  181. package/dist/src/ui/hooks/useLoadingIndicator.js +1 -0
  182. package/dist/src/ui/hooks/useLoadingIndicator.js.map +1 -1
  183. package/dist/src/ui/hooks/useLoadingIndicator.test.js +2 -0
  184. package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
  185. package/dist/src/ui/hooks/useQuotaAndFallback.js +2 -2
  186. package/dist/src/ui/hooks/useQuotaAndFallback.js.map +1 -1
  187. package/dist/src/ui/hooks/useSelectionList.js +24 -1
  188. package/dist/src/ui/hooks/useSelectionList.js.map +1 -1
  189. package/dist/src/ui/hooks/useSelectionList.test.js +63 -1
  190. package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
  191. package/dist/src/ui/utils/CodeColorizer.d.ts +1 -0
  192. package/dist/src/ui/utils/CodeColorizer.js +13 -7
  193. package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
  194. package/dist/src/ui/utils/TableRenderer.js +3 -2
  195. package/dist/src/ui/utils/TableRenderer.js.map +1 -1
  196. package/dist/src/ui/utils/borderStyles.d.ts +1 -0
  197. package/dist/src/ui/utils/borderStyles.js +1 -0
  198. package/dist/src/ui/utils/borderStyles.js.map +1 -1
  199. package/dist/src/ui/utils/fileUtils.d.ts +4 -0
  200. package/dist/src/ui/utils/fileUtils.js +13 -0
  201. package/dist/src/ui/utils/fileUtils.js.map +1 -1
  202. package/dist/src/ui/utils/renderBorder.d.ts +27 -0
  203. package/dist/src/ui/utils/renderBorder.js +46 -0
  204. package/dist/src/ui/utils/renderBorder.js.map +1 -0
  205. package/dist/src/ui/utils/renderBorder.test.d.ts +6 -0
  206. package/dist/src/ui/utils/renderBorder.test.js +74 -0
  207. package/dist/src/ui/utils/renderBorder.test.js.map +1 -0
  208. package/dist/src/ui/utils/rewindFileOps.d.ts +9 -0
  209. package/dist/src/ui/utils/rewindFileOps.js +25 -1
  210. package/dist/src/ui/utils/rewindFileOps.js.map +1 -1
  211. package/dist/src/ui/utils/rewindFileOps.test.js +94 -1
  212. package/dist/src/ui/utils/rewindFileOps.test.js.map +1 -1
  213. package/dist/src/ui/utils/terminalCapabilityManager.js +7 -0
  214. package/dist/src/ui/utils/terminalCapabilityManager.js.map +1 -1
  215. package/dist/src/ui/utils/terminalCapabilityManager.stdin-flow.test.d.ts +6 -0
  216. package/dist/src/ui/utils/terminalCapabilityManager.stdin-flow.test.js +105 -0
  217. package/dist/src/ui/utils/terminalCapabilityManager.stdin-flow.test.js.map +1 -0
  218. package/dist/src/utils/commentJson.js +66 -5
  219. package/dist/src/utils/commentJson.js.map +1 -1
  220. package/dist/src/utils/commentJson.test.js +21 -0
  221. package/dist/src/utils/commentJson.test.js.map +1 -1
  222. package/dist/src/utils/handleAutoUpdate.test.js +2 -2
  223. package/dist/src/utils/persistentState.js +84 -15
  224. package/dist/src/utils/persistentState.js.map +1 -1
  225. package/dist/src/utils/persistentState.test.js +66 -9
  226. package/dist/src/utils/persistentState.test.js.map +1 -1
  227. package/dist/src/utils/persistentStateRecovery.test.d.ts +6 -0
  228. package/dist/src/utils/persistentStateRecovery.test.js +84 -0
  229. package/dist/src/utils/persistentStateRecovery.test.js.map +1 -0
  230. package/dist/src/utils/processUtils.d.ts +3 -1
  231. package/dist/src/utils/processUtils.js +26 -1
  232. package/dist/src/utils/processUtils.js.map +1 -1
  233. package/dist/src/utils/processUtils.test.js +58 -1
  234. package/dist/src/utils/processUtils.test.js.map +1 -1
  235. package/dist/src/utils/relaunch.js +7 -0
  236. package/dist/src/utils/relaunch.js.map +1 -1
  237. package/dist/src/utils/relaunch.test.js +16 -0
  238. package/dist/src/utils/relaunch.test.js.map +1 -1
  239. package/dist/src/utils/retry.d.ts +22 -0
  240. package/dist/src/utils/retry.js +54 -0
  241. package/dist/src/utils/retry.js.map +1 -0
  242. package/dist/src/utils/retry.test.d.ts +6 -0
  243. package/dist/src/utils/retry.test.js +141 -0
  244. package/dist/src/utils/retry.test.js.map +1 -0
  245. package/dist/src/utils/sandbox-macos-permissive-open.sb +36 -1
  246. package/dist/src/utils/sandbox-macos-permissive-proxied.sb +36 -1
  247. package/dist/src/utils/sandbox-macos-profiles.test.js +93 -0
  248. package/dist/src/utils/sandbox-macos-profiles.test.js.map +1 -1
  249. package/dist/src/utils/sandbox-macos-restrictive-open.sb +39 -1
  250. package/dist/src/utils/sandbox-macos-restrictive-proxied.sb +40 -1
  251. package/dist/src/utils/sandbox-macos-strict-open.sb +38 -2
  252. package/dist/src/utils/sandbox-macos-strict-proxied.sb +38 -2
  253. package/dist/src/utils/sandbox.js +120 -47
  254. package/dist/src/utils/sandbox.js.map +1 -1
  255. package/dist/src/utils/sandbox.test.js +312 -5
  256. package/dist/src/utils/sandbox.test.js.map +1 -1
  257. package/dist/src/utils/sandboxBuiltinProfiles.js +198 -8
  258. package/dist/src/utils/sandboxBuiltinProfiles.js.map +1 -1
  259. package/dist/src/utils/sandboxUtils.d.ts +11 -0
  260. package/dist/src/utils/sandboxUtils.js +150 -2
  261. package/dist/src/utils/sandboxUtils.js.map +1 -1
  262. package/dist/src/utils/sandboxUtils.test.js +257 -3
  263. package/dist/src/utils/sandboxUtils.test.js.map +1 -1
  264. package/dist/src/utils/sessionUtils.d.ts +21 -1
  265. package/dist/src/utils/sessionUtils.js +66 -2
  266. package/dist/src/utils/sessionUtils.js.map +1 -1
  267. package/dist/src/utils/sessionUtils.test.js +143 -0
  268. package/dist/src/utils/sessionUtils.test.js.map +1 -1
  269. package/dist/tsconfig.tsbuildinfo +1 -1
  270. package/package.json +3 -3
@@ -96,6 +96,65 @@ describe('macOS Seatbelt container runtime isolation', () => {
96
96
  });
97
97
  });
98
98
  });
99
+ describe('macOS Seatbelt Gemini configuration isolation', () => {
100
+ describe.each(ALL_PROFILES)('%s', (profile) => {
101
+ const rules = readRules(profile);
102
+ it('does not allow writes to HOME_DIR/.cell-cli', () => {
103
+ const allowWriteMatch = rules.match(/\(allow file-write\*[\s\S]*?\n\)/);
104
+ expect(allowWriteMatch).not.toBeNull();
105
+ expect(allowWriteMatch[0]).not.toContain('(subpath (string-append (param "HOME_DIR") "/.cell-cli"))');
106
+ });
107
+ it('denies writing to Gemini configuration directory and sensitive files', () => {
108
+ expect(rules).toContain('(deny file-write*');
109
+ expect(rules).toContain('(subpath (string-append (param "HOME_DIR") "/.cell-cli"))');
110
+ expect(rules).toContain('(regex #"/trustedFolders\\.json$")');
111
+ expect(rules).toContain('(regex #"/policy_integrity\\.json$")');
112
+ });
113
+ it('denies reading sensitive credential and environment files', () => {
114
+ expect(rules).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/oauth_creds.json"))');
115
+ expect(rules).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/gemini-credentials.json"))');
116
+ expect(rules).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/mcp-oauth-tokens.json"))');
117
+ expect(rules).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/a2a-oauth-tokens.json"))');
118
+ expect(rules).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/google_accounts.json"))');
119
+ expect(rules).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/trusted_hooks.json"))');
120
+ expect(rules).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/trustedFolders.json"))');
121
+ expect(rules).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/policy_integrity.json"))');
122
+ expect(rules).toContain('(regex #"/google_accounts\\.json$")');
123
+ expect(rules).toContain('(regex #"/trusted_hooks\\.json$")');
124
+ expect(rules).toContain('(regex #"/trustedFolders\\.json$")');
125
+ expect(rules).toContain('(regex #"/policy_integrity\\.json$")');
126
+ });
127
+ });
128
+ });
129
+ const RESTRICTIVE_AND_STRICT_PROFILES = [
130
+ 'sandbox-macos-restrictive-open.sb',
131
+ 'sandbox-macos-restrictive-proxied.sb',
132
+ 'sandbox-macos-strict-open.sb',
133
+ 'sandbox-macos-strict-proxied.sb',
134
+ ];
135
+ describe('macOS Seatbelt non-sensitive configuration read access', () => {
136
+ describe.each(RESTRICTIVE_AND_STRICT_PROFILES)('%s', (profile) => {
137
+ const rules = readRules(profile);
138
+ it('allows reading settings.json and keybindings.json configuration files', () => {
139
+ expect(rules).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/settings.json"))');
140
+ expect(rules).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/keybindings.json"))');
141
+ });
142
+ });
143
+ });
144
+ const STRICT_PROFILES = [
145
+ 'sandbox-macos-strict-open.sb',
146
+ 'sandbox-macos-strict-proxied.sb',
147
+ ];
148
+ describe('macOS Seatbelt strict profile scoped read access', () => {
149
+ describe.each(STRICT_PROFILES)('%s', (profile) => {
150
+ const rules = readRules(profile);
151
+ it('does not allow broad read access to ~/.cell-cli subpath', () => {
152
+ const allowReadMatch = rules.match(/\(allow file-read\*[\s\S]*?\n\)/);
153
+ expect(allowReadMatch).not.toBeNull();
154
+ expect(allowReadMatch[0]).not.toContain('(subpath (string-append (param "HOME_DIR") "/.cell-cli"))');
155
+ });
156
+ });
157
+ });
99
158
  describe('BUILTIN_SEATBELT_PROFILE_CONTENTS consistency', () => {
100
159
  const profileKeyMap = {
101
160
  'sandbox-macos-permissive-open.sb': 'permissive-open',
@@ -113,6 +172,40 @@ describe('BUILTIN_SEATBELT_PROFILE_CONTENTS consistency', () => {
113
172
  expect(embeddedContent).toContain('(literal "/usr/local/bin/docker")');
114
173
  expect(embeddedContent).toContain('(xpc-service-name-prefix "com.docker.")');
115
174
  });
175
+ it('contains Gemini config isolation and credential denial rules in embedded content', () => {
176
+ const embeddedContent = BUILTIN_SEATBELT_PROFILE_CONTENTS[key];
177
+ expect(embeddedContent).toBeDefined();
178
+ expect(embeddedContent).toContain('(deny file-write*');
179
+ expect(embeddedContent).toContain('(subpath (string-append (param "HOME_DIR") "/.cell-cli"))');
180
+ expect(embeddedContent).toContain('(regex #"/trustedFolders\\.json$")');
181
+ expect(embeddedContent).toContain('(regex #"/policy_integrity\\.json$")');
182
+ expect(embeddedContent).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/oauth_creds.json"))');
183
+ expect(embeddedContent).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/google_accounts.json"))');
184
+ expect(embeddedContent).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/trusted_hooks.json"))');
185
+ expect(embeddedContent).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/trustedFolders.json"))');
186
+ expect(embeddedContent).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/policy_integrity.json"))');
187
+ });
188
+ it('contains settings and keybindings read rules in embedded content for restrictive and strict profiles', () => {
189
+ if ([
190
+ 'restrictive-open',
191
+ 'restrictive-proxied',
192
+ 'strict-open',
193
+ 'strict-proxied',
194
+ ].includes(key)) {
195
+ const embeddedContent = BUILTIN_SEATBELT_PROFILE_CONTENTS[key];
196
+ expect(embeddedContent).toBeDefined();
197
+ expect(embeddedContent).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/settings.json"))');
198
+ expect(embeddedContent).toContain('(literal (string-append (param "HOME_DIR") "/.cell-cli/keybindings.json"))');
199
+ }
200
+ });
201
+ it('does not contain broad .cell-cli subpath read rule in embedded strict content', () => {
202
+ if (['strict-open', 'strict-proxied'].includes(key)) {
203
+ const embeddedContent = BUILTIN_SEATBELT_PROFILE_CONTENTS[key];
204
+ const allowReadMatch = embeddedContent.match(/\(allow file-read\*[\s\S]*?\n\)/);
205
+ expect(allowReadMatch).not.toBeNull();
206
+ expect(allowReadMatch[0]).not.toContain('(subpath (string-append (param "HOME_DIR") "/.cell-cli"))');
207
+ }
208
+ });
116
209
  });
117
210
  });
118
211
  //# sourceMappingURL=sandbox-macos-profiles.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox-macos-profiles.test.js","sourceRoot":"","sources":["../../../src/utils/sandbox-macos-profiles.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sandbox-macos-profiles.test.js","sourceRoot":"","sources":["../../../src/utils/sandbox-macos-profiles.test.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,10 @@
5
5
 
6
6
  ;; allow reading files from anywhere on host
7
7
  (allow file-read*)
8
+ (allow file-read*
9
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/settings.json"))
10
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/keybindings.json"))
11
+ )
8
12
 
9
13
  ;; allow exec/fork (children inherit policy)
10
14
  (allow process-exec)
@@ -67,7 +71,6 @@
67
71
  (subpath (param "TARGET_DIR"))
68
72
  (subpath (param "TMP_DIR"))
69
73
  (subpath (param "CACHE_DIR"))
70
- (subpath (string-append (param "HOME_DIR") "/.cell-cli"))
71
74
  (subpath (string-append (param "HOME_DIR") "/.npm"))
72
75
  (subpath (string-append (param "HOME_DIR") "/.cache"))
73
76
  ;; Allow writes to included directories from --include-directories
@@ -142,3 +145,38 @@
142
145
  (ipc-posix-name-prefix "docker")
143
146
  (ipc-posix-name-prefix "com.docker.")
144
147
  )
148
+
149
+ ;; Deny writing to user's Cell CLI configuration directory and sensitive files
150
+ (deny file-write*
151
+ (subpath (string-append (param "HOME_DIR") "/.cell-cli"))
152
+ (regex #"/oauth_creds\.json$")
153
+ (regex #"/gemini-credentials\.json$")
154
+ (regex #"/mcp-oauth-tokens\.json$")
155
+ (regex #"/a2a-oauth-tokens\.json$")
156
+ (regex #"/google_accounts\.json$")
157
+ (regex #"/trusted_hooks\.json$")
158
+ (regex #"/trustedFolders\.json$")
159
+ (regex #"/policy_integrity\.json$")
160
+ (regex #"/\.env($|\..*)")
161
+ )
162
+
163
+ ;; Block reading sensitive credentials and environment files
164
+ (deny file-read*
165
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/oauth_creds.json"))
166
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/gemini-credentials.json"))
167
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/mcp-oauth-tokens.json"))
168
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/a2a-oauth-tokens.json"))
169
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/google_accounts.json"))
170
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/trusted_hooks.json"))
171
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/trustedFolders.json"))
172
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/policy_integrity.json"))
173
+ (regex #"/oauth_creds\.json$")
174
+ (regex #"/gemini-credentials\.json$")
175
+ (regex #"/mcp-oauth-tokens\.json$")
176
+ (regex #"/a2a-oauth-tokens\.json$")
177
+ (regex #"/google_accounts\.json$")
178
+ (regex #"/trusted_hooks\.json$")
179
+ (regex #"/trustedFolders\.json$")
180
+ (regex #"/policy_integrity\.json$")
181
+ (regex #"/\.env($|\..*)")
182
+ )
@@ -5,6 +5,10 @@
5
5
 
6
6
  ;; allow reading files from anywhere on host
7
7
  (allow file-read*)
8
+ (allow file-read*
9
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/settings.json"))
10
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/keybindings.json"))
11
+ )
8
12
 
9
13
  ;; allow exec/fork (children inherit policy)
10
14
  (allow process-exec)
@@ -67,7 +71,6 @@
67
71
  (subpath (param "TARGET_DIR"))
68
72
  (subpath (param "TMP_DIR"))
69
73
  (subpath (param "CACHE_DIR"))
70
- (subpath (string-append (param "HOME_DIR") "/.cell-cli"))
71
74
  (subpath (string-append (param "HOME_DIR") "/.npm"))
72
75
  (subpath (string-append (param "HOME_DIR") "/.cache"))
73
76
  ;; Allow writes to included directories from --include-directories
@@ -145,3 +148,39 @@
145
148
  (ipc-posix-name-prefix "com.docker.")
146
149
  )
147
150
 
151
+ ;; Deny writing to user's Cell CLI configuration directory and sensitive files
152
+ (deny file-write*
153
+ (subpath (string-append (param "HOME_DIR") "/.cell-cli"))
154
+ (regex #"/oauth_creds\.json$")
155
+ (regex #"/gemini-credentials\.json$")
156
+ (regex #"/mcp-oauth-tokens\.json$")
157
+ (regex #"/a2a-oauth-tokens\.json$")
158
+ (regex #"/google_accounts\.json$")
159
+ (regex #"/trusted_hooks\.json$")
160
+ (regex #"/trustedFolders\.json$")
161
+ (regex #"/policy_integrity\.json$")
162
+ (regex #"/\.env($|\..*)")
163
+ )
164
+
165
+ ;; Block reading sensitive credentials and environment files
166
+ (deny file-read*
167
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/oauth_creds.json"))
168
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/gemini-credentials.json"))
169
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/mcp-oauth-tokens.json"))
170
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/a2a-oauth-tokens.json"))
171
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/google_accounts.json"))
172
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/trusted_hooks.json"))
173
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/trustedFolders.json"))
174
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/policy_integrity.json"))
175
+ (regex #"/oauth_creds\.json$")
176
+ (regex #"/gemini-credentials\.json$")
177
+ (regex #"/mcp-oauth-tokens\.json$")
178
+ (regex #"/a2a-oauth-tokens\.json$")
179
+ (regex #"/google_accounts\.json$")
180
+ (regex #"/trusted_hooks\.json$")
181
+ (regex #"/trustedFolders\.json$")
182
+ (regex #"/policy_integrity\.json$")
183
+ (regex #"/\.env($|\..*)")
184
+ )
185
+
186
+
@@ -10,7 +10,8 @@
10
10
  (subpath (param "TMP_DIR"))
11
11
  (subpath (param "CACHE_DIR"))
12
12
  ;; Only allow reading essential dotfiles/directories under HOME, not the entire HOME
13
- (subpath (string-append (param "HOME_DIR") "/.cell-cli"))
13
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/settings.json"))
14
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/keybindings.json"))
14
15
  (subpath (string-append (param "HOME_DIR") "/.npm"))
15
16
  (subpath (string-append (param "HOME_DIR") "/.cache"))
16
17
  (literal (string-append (param "HOME_DIR") "/.gitconfig"))
@@ -102,7 +103,6 @@
102
103
  (subpath (param "TARGET_DIR"))
103
104
  (subpath (param "TMP_DIR"))
104
105
  (subpath (param "CACHE_DIR"))
105
- (subpath (string-append (param "HOME_DIR") "/.cell-cli"))
106
106
  (subpath (string-append (param "HOME_DIR") "/.npm"))
107
107
  (subpath (string-append (param "HOME_DIR") "/.cache"))
108
108
  ;; Allow writes to included directories from --include-directories
@@ -178,3 +178,39 @@
178
178
  (ipc-posix-name-prefix "com.docker.")
179
179
  )
180
180
 
181
+ ;; Deny writing to user's Cell CLI configuration directory and sensitive files
182
+ (deny file-write*
183
+ (subpath (string-append (param "HOME_DIR") "/.cell-cli"))
184
+ (regex #"/oauth_creds\.json$")
185
+ (regex #"/gemini-credentials\.json$")
186
+ (regex #"/mcp-oauth-tokens\.json$")
187
+ (regex #"/a2a-oauth-tokens\.json$")
188
+ (regex #"/google_accounts\.json$")
189
+ (regex #"/trusted_hooks\.json$")
190
+ (regex #"/trustedFolders\.json$")
191
+ (regex #"/policy_integrity\.json$")
192
+ (regex #"/\.env($|\..*)")
193
+ )
194
+
195
+ ;; Block reading sensitive credentials and environment files
196
+ (deny file-read*
197
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/oauth_creds.json"))
198
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/gemini-credentials.json"))
199
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/mcp-oauth-tokens.json"))
200
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/a2a-oauth-tokens.json"))
201
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/google_accounts.json"))
202
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/trusted_hooks.json"))
203
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/trustedFolders.json"))
204
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/policy_integrity.json"))
205
+ (regex #"/oauth_creds\.json$")
206
+ (regex #"/gemini-credentials\.json$")
207
+ (regex #"/mcp-oauth-tokens\.json$")
208
+ (regex #"/a2a-oauth-tokens\.json$")
209
+ (regex #"/google_accounts\.json$")
210
+ (regex #"/trusted_hooks\.json$")
211
+ (regex #"/trustedFolders\.json$")
212
+ (regex #"/policy_integrity\.json$")
213
+ (regex #"/\.env($|\..*)")
214
+ )
215
+
216
+
@@ -10,7 +10,8 @@
10
10
  (subpath (param "TMP_DIR"))
11
11
  (subpath (param "CACHE_DIR"))
12
12
  ;; Only allow reading essential dotfiles/directories under HOME, not the entire HOME
13
- (subpath (string-append (param "HOME_DIR") "/.cell-cli"))
13
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/settings.json"))
14
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/keybindings.json"))
14
15
  (subpath (string-append (param "HOME_DIR") "/.npm"))
15
16
  (subpath (string-append (param "HOME_DIR") "/.cache"))
16
17
  (literal (string-append (param "HOME_DIR") "/.gitconfig"))
@@ -102,7 +103,6 @@
102
103
  (subpath (param "TARGET_DIR"))
103
104
  (subpath (param "TMP_DIR"))
104
105
  (subpath (param "CACHE_DIR"))
105
- (subpath (string-append (param "HOME_DIR") "/.cell-cli"))
106
106
  (subpath (string-append (param "HOME_DIR") "/.npm"))
107
107
  (subpath (string-append (param "HOME_DIR") "/.cache"))
108
108
  ;; Allow writes to included directories from --include-directories
@@ -180,3 +180,39 @@
180
180
  (ipc-posix-name-prefix "com.docker.")
181
181
  )
182
182
 
183
+ ;; Deny writing to user's Cell CLI configuration directory and sensitive files
184
+ (deny file-write*
185
+ (subpath (string-append (param "HOME_DIR") "/.cell-cli"))
186
+ (regex #"/oauth_creds\.json$")
187
+ (regex #"/gemini-credentials\.json$")
188
+ (regex #"/mcp-oauth-tokens\.json$")
189
+ (regex #"/a2a-oauth-tokens\.json$")
190
+ (regex #"/google_accounts\.json$")
191
+ (regex #"/trusted_hooks\.json$")
192
+ (regex #"/trustedFolders\.json$")
193
+ (regex #"/policy_integrity\.json$")
194
+ (regex #"/\.env($|\..*)")
195
+ )
196
+
197
+ ;; Block reading sensitive credentials and environment files
198
+ (deny file-read*
199
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/oauth_creds.json"))
200
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/gemini-credentials.json"))
201
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/mcp-oauth-tokens.json"))
202
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/a2a-oauth-tokens.json"))
203
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/google_accounts.json"))
204
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/trusted_hooks.json"))
205
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/trustedFolders.json"))
206
+ (literal (string-append (param "HOME_DIR") "/.cell-cli/policy_integrity.json"))
207
+ (regex #"/oauth_creds\.json$")
208
+ (regex #"/gemini-credentials\.json$")
209
+ (regex #"/mcp-oauth-tokens\.json$")
210
+ (regex #"/a2a-oauth-tokens\.json$")
211
+ (regex #"/google_accounts\.json$")
212
+ (regex #"/trusted_hooks\.json$")
213
+ (regex #"/trustedFolders\.json$")
214
+ (regex #"/policy_integrity\.json$")
215
+ (regex #"/\.env($|\..*)")
216
+ )
217
+
218
+
@@ -10,11 +10,15 @@ import os from 'node:os';
10
10
  import { fileURLToPath } from 'node:url';
11
11
  import { quote, parse } from 'shell-quote';
12
12
  import { promisify } from 'node:util';
13
- import { coreEvents, debugLogger, FatalSandboxError, CELL_DIR, homedir, } from '@google/gemini-cli-core';
13
+ import { coreEvents, debugLogger, FatalSandboxError, CELL_DIR, homedir, resolveToRealPath, } from '@google/gemini-cli-core';
14
14
  import { ConsolePatcher } from '../ui/utils/ConsolePatcher.js';
15
15
  import { randomBytes } from 'node:crypto';
16
- import { getContainerPath, shouldUseCurrentUserInSandbox, parseImageName, ports, entrypoint, LOCAL_DEV_SANDBOX_IMAGE_NAME, SANDBOX_NETWORK_NAME, SANDBOX_PROXY_NAME, BUILTIN_SEATBELT_PROFILES, prepareIsolatedSettingsDir, } from './sandboxUtils.js';
16
+ import stripJsonComments from 'strip-json-comments';
17
+ import { getContainerPath, shouldUseCurrentUserInSandbox, parseImageName, ports, entrypoint, LOCAL_DEV_SANDBOX_IMAGE_NAME, SANDBOX_NETWORK_NAME, SANDBOX_PROXY_NAME, BUILTIN_SEATBELT_PROFILES, isSensitiveHostPath, sanitizeSettingsForSandbox, } from './sandboxUtils.js';
17
18
  import { BUILTIN_SEATBELT_PROFILE_CONTENTS } from './sandboxBuiltinProfiles.js';
19
+ function isRecord(value) {
20
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
21
+ }
18
22
  const execAsync = promisify(exec);
19
23
  const execFileAsync = promisify(execFile);
20
24
  export async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs = []) {
@@ -26,20 +30,7 @@ export async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs =
26
30
  let stopProxy = undefined;
27
31
  let tempProfileFile = null;
28
32
  let sandboxTmpDir = null;
29
- let isolatedSettingsDir = null;
30
33
  const cleanup = () => {
31
- if (isolatedSettingsDir) {
32
- const dirToDelete = isolatedSettingsDir;
33
- isolatedSettingsDir = null;
34
- try {
35
- if (fs.existsSync(dirToDelete)) {
36
- fs.rmSync(dirToDelete, { recursive: true, force: true });
37
- }
38
- }
39
- catch {
40
- // ignore
41
- }
42
- }
43
34
  if (sandboxTmpDir) {
44
35
  const dirToDelete = sandboxTmpDir;
45
36
  sandboxTmpDir = null;
@@ -100,11 +91,15 @@ export async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs =
100
91
  if (!BUILTIN_SEATBELT_PROFILES.includes(profile)) {
101
92
  const safeProfile = path.basename(profile);
102
93
  const fileName = `sandbox-macos-${safeProfile}.sb`;
103
- const userProfileFile = path.join(homedir(), CELL_DIR, fileName);
94
+ const userHome = homedir();
95
+ const userProfileFile = userHome
96
+ ? path.join(userHome, CELL_DIR, fileName)
97
+ : '';
104
98
  const projectProfileFile = path.join(CELL_DIR, fileName);
105
- profileFile = fs.existsSync(userProfileFile)
106
- ? userProfileFile
107
- : projectProfileFile;
99
+ profileFile =
100
+ userProfileFile && fs.existsSync(userProfileFile)
101
+ ? userProfileFile
102
+ : projectProfileFile;
108
103
  }
109
104
  else {
110
105
  // For builtin profiles, if the file doesn't exist on disk (e.g. bundled or bazel environments),
@@ -138,12 +133,32 @@ export async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs =
138
133
  ...(process.env['DEBUG'] ? ['--inspect-brk'] : []),
139
134
  ...nodeArgs,
140
135
  ].join(' ');
136
+ const targetDir = fs.realpathSync(process.cwd());
137
+ if (isSensitiveHostPath(targetDir)) {
138
+ throw new FatalSandboxError(`Running sandbox from a sensitive host directory '${targetDir}' is strictly prohibited`);
139
+ }
141
140
  const hostTmpDir = fs.realpathSync(os.tmpdir());
142
141
  const resolvedTmpDir = fs.mkdtempSync(path.join(hostTmpDir, 'cell-sandbox-'));
142
+ try {
143
+ fs.chmodSync(resolvedTmpDir, 0o700);
144
+ }
145
+ catch {
146
+ // Silently ignore permission errors on non-POSIX filesystems
147
+ }
143
148
  sandboxTmpDir = resolvedTmpDir;
149
+ const userHome = homedir();
150
+ if (userHome) {
151
+ const seatbeltCacheDir = path.join(userHome, '.cache', CELL_DIR);
152
+ try {
153
+ fs.mkdirSync(seatbeltCacheDir, { recursive: true });
154
+ }
155
+ catch {
156
+ // Silently ignore directory creation failures
157
+ }
158
+ }
144
159
  const args = [
145
160
  '-D',
146
- `TARGET_DIR=${fs.realpathSync(process.cwd())}`,
161
+ `TARGET_DIR=${targetDir}`,
147
162
  '-D',
148
163
  `TMP_DIR=${resolvedTmpDir}`,
149
164
  '-D',
@@ -154,15 +169,27 @@ export async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs =
154
169
  // Add included directories from the workspace context
155
170
  // Always add 5 INCLUDE_DIR parameters to ensure .sb files can reference them
156
171
  const MAX_INCLUDE_DIRS = 5;
157
- const targetDir = fs.realpathSync(cliConfig?.getTargetDir() || '');
172
+ const configTargetDir = cliConfig?.getTargetDir()
173
+ ? resolveToRealPath(cliConfig.getTargetDir())
174
+ : targetDir;
175
+ if (cliConfig?.getTargetDir() && isSensitiveHostPath(configTargetDir)) {
176
+ throw new FatalSandboxError(`Running sandbox from a sensitive host directory '${configTargetDir}' is strictly prohibited`);
177
+ }
158
178
  const includedDirs = [];
159
179
  if (cliConfig) {
160
180
  const workspaceContext = cliConfig.getWorkspaceContext();
161
181
  const directories = workspaceContext.getDirectories();
162
182
  // Filter out TARGET_DIR
163
183
  for (const dir of directories) {
164
- const realDir = fs.realpathSync(dir);
165
- if (realDir !== targetDir) {
184
+ const realDir = resolveToRealPath(dir);
185
+ if (!realDir) {
186
+ continue;
187
+ }
188
+ if (realDir !== targetDir && realDir !== configTargetDir) {
189
+ if (isSensitiveHostPath(realDir)) {
190
+ debugLogger.warn(`Skipping sensitive workspace directory '${realDir}' in sandbox`);
191
+ continue;
192
+ }
166
193
  includedDirs.push(realDir);
167
194
  }
168
195
  }
@@ -174,7 +201,13 @@ export async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs =
174
201
  path.isAbsolute(hostPath) &&
175
202
  fs.existsSync(hostPath)) {
176
203
  const realDir = fs.realpathSync(hostPath);
177
- if (!includedDirs.includes(realDir) && realDir !== targetDir) {
204
+ if (!includedDirs.includes(realDir) &&
205
+ realDir !== targetDir &&
206
+ realDir !== configTargetDir) {
207
+ if (isSensitiveHostPath(realDir)) {
208
+ debugLogger.warn(`Skipping sensitive path '${realDir}' in config.allowedPaths`);
209
+ continue;
210
+ }
178
211
  includedDirs.push(realDir);
179
212
  }
180
213
  }
@@ -350,32 +383,58 @@ export async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs =
350
383
  // allow access to host.docker.internal
351
384
  args.push('--add-host', 'host.docker.internal:host-gateway');
352
385
  // mount current directory as working directory in sandbox (set via --workdir)
353
- args.push('--volume', `${workdir}:${containerWorkdir}`);
354
- // mount user settings directory inside container, after creating if missing
355
- // note user/home changes inside sandbox and we mount at BOTH paths for consistency
356
- const userHomeDirOnHost = homedir();
357
- const userSettingsDirInSandbox = getContainerPath(`/home/node/${CELL_DIR}`);
358
- if (!fs.existsSync(userHomeDirOnHost)) {
359
- fs.mkdirSync(userHomeDirOnHost, { recursive: true });
386
+ if (isSensitiveHostPath(workdir)) {
387
+ throw new FatalSandboxError(`Running sandbox from a sensitive host directory '${workdir}' is strictly prohibited`);
360
388
  }
361
- const userSettingsDirOnHost = path.join(userHomeDirOnHost, CELL_DIR);
362
- if (!fs.existsSync(userSettingsDirOnHost)) {
363
- fs.mkdirSync(userSettingsDirOnHost, { recursive: true });
389
+ if (cliConfig?.getTargetDir() &&
390
+ isSensitiveHostPath(cliConfig.getTargetDir())) {
391
+ throw new FatalSandboxError(`Running sandbox from a sensitive host directory '${cliConfig.getTargetDir()}' is strictly prohibited`);
364
392
  }
365
- isolatedSettingsDir = prepareIsolatedSettingsDir(userSettingsDirOnHost);
366
- args.push('--volume', `${isolatedSettingsDir}:${userSettingsDirInSandbox}`);
367
- if (userSettingsDirInSandbox !== getContainerPath(userSettingsDirOnHost)) {
368
- args.push('--volume', `${isolatedSettingsDir}:${getContainerPath(userSettingsDirOnHost)}`);
393
+ args.push('--volume', `${workdir}:${containerWorkdir}`);
394
+ // Create ephemeral sandbox temp directory on host for sanitized configuration files
395
+ if (!sandboxTmpDir) {
396
+ const hostTmpDir = fs.realpathSync(os.tmpdir());
397
+ sandboxTmpDir = fs.mkdtempSync(path.join(hostTmpDir, 'cell-sandbox-'));
398
+ try {
399
+ fs.chmodSync(sandboxTmpDir, 0o700);
400
+ }
401
+ catch {
402
+ // Silently ignore permission errors on non-POSIX filesystems
403
+ }
369
404
  }
370
- // mount os.tmpdir() as os.tmpdir() inside container
371
- args.push('--volume', `${os.tmpdir()}:${getContainerPath(os.tmpdir())}`);
372
- // mount homedir() as homedir() inside container
373
- if (userHomeDirOnHost !== os.homedir()) {
374
- args.push('--volume', `${userHomeDirOnHost}:${getContainerPath(userHomeDirOnHost)}`);
405
+ // Sanitize user settings before mounting into the sandbox container.
406
+ // We STRICTLY do NOT mount ~/.cell-cli root directory or sensitive credential files
407
+ // (oauth_creds.json, .env, etc.). We only mount the sanitized settings file as read-only (:ro).
408
+ const userHomeDirOnHost = homedir();
409
+ let rawSettings = {};
410
+ if (userHomeDirOnHost) {
411
+ const userSettingsFileOnHost = path.join(userHomeDirOnHost, CELL_DIR, 'settings.json');
412
+ if (fs.existsSync(userSettingsFileOnHost)) {
413
+ try {
414
+ const rawContent = fs.readFileSync(userSettingsFileOnHost, 'utf8');
415
+ const parsed = JSON.parse(stripJsonComments(rawContent));
416
+ if (isRecord(parsed)) {
417
+ rawSettings = parsed;
418
+ }
419
+ }
420
+ catch (err) {
421
+ debugLogger.warn(`Failed to parse host user settings for sandbox: ${err}`);
422
+ }
423
+ }
375
424
  }
425
+ const sanitizedSettings = sanitizeSettingsForSandbox(rawSettings);
426
+ const sanitizedSettingsFile = path.join(sandboxTmpDir, 'settings.json');
427
+ fs.writeFileSync(sanitizedSettingsFile, JSON.stringify(sanitizedSettings, null, 2), { mode: 0o600 });
428
+ // Mount isolated sanitized settings directory inside container
429
+ const userSettingsDirInSandbox = getContainerPath(`/home/node/${CELL_DIR}`);
430
+ // Force HOME to /home/node inside the container so that the isolated settings are correctly resolved
431
+ args.push('--env', 'HOME=/home/node');
432
+ args.push('--volume', `${sandboxTmpDir}:${userSettingsDirInSandbox}:rw`);
376
433
  // mount gcloud config directory if it exists
377
- const gcloudConfigDir = path.join(homedir(), '.config', 'gcloud');
378
- if (fs.existsSync(gcloudConfigDir)) {
434
+ const gcloudConfigDir = userHomeDirOnHost
435
+ ? path.join(userHomeDirOnHost, '.config', 'gcloud')
436
+ : '';
437
+ if (gcloudConfigDir && fs.existsSync(gcloudConfigDir)) {
379
438
  args.push('--volume', `${gcloudConfigDir}:${getContainerPath(gcloudConfigDir)}:ro`);
380
439
  }
381
440
  // mount ADC file if GOOGLE_APPLICATION_CREDENTIALS is set
@@ -399,6 +458,9 @@ export async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs =
399
458
  if (!path.isAbsolute(from)) {
400
459
  throw new FatalSandboxError(`Path '${from}' listed in SANDBOX_MOUNTS must be absolute`);
401
460
  }
461
+ if (isSensitiveHostPath(from)) {
462
+ throw new FatalSandboxError(`Mounting sensitive host path '${from}' listed in SANDBOX_MOUNTS is strictly prohibited`);
463
+ }
402
464
  // check that from path exists on host
403
465
  if (!fs.existsSync(from)) {
404
466
  throw new FatalSandboxError(`Missing mount path '${from}' listed in SANDBOX_MOUNTS`);
@@ -412,6 +474,10 @@ export async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs =
412
474
  if (config.allowedPaths) {
413
475
  for (const hostPath of config.allowedPaths) {
414
476
  if (hostPath && path.isAbsolute(hostPath) && fs.existsSync(hostPath)) {
477
+ if (isSensitiveHostPath(hostPath)) {
478
+ debugLogger.warn(`Skipping sensitive path '${hostPath}' in config.allowedPaths`);
479
+ continue;
480
+ }
415
481
  const containerPath = getContainerPath(hostPath);
416
482
  debugLogger.log(`Config allowedPath: ${hostPath} -> ${containerPath} (ro)`);
417
483
  args.push('--volume', `${hostPath}:${containerPath}:ro`);
@@ -619,8 +685,8 @@ export async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs =
619
685
  finalEntrypoint[2] = defensiveEntrypoint;
620
686
  // We still need userFlag for the simpler proxy container, which does not have this issue.
621
687
  userFlag = `--user ${uid}:${gid}`;
622
- // When forcing a UID in the sandbox, $HOME can be reset to '/', so we copy $HOME as well.
623
- args.push('--env', `HOME=${homedir()}`);
688
+ // When forcing a UID in the sandbox, $HOME can be reset to '/', so ensure $HOME is set to /home/node.
689
+ args.push('--env', 'HOME=/home/node');
624
690
  }
625
691
  // push container image name
626
692
  args.push(image);
@@ -725,6 +791,9 @@ export async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs =
725
791
  async function start_lxc_sandbox(config, nodeArgs = [], cliArgs = []) {
726
792
  const containerName = config.image || 'cell-sandbox';
727
793
  const workdir = path.resolve(process.cwd());
794
+ if (isSensitiveHostPath(workdir)) {
795
+ throw new FatalSandboxError(`Running sandbox from a sensitive host directory '${workdir}' is strictly prohibited`);
796
+ }
728
797
  debugLogger.log(`starting lxc sandbox (container: ${containerName}, workdir: ${workdir}) ...`);
729
798
  // Verify the container exists and is running.
730
799
  let listOutput;
@@ -804,6 +873,10 @@ async function start_lxc_sandbox(config, nodeArgs = [], cliArgs = []) {
804
873
  if (config.allowedPaths) {
805
874
  for (const hostPath of config.allowedPaths) {
806
875
  if (hostPath && path.isAbsolute(hostPath) && fs.existsSync(hostPath)) {
876
+ if (isSensitiveHostPath(hostPath)) {
877
+ debugLogger.warn(`Skipping sensitive path '${hostPath}' in config.allowedPaths for LXC`);
878
+ continue;
879
+ }
807
880
  const allowedDeviceName = `gemini-allowed-${randomBytes(4).toString('hex')}`;
808
881
  devicesToRemove.push(allowedDeviceName);
809
882
  try {