@google/gemini-cli-core 0.35.0-preview.2 → 0.36.0-nightly.20260321.fc03891a1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/dist/docs/CONTRIBUTING.md +0 -15
- package/dist/docs/admin/enterprise-controls.md +61 -0
- package/dist/docs/changelogs/index.md +11 -0
- package/dist/docs/changelogs/latest.md +459 -209
- package/dist/docs/changelogs/preview.md +355 -454
- package/dist/docs/cli/checkpointing.md +3 -1
- package/dist/docs/cli/cli-reference.md +1 -0
- package/dist/docs/cli/custom-commands.md +7 -5
- package/dist/docs/cli/enterprise.md +15 -9
- package/dist/docs/cli/git-worktrees.md +107 -0
- package/dist/docs/cli/model-steering.md +4 -3
- package/dist/docs/cli/model.md +3 -1
- package/dist/docs/cli/notifications.md +4 -3
- package/dist/docs/cli/plan-mode.md +28 -8
- package/dist/docs/cli/sandbox.md +24 -4
- package/dist/docs/cli/session-management.md +6 -0
- package/dist/docs/cli/settings.md +14 -1
- package/dist/docs/cli/skills.md +4 -2
- package/dist/docs/cli/system-prompt.md +3 -1
- package/dist/docs/cli/telemetry.md +6 -3
- package/dist/docs/cli/themes.md +12 -8
- package/dist/docs/cli/tutorials/file-management.md +8 -6
- package/dist/docs/cli/tutorials/mcp-setup.md +5 -3
- package/dist/docs/cli/tutorials/memory-management.md +6 -6
- package/dist/docs/cli/tutorials/plan-mode-steering.md +4 -3
- package/dist/docs/cli/tutorials/shell-commands.md +3 -3
- package/dist/docs/core/remote-agents.md +8 -3
- package/dist/docs/core/subagents.md +21 -13
- package/dist/docs/extensions/reference.md +8 -3
- package/dist/docs/get-started/authentication.md +60 -50
- package/dist/docs/get-started/examples.md +3 -1
- package/dist/docs/get-started/gemini-3.md +11 -5
- package/dist/docs/hooks/index.md +3 -1
- package/dist/docs/hooks/writing-hooks.md +2 -2
- package/dist/docs/ide-integration/ide-companion-spec.md +5 -3
- package/dist/docs/ide-integration/index.md +8 -4
- package/dist/docs/issue-and-pr-automation.md +3 -1
- package/dist/docs/local-development.md +3 -1
- package/dist/docs/reference/commands.md +2 -2
- package/dist/docs/reference/configuration.md +410 -16
- package/dist/docs/reference/policy-engine.md +47 -19
- package/dist/docs/reference/tools.md +3 -1
- package/dist/docs/release-confidence.md +7 -3
- package/dist/docs/releases.md +11 -7
- package/dist/docs/resources/faq.md +13 -0
- package/dist/docs/resources/tos-privacy.md +4 -2
- package/dist/docs/resources/troubleshooting.md +3 -1
- package/dist/docs/sidebar.json +5 -0
- package/dist/docs/tools/mcp-server.md +17 -9
- package/dist/docs/tools/planning.md +3 -1
- package/dist/docs/tools/shell.md +4 -4
- package/dist/docs/tools/todos.md +2 -1
- package/dist/{google-gemini-cli-core-0.35.0-preview.1.tgz → google-gemini-cli-core-0.36.0-nightly.20260317.2f90b4653.tgz} +0 -0
- package/dist/src/agent/agent-session.d.ts +37 -0
- package/dist/src/agent/agent-session.js +168 -0
- package/dist/src/agent/agent-session.js.map +1 -0
- package/dist/src/agent/agent-session.test.d.ts +6 -0
- package/dist/src/agent/agent-session.test.js +217 -0
- package/dist/src/agent/agent-session.test.js.map +1 -0
- package/dist/src/agent/content-utils.d.ts +33 -0
- package/dist/src/agent/content-utils.js +135 -0
- package/dist/src/agent/content-utils.js.map +1 -0
- package/dist/src/agent/content-utils.test.d.ts +6 -0
- package/dist/src/agent/content-utils.test.js +223 -0
- package/dist/src/agent/content-utils.test.js.map +1 -0
- package/dist/src/agent/mock.d.ts +9 -12
- package/dist/src/agent/mock.js +88 -129
- package/dist/src/agent/mock.js.map +1 -1
- package/dist/src/agent/mock.test.js +114 -144
- package/dist/src/agent/mock.test.js.map +1 -1
- package/dist/src/agent/types.d.ts +21 -21
- package/dist/src/agents/a2a-client-manager.d.ts +2 -11
- package/dist/src/agents/a2a-client-manager.js +3 -19
- package/dist/src/agents/a2a-client-manager.js.map +1 -1
- package/dist/src/agents/a2a-client-manager.test.js +6 -10
- package/dist/src/agents/a2a-client-manager.test.js.map +1 -1
- package/dist/src/agents/agent-scheduler.d.ts +6 -0
- package/dist/src/agents/agent-scheduler.js +3 -2
- package/dist/src/agents/agent-scheduler.js.map +1 -1
- package/dist/src/agents/agent-scheduler.test.js +6 -0
- package/dist/src/agents/agent-scheduler.test.js.map +1 -1
- package/dist/src/agents/browser/browserAgentDefinition.js +10 -1
- package/dist/src/agents/browser/browserAgentDefinition.js.map +1 -1
- package/dist/src/agents/browser/browserAgentFactory.js +62 -1
- package/dist/src/agents/browser/browserAgentFactory.js.map +1 -1
- package/dist/src/agents/browser/browserAgentFactory.test.js +73 -0
- package/dist/src/agents/browser/browserAgentFactory.test.js.map +1 -1
- package/dist/src/agents/browser/browserAgentInvocation.js +2 -97
- package/dist/src/agents/browser/browserAgentInvocation.js.map +1 -1
- package/dist/src/agents/browser/browserAgentInvocation.test.js +30 -0
- package/dist/src/agents/browser/browserAgentInvocation.test.js.map +1 -1
- package/dist/src/agents/browser/browserManager.js +11 -0
- package/dist/src/agents/browser/browserManager.js.map +1 -1
- package/dist/src/agents/browser/browserManager.test.js +37 -0
- package/dist/src/agents/browser/browserManager.test.js.map +1 -1
- package/dist/src/agents/browser/mcpToolWrapper.d.ts +4 -2
- package/dist/src/agents/browser/mcpToolWrapper.js +30 -8
- package/dist/src/agents/browser/mcpToolWrapper.js.map +1 -1
- package/dist/src/agents/browser/mcpToolWrapper.test.js +30 -0
- package/dist/src/agents/browser/mcpToolWrapper.test.js.map +1 -1
- package/dist/src/agents/browser/mcpToolWrapperConfirmation.test.js +3 -3
- package/dist/src/agents/codebase-investigator.js +3 -3
- package/dist/src/agents/codebase-investigator.js.map +1 -1
- package/dist/src/agents/local-executor.d.ts +3 -1
- package/dist/src/agents/local-executor.js +138 -39
- package/dist/src/agents/local-executor.js.map +1 -1
- package/dist/src/agents/local-executor.test.js +305 -12
- package/dist/src/agents/local-executor.test.js.map +1 -1
- package/dist/src/agents/local-invocation.js +43 -24
- package/dist/src/agents/local-invocation.js.map +1 -1
- package/dist/src/agents/local-invocation.test.js +89 -14
- package/dist/src/agents/local-invocation.test.js.map +1 -1
- package/dist/src/agents/memory-manager-agent.d.ts +25 -0
- package/dist/src/agents/memory-manager-agent.js +137 -0
- package/dist/src/agents/memory-manager-agent.js.map +1 -0
- package/dist/src/agents/memory-manager-agent.test.d.ts +6 -0
- package/dist/src/agents/memory-manager-agent.test.js +117 -0
- package/dist/src/agents/memory-manager-agent.test.js.map +1 -0
- package/dist/src/agents/registry.js +21 -3
- package/dist/src/agents/registry.js.map +1 -1
- package/dist/src/agents/registry.test.js +23 -24
- package/dist/src/agents/registry.test.js.map +1 -1
- package/dist/src/agents/remote-invocation.d.ts +3 -1
- package/dist/src/agents/remote-invocation.js +10 -5
- package/dist/src/agents/remote-invocation.js.map +1 -1
- package/dist/src/agents/remote-invocation.test.js +64 -41
- package/dist/src/agents/remote-invocation.test.js.map +1 -1
- package/dist/src/agents/subagent-tool-wrapper.js +1 -1
- package/dist/src/agents/subagent-tool-wrapper.js.map +1 -1
- package/dist/src/agents/types.d.ts +12 -0
- package/dist/src/agents/types.js +14 -0
- package/dist/src/agents/types.js.map +1 -1
- package/dist/src/availability/policyHelpers.js +41 -1
- package/dist/src/availability/policyHelpers.js.map +1 -1
- package/dist/src/availability/policyHelpers.test.js +47 -0
- package/dist/src/availability/policyHelpers.test.js.map +1 -1
- package/dist/src/code_assist/admin/admin_controls.js +11 -0
- package/dist/src/code_assist/admin/admin_controls.js.map +1 -1
- package/dist/src/code_assist/admin/admin_controls.test.js +68 -0
- package/dist/src/code_assist/admin/admin_controls.test.js.map +1 -1
- package/dist/src/code_assist/admin/mcpUtils.d.ts +16 -1
- package/dist/src/code_assist/admin/mcpUtils.js +43 -0
- package/dist/src/code_assist/admin/mcpUtils.js.map +1 -1
- package/dist/src/code_assist/admin/mcpUtils.test.js +130 -1
- package/dist/src/code_assist/admin/mcpUtils.test.js.map +1 -1
- package/dist/src/code_assist/types.d.ts +458 -0
- package/dist/src/code_assist/types.js +26 -0
- package/dist/src/code_assist/types.js.map +1 -1
- package/dist/src/config/agent-loop-context.d.ts +6 -0
- package/dist/src/config/config.d.ts +41 -10
- package/dist/src/config/config.js +96 -19
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +29 -1
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/defaultModelConfigs.js +265 -9
- package/dist/src/config/defaultModelConfigs.js.map +1 -1
- package/dist/src/config/models.d.ts +13 -2
- package/dist/src/config/models.js +31 -3
- package/dist/src/config/models.js.map +1 -1
- package/dist/src/config/models.test.js +52 -7
- package/dist/src/config/models.test.js.map +1 -1
- package/dist/src/config/path-validation.test.d.ts +6 -0
- package/dist/src/config/path-validation.test.js +59 -0
- package/dist/src/config/path-validation.test.js.map +1 -0
- package/dist/src/core/client.d.ts +1 -0
- package/dist/src/core/client.js +6 -1
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +9 -1
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/contentGenerator.js +36 -6
- package/dist/src/core/contentGenerator.js.map +1 -1
- package/dist/src/core/contentGenerator.test.js +97 -3
- package/dist/src/core/contentGenerator.test.js.map +1 -1
- package/dist/src/core/geminiChat.js +2 -2
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/core/prompts.test.js +10 -0
- package/dist/src/core/prompts.test.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/generated/git-commit.js.map +1 -1
- package/dist/src/ide/ide-connection-utils.js +2 -7
- package/dist/src/ide/ide-connection-utils.js.map +1 -1
- package/dist/src/ide/ide-connection-utils.test.js +7 -0
- package/dist/src/ide/ide-connection-utils.test.js.map +1 -1
- package/dist/src/index.d.ts +4 -0
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/policy/config.js +2 -0
- package/dist/src/policy/config.js.map +1 -1
- package/dist/src/policy/config.test.js +15 -0
- package/dist/src/policy/config.test.js.map +1 -1
- package/dist/src/policy/memory-manager-policy.test.d.ts +6 -0
- package/dist/src/policy/memory-manager-policy.test.js +80 -0
- package/dist/src/policy/memory-manager-policy.test.js.map +1 -0
- package/dist/src/policy/policies/memory-manager.toml +10 -0
- package/dist/src/policy/policies/plan.toml +14 -0
- package/dist/src/policy/policies/yolo.toml +1 -0
- package/dist/src/policy/policy-engine.js +33 -6
- package/dist/src/policy/policy-engine.js.map +1 -1
- package/dist/src/policy/policy-engine.test.js +85 -3
- package/dist/src/policy/policy-engine.test.js.map +1 -1
- package/dist/src/policy/policy-updater.test.js +44 -0
- package/dist/src/policy/policy-updater.test.js.map +1 -1
- package/dist/src/policy/toml-loader.js +2 -0
- package/dist/src/policy/toml-loader.js.map +1 -1
- package/dist/src/policy/types.d.ts +11 -0
- package/dist/src/policy/types.js +5 -0
- package/dist/src/policy/types.js.map +1 -1
- package/dist/src/prompts/promptProvider.js +5 -3
- package/dist/src/prompts/promptProvider.js.map +1 -1
- package/dist/src/prompts/promptProvider.test.js +1 -0
- package/dist/src/prompts/promptProvider.test.js.map +1 -1
- package/dist/src/prompts/snippets-memory-manager.test.d.ts +6 -0
- package/dist/src/prompts/snippets-memory-manager.test.js +31 -0
- package/dist/src/prompts/snippets-memory-manager.test.js.map +1 -0
- package/dist/src/prompts/snippets.d.ts +2 -0
- package/dist/src/prompts/snippets.js +7 -3
- package/dist/src/prompts/snippets.js.map +1 -1
- package/dist/src/prompts/snippets.legacy.d.ts +5 -0
- package/dist/src/prompts/snippets.legacy.js +30 -2
- package/dist/src/prompts/snippets.legacy.js.map +1 -1
- package/dist/src/routing/strategies/classifierStrategy.js +1 -1
- package/dist/src/routing/strategies/classifierStrategy.js.map +1 -1
- package/dist/src/routing/strategies/defaultStrategy.js +1 -1
- package/dist/src/routing/strategies/defaultStrategy.js.map +1 -1
- package/dist/src/routing/strategies/fallbackStrategy.js +1 -1
- package/dist/src/routing/strategies/fallbackStrategy.js.map +1 -1
- package/dist/src/routing/strategies/numericalClassifierStrategy.js +1 -1
- package/dist/src/routing/strategies/numericalClassifierStrategy.js.map +1 -1
- package/dist/src/routing/strategies/overrideStrategy.js +1 -1
- package/dist/src/routing/strategies/overrideStrategy.js.map +1 -1
- package/dist/src/sandbox/macos/MacOsSandboxManager.d.ts +28 -0
- package/dist/src/sandbox/macos/MacOsSandboxManager.integration.test.d.ts +1 -0
- package/dist/src/sandbox/macos/MacOsSandboxManager.integration.test.js +160 -0
- package/dist/src/sandbox/macos/MacOsSandboxManager.integration.test.js.map +1 -0
- package/dist/src/sandbox/macos/MacOsSandboxManager.js +33 -0
- package/dist/src/sandbox/macos/MacOsSandboxManager.js.map +1 -0
- package/dist/src/sandbox/macos/MacOsSandboxManager.test.d.ts +1 -0
- package/dist/src/sandbox/macos/MacOsSandboxManager.test.js +87 -0
- package/dist/src/sandbox/macos/MacOsSandboxManager.test.js.map +1 -0
- package/dist/src/sandbox/macos/baseProfile.d.ts +20 -0
- package/dist/src/sandbox/macos/baseProfile.js +93 -0
- package/dist/src/sandbox/macos/baseProfile.js.map +1 -0
- package/dist/src/sandbox/macos/seatbeltArgsBuilder.d.ts +25 -0
- package/dist/src/sandbox/macos/seatbeltArgsBuilder.js +58 -0
- package/dist/src/sandbox/macos/seatbeltArgsBuilder.js.map +1 -0
- package/dist/src/sandbox/macos/seatbeltArgsBuilder.test.d.ts +1 -0
- package/dist/src/sandbox/macos/seatbeltArgsBuilder.test.js +80 -0
- package/dist/src/sandbox/macos/seatbeltArgsBuilder.test.js.map +1 -0
- package/dist/src/scheduler/scheduler.js +2 -0
- package/dist/src/scheduler/scheduler.js.map +1 -1
- package/dist/src/services/contextManager.js +2 -3
- package/dist/src/services/contextManager.js.map +1 -1
- package/dist/src/services/contextManager.test.js +1 -1
- package/dist/src/services/contextManager.test.js.map +1 -1
- package/dist/src/services/modelConfigService.d.ts +36 -1
- package/dist/src/services/modelConfigService.js +66 -0
- package/dist/src/services/modelConfigService.js.map +1 -1
- package/dist/src/services/sandboxManager.d.ts +3 -4
- package/dist/src/services/sandboxManager.js +1 -14
- package/dist/src/services/sandboxManager.js.map +1 -1
- package/dist/src/services/sandboxManager.test.js +13 -16
- package/dist/src/services/sandboxManager.test.js.map +1 -1
- package/dist/src/services/sandboxManagerFactory.d.ts +11 -0
- package/dist/src/services/sandboxManagerFactory.js +31 -0
- package/dist/src/services/sandboxManagerFactory.js.map +1 -0
- package/dist/src/services/sandboxedFileSystemService.d.ts +17 -0
- package/dist/src/services/sandboxedFileSystemService.js +95 -0
- package/dist/src/services/sandboxedFileSystemService.js.map +1 -0
- package/dist/src/services/sandboxedFileSystemService.test.d.ts +6 -0
- package/dist/src/services/sandboxedFileSystemService.test.js +87 -0
- package/dist/src/services/sandboxedFileSystemService.test.js.map +1 -0
- package/dist/src/services/scripts/GeminiSandbox.cs +370 -0
- package/dist/src/services/shellExecutionService.d.ts +2 -0
- package/dist/src/services/shellExecutionService.js +79 -75
- package/dist/src/services/shellExecutionService.js.map +1 -1
- package/dist/src/services/trackerTypes.d.ts +1 -0
- package/dist/src/services/trackerTypes.js +1 -0
- package/dist/src/services/trackerTypes.js.map +1 -1
- package/dist/src/services/windowsSandboxManager.d.ts +27 -0
- package/dist/src/services/windowsSandboxManager.js +148 -0
- package/dist/src/services/windowsSandboxManager.js.map +1 -0
- package/dist/src/services/windowsSandboxManager.test.d.ts +6 -0
- package/dist/src/services/windowsSandboxManager.test.js +59 -0
- package/dist/src/services/windowsSandboxManager.test.js.map +1 -0
- package/dist/src/services/worktreeService.d.ts +33 -0
- package/dist/src/services/worktreeService.js +174 -0
- package/dist/src/services/worktreeService.js.map +1 -0
- package/dist/src/services/worktreeService.test.d.ts +6 -0
- package/dist/src/services/worktreeService.test.js +200 -0
- package/dist/src/services/worktreeService.test.js.map +1 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +4 -0
- package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +1 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +2 -0
- package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
- package/dist/src/telemetry/loggers.test.js +62 -40
- package/dist/src/telemetry/loggers.test.js.map +1 -1
- package/dist/src/telemetry/types.d.ts +1 -0
- package/dist/src/telemetry/types.js +3 -0
- package/dist/src/telemetry/types.js.map +1 -1
- package/dist/src/tools/definitions/model-family-sets/default-legacy.js +8 -1
- package/dist/src/tools/definitions/model-family-sets/default-legacy.js.map +1 -1
- package/dist/src/tools/definitions/model-family-sets/gemini-3.js +8 -1
- package/dist/src/tools/definitions/model-family-sets/gemini-3.js.map +1 -1
- package/dist/src/tools/exit-plan-mode.d.ts +6 -1
- package/dist/src/tools/exit-plan-mode.js +17 -6
- package/dist/src/tools/exit-plan-mode.js.map +1 -1
- package/dist/src/tools/exit-plan-mode.test.js +22 -1
- package/dist/src/tools/exit-plan-mode.test.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.d.ts +22 -3
- package/dist/src/tools/mcp-client-manager.js +84 -32
- package/dist/src/tools/mcp-client-manager.js.map +1 -1
- package/dist/src/tools/mcp-client-manager.test.js +76 -56
- package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
- package/dist/src/tools/mcp-client.d.ts +15 -6
- package/dist/src/tools/mcp-client.js +85 -71
- package/dist/src/tools/mcp-client.js.map +1 -1
- package/dist/src/tools/mcp-client.test.js +195 -88
- package/dist/src/tools/mcp-client.test.js.map +1 -1
- package/dist/src/tools/tool-registry.d.ts +2 -1
- package/dist/src/tools/tool-registry.js +12 -1
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +15 -0
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +1 -1
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/trackerTools.js +6 -1
- package/dist/src/tools/trackerTools.js.map +1 -1
- package/dist/src/tools/trackerTools.test.js +9 -1
- package/dist/src/tools/trackerTools.test.js.map +1 -1
- package/dist/src/tools/write-todos.js +1 -0
- package/dist/src/tools/write-todos.js.map +1 -1
- package/dist/src/tools/write-todos.test.js +4 -1
- package/dist/src/tools/write-todos.test.js.map +1 -1
- package/dist/src/utils/agent-sanitization-utils.d.ts +23 -0
- package/dist/src/utils/agent-sanitization-utils.js +123 -0
- package/dist/src/utils/agent-sanitization-utils.js.map +1 -0
- package/dist/src/utils/agent-sanitization-utils.test.d.ts +6 -0
- package/dist/src/utils/agent-sanitization-utils.test.js +83 -0
- package/dist/src/utils/agent-sanitization-utils.test.js.map +1 -0
- package/dist/src/utils/browserConsent.d.ts +17 -0
- package/dist/src/utils/browserConsent.js +78 -0
- package/dist/src/utils/browserConsent.js.map +1 -0
- package/dist/src/utils/browserConsent.test.d.ts +6 -0
- package/dist/src/utils/browserConsent.test.js +93 -0
- package/dist/src/utils/browserConsent.test.js.map +1 -0
- package/dist/src/utils/compatibility.d.ts +16 -0
- package/dist/src/utils/compatibility.js +58 -9
- package/dist/src/utils/compatibility.js.map +1 -1
- package/dist/src/utils/compatibility.test.js +127 -29
- package/dist/src/utils/compatibility.test.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.d.ts +2 -2
- package/dist/src/utils/memoryDiscovery.js +5 -10
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +37 -37
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/memoryImportProcessor.js +5 -5
- package/dist/src/utils/memoryImportProcessor.js.map +1 -1
- package/dist/src/utils/surface.js +4 -3
- package/dist/src/utils/surface.js.map +1 -1
- package/dist/src/utils/toolCallContext.d.ts +2 -0
- package/dist/src/utils/toolCallContext.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from 'node:child_process';
|
|
7
|
+
import {} from './fileSystemService.js';
|
|
8
|
+
import {} from './sandboxManager.js';
|
|
9
|
+
import { debugLogger } from '../utils/debugLogger.js';
|
|
10
|
+
import { isNodeError } from '../utils/errors.js';
|
|
11
|
+
/**
|
|
12
|
+
* A FileSystemService implementation that performs operations through a sandbox.
|
|
13
|
+
*/
|
|
14
|
+
export class SandboxedFileSystemService {
|
|
15
|
+
sandboxManager;
|
|
16
|
+
cwd;
|
|
17
|
+
constructor(sandboxManager, cwd) {
|
|
18
|
+
this.sandboxManager = sandboxManager;
|
|
19
|
+
this.cwd = cwd;
|
|
20
|
+
}
|
|
21
|
+
async readTextFile(filePath) {
|
|
22
|
+
const prepared = await this.sandboxManager.prepareCommand({
|
|
23
|
+
command: '__read',
|
|
24
|
+
args: [filePath],
|
|
25
|
+
cwd: this.cwd,
|
|
26
|
+
env: process.env,
|
|
27
|
+
});
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
// Direct spawn is necessary here for streaming large file contents.
|
|
30
|
+
const child = spawn(prepared.program, prepared.args, {
|
|
31
|
+
cwd: this.cwd,
|
|
32
|
+
env: prepared.env,
|
|
33
|
+
});
|
|
34
|
+
let output = '';
|
|
35
|
+
let error = '';
|
|
36
|
+
child.stdout?.on('data', (data) => {
|
|
37
|
+
output += data.toString();
|
|
38
|
+
});
|
|
39
|
+
child.stderr?.on('data', (data) => {
|
|
40
|
+
error += data.toString();
|
|
41
|
+
});
|
|
42
|
+
child.on('close', (code) => {
|
|
43
|
+
if (code === 0) {
|
|
44
|
+
resolve(output);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
reject(new Error(`Sandbox Error: read_file failed for '${filePath}'. Exit code ${code}. ${error ? 'Details: ' + error : ''}`));
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
child.on('error', (err) => {
|
|
51
|
+
reject(new Error(`Sandbox Error: Failed to spawn read_file for '${filePath}': ${err.message}`));
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
async writeTextFile(filePath, content) {
|
|
56
|
+
const prepared = await this.sandboxManager.prepareCommand({
|
|
57
|
+
command: '__write',
|
|
58
|
+
args: [filePath],
|
|
59
|
+
cwd: this.cwd,
|
|
60
|
+
env: process.env,
|
|
61
|
+
});
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
// Direct spawn is necessary here for streaming large file contents.
|
|
64
|
+
const child = spawn(prepared.program, prepared.args, {
|
|
65
|
+
cwd: this.cwd,
|
|
66
|
+
env: prepared.env,
|
|
67
|
+
});
|
|
68
|
+
child.stdin?.on('error', (err) => {
|
|
69
|
+
// Silently ignore EPIPE errors on stdin, they will be caught by the process error/close listeners
|
|
70
|
+
if (isNodeError(err) && err.code === 'EPIPE') {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
debugLogger.error(`Sandbox Error: stdin error for '${filePath}': ${err instanceof Error ? err.message : String(err)}`);
|
|
74
|
+
});
|
|
75
|
+
child.stdin?.write(content);
|
|
76
|
+
child.stdin?.end();
|
|
77
|
+
let error = '';
|
|
78
|
+
child.stderr?.on('data', (data) => {
|
|
79
|
+
error += data.toString();
|
|
80
|
+
});
|
|
81
|
+
child.on('close', (code) => {
|
|
82
|
+
if (code === 0) {
|
|
83
|
+
resolve();
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
reject(new Error(`Sandbox Error: write_file failed for '${filePath}'. Exit code ${code}. ${error ? 'Details: ' + error : ''}`));
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
child.on('error', (err) => {
|
|
90
|
+
reject(new Error(`Sandbox Error: Failed to spawn write_file for '${filePath}': ${err.message}`));
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=sandboxedFileSystemService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandboxedFileSystemService.js","sourceRoot":"","sources":["../../../src/services/sandboxedFileSystemService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, vi, beforeEach, afterEach, } from 'vitest';
|
|
7
|
+
import { SandboxedFileSystemService } from './sandboxedFileSystemService.js';
|
|
8
|
+
import { spawn } from 'node:child_process';
|
|
9
|
+
import { EventEmitter } from 'node:events';
|
|
10
|
+
vi.mock('node:child_process', () => ({
|
|
11
|
+
spawn: vi.fn(),
|
|
12
|
+
}));
|
|
13
|
+
class MockSandboxManager {
|
|
14
|
+
async prepareCommand(req) {
|
|
15
|
+
return {
|
|
16
|
+
program: 'sandbox.exe',
|
|
17
|
+
args: ['0', req.cwd, req.command, ...req.args],
|
|
18
|
+
env: req.env || {},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
describe('SandboxedFileSystemService', () => {
|
|
23
|
+
let sandboxManager;
|
|
24
|
+
let service;
|
|
25
|
+
const cwd = '/test/cwd';
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
sandboxManager = new MockSandboxManager();
|
|
28
|
+
service = new SandboxedFileSystemService(sandboxManager, cwd);
|
|
29
|
+
vi.clearAllMocks();
|
|
30
|
+
});
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
vi.restoreAllMocks();
|
|
33
|
+
});
|
|
34
|
+
it('should read a file through the sandbox', async () => {
|
|
35
|
+
const mockChild = new EventEmitter();
|
|
36
|
+
Object.assign(mockChild, {
|
|
37
|
+
stdout: new EventEmitter(),
|
|
38
|
+
stderr: new EventEmitter(),
|
|
39
|
+
});
|
|
40
|
+
vi.mocked(spawn).mockReturnValue(mockChild);
|
|
41
|
+
const readPromise = service.readTextFile('/test/file.txt');
|
|
42
|
+
// Use setImmediate to ensure events are emitted after the promise starts executing
|
|
43
|
+
setImmediate(() => {
|
|
44
|
+
mockChild.stdout.emit('data', Buffer.from('file content'));
|
|
45
|
+
mockChild.emit('close', 0);
|
|
46
|
+
});
|
|
47
|
+
const content = await readPromise;
|
|
48
|
+
expect(content).toBe('file content');
|
|
49
|
+
expect(spawn).toHaveBeenCalledWith('sandbox.exe', ['0', cwd, '__read', '/test/file.txt'], expect.any(Object));
|
|
50
|
+
});
|
|
51
|
+
it('should write a file through the sandbox', async () => {
|
|
52
|
+
const mockChild = new EventEmitter();
|
|
53
|
+
const mockStdin = new EventEmitter();
|
|
54
|
+
Object.assign(mockStdin, {
|
|
55
|
+
write: vi.fn(),
|
|
56
|
+
end: vi.fn(),
|
|
57
|
+
});
|
|
58
|
+
Object.assign(mockChild, {
|
|
59
|
+
stdin: mockStdin,
|
|
60
|
+
stderr: new EventEmitter(),
|
|
61
|
+
});
|
|
62
|
+
vi.mocked(spawn).mockReturnValue(mockChild);
|
|
63
|
+
const writePromise = service.writeTextFile('/test/file.txt', 'new content');
|
|
64
|
+
setImmediate(() => {
|
|
65
|
+
mockChild.emit('close', 0);
|
|
66
|
+
});
|
|
67
|
+
await writePromise;
|
|
68
|
+
expect(mockStdin.write).toHaveBeenCalledWith('new content');
|
|
69
|
+
expect(mockStdin.end).toHaveBeenCalled();
|
|
70
|
+
expect(spawn).toHaveBeenCalledWith('sandbox.exe', ['0', cwd, '__write', '/test/file.txt'], expect.any(Object));
|
|
71
|
+
});
|
|
72
|
+
it('should reject if sandbox command fails', async () => {
|
|
73
|
+
const mockChild = new EventEmitter();
|
|
74
|
+
Object.assign(mockChild, {
|
|
75
|
+
stdout: new EventEmitter(),
|
|
76
|
+
stderr: new EventEmitter(),
|
|
77
|
+
});
|
|
78
|
+
vi.mocked(spawn).mockReturnValue(mockChild);
|
|
79
|
+
const readPromise = service.readTextFile('/test/file.txt');
|
|
80
|
+
setImmediate(() => {
|
|
81
|
+
mockChild.stderr.emit('data', Buffer.from('access denied'));
|
|
82
|
+
mockChild.emit('close', 1);
|
|
83
|
+
});
|
|
84
|
+
await expect(readPromise).rejects.toThrow("Sandbox Error: read_file failed for '/test/file.txt'. Exit code 1. Details: access denied");
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=sandboxedFileSystemService.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandboxedFileSystemService.test.js","sourceRoot":"","sources":["../../../src/services/sandboxedFileSystemService.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
using System;
|
|
8
|
+
using System.Runtime.InteropServices;
|
|
9
|
+
using System.Collections.Generic;
|
|
10
|
+
using System.Diagnostics;
|
|
11
|
+
using System.Security.Principal;
|
|
12
|
+
using System.IO;
|
|
13
|
+
|
|
14
|
+
public class GeminiSandbox {
|
|
15
|
+
[StructLayout(LayoutKind.Sequential)]
|
|
16
|
+
public struct STARTUPINFO {
|
|
17
|
+
public uint cb;
|
|
18
|
+
public string lpReserved;
|
|
19
|
+
public string lpDesktop;
|
|
20
|
+
public string lpTitle;
|
|
21
|
+
public uint dwX;
|
|
22
|
+
public uint dwY;
|
|
23
|
+
public uint dwXSize;
|
|
24
|
+
public uint dwYSize;
|
|
25
|
+
public uint dwXCountChars;
|
|
26
|
+
public uint dwYCountChars;
|
|
27
|
+
public uint dwFillAttribute;
|
|
28
|
+
public uint dwFlags;
|
|
29
|
+
public ushort wShowWindow;
|
|
30
|
+
public ushort cbReserved2;
|
|
31
|
+
public IntPtr lpReserved2;
|
|
32
|
+
public IntPtr hStdInput;
|
|
33
|
+
public IntPtr hStdOutput;
|
|
34
|
+
public IntPtr hStdError;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
[StructLayout(LayoutKind.Sequential)]
|
|
38
|
+
public struct PROCESS_INFORMATION {
|
|
39
|
+
public IntPtr hProcess;
|
|
40
|
+
public IntPtr hThread;
|
|
41
|
+
public uint dwProcessId;
|
|
42
|
+
public uint dwThreadId;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
[StructLayout(LayoutKind.Sequential)]
|
|
46
|
+
public struct JOBOBJECT_BASIC_LIMIT_INFORMATION {
|
|
47
|
+
public Int64 PerProcessUserTimeLimit;
|
|
48
|
+
public Int64 PerJobUserTimeLimit;
|
|
49
|
+
public uint LimitFlags;
|
|
50
|
+
public UIntPtr MinimumWorkingSetSize;
|
|
51
|
+
public UIntPtr MaximumWorkingSetSize;
|
|
52
|
+
public uint ActiveProcessLimit;
|
|
53
|
+
public UIntPtr Affinity;
|
|
54
|
+
public uint PriorityClass;
|
|
55
|
+
public uint SchedulingClass;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
[StructLayout(LayoutKind.Sequential)]
|
|
59
|
+
public struct IO_COUNTERS {
|
|
60
|
+
public ulong ReadOperationCount;
|
|
61
|
+
public ulong WriteOperationCount;
|
|
62
|
+
public ulong OtherOperationCount;
|
|
63
|
+
public ulong ReadTransferCount;
|
|
64
|
+
public ulong WriteTransferCount;
|
|
65
|
+
public ulong OtherTransferCount;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
[StructLayout(LayoutKind.Sequential)]
|
|
69
|
+
public struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION {
|
|
70
|
+
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
|
|
71
|
+
public IO_COUNTERS IoInfo;
|
|
72
|
+
public UIntPtr ProcessMemoryLimit;
|
|
73
|
+
public UIntPtr JobMemoryLimit;
|
|
74
|
+
public UIntPtr PeakProcessMemoryUsed;
|
|
75
|
+
public UIntPtr PeakJobMemoryUsed;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
[StructLayout(LayoutKind.Sequential)]
|
|
79
|
+
public struct SID_AND_ATTRIBUTES {
|
|
80
|
+
public IntPtr Sid;
|
|
81
|
+
public uint Attributes;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
[StructLayout(LayoutKind.Sequential)]
|
|
85
|
+
public struct TOKEN_MANDATORY_LABEL {
|
|
86
|
+
public SID_AND_ATTRIBUTES Label;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public enum JobObjectInfoClass {
|
|
90
|
+
ExtendedLimitInformation = 9
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
94
|
+
public static extern IntPtr GetCurrentProcess();
|
|
95
|
+
|
|
96
|
+
[DllImport("advapi32.dll", SetLastError = true)]
|
|
97
|
+
public static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle);
|
|
98
|
+
|
|
99
|
+
[DllImport("advapi32.dll", SetLastError = true)]
|
|
100
|
+
public static extern bool CreateRestrictedToken(IntPtr ExistingTokenHandle, uint Flags, uint DisableSidCount, IntPtr SidsToDisable, uint DeletePrivilegeCount, IntPtr PrivilegesToDelete, uint RestrictedSidCount, IntPtr SidsToRestrict, out IntPtr NewTokenHandle);
|
|
101
|
+
|
|
102
|
+
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
103
|
+
public static extern bool CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
|
|
104
|
+
|
|
105
|
+
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
106
|
+
public static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, string lpName);
|
|
107
|
+
|
|
108
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
109
|
+
public static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoClass JobObjectInfoClass, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);
|
|
110
|
+
|
|
111
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
112
|
+
public static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess);
|
|
113
|
+
|
|
114
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
115
|
+
public static extern uint ResumeThread(IntPtr hThread);
|
|
116
|
+
|
|
117
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
118
|
+
public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);
|
|
119
|
+
|
|
120
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
121
|
+
public static extern bool GetExitCodeProcess(IntPtr hProcess, out uint lpExitCode);
|
|
122
|
+
|
|
123
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
124
|
+
public static extern bool CloseHandle(IntPtr hObject);
|
|
125
|
+
|
|
126
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
127
|
+
public static extern IntPtr GetStdHandle(int nStdHandle);
|
|
128
|
+
|
|
129
|
+
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
130
|
+
public static extern bool ConvertStringSidToSid(string StringSid, out IntPtr Sid);
|
|
131
|
+
|
|
132
|
+
[DllImport("advapi32.dll", SetLastError = true)]
|
|
133
|
+
public static extern bool SetTokenInformation(IntPtr TokenHandle, int TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength);
|
|
134
|
+
|
|
135
|
+
[DllImport("kernel32.dll", SetLastError = true)]
|
|
136
|
+
public static extern IntPtr LocalFree(IntPtr hMem);
|
|
137
|
+
|
|
138
|
+
public const uint TOKEN_DUPLICATE = 0x0002;
|
|
139
|
+
public const uint TOKEN_QUERY = 0x0008;
|
|
140
|
+
public const uint TOKEN_ASSIGN_PRIMARY = 0x0001;
|
|
141
|
+
public const uint TOKEN_ADJUST_DEFAULT = 0x0080;
|
|
142
|
+
public const uint DISABLE_MAX_PRIVILEGE = 0x1;
|
|
143
|
+
public const uint CREATE_SUSPENDED = 0x00000004;
|
|
144
|
+
public const uint CREATE_UNICODE_ENVIRONMENT = 0x00000400;
|
|
145
|
+
public const uint JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x00002000;
|
|
146
|
+
public const uint STARTF_USESTDHANDLES = 0x00000100;
|
|
147
|
+
public const int TokenIntegrityLevel = 25;
|
|
148
|
+
public const uint SE_GROUP_INTEGRITY = 0x00000020;
|
|
149
|
+
public const uint INFINITE = 0xFFFFFFFF;
|
|
150
|
+
|
|
151
|
+
static int Main(string[] args) {
|
|
152
|
+
if (args.Length < 3) {
|
|
153
|
+
Console.WriteLine("Usage: GeminiSandbox.exe <network:0|1> <cwd> <command> [args...]");
|
|
154
|
+
Console.WriteLine("Internal commands: __read <path>, __write <path>");
|
|
155
|
+
return 1;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
bool networkAccess = args[0] == "1";
|
|
159
|
+
string cwd = args[1];
|
|
160
|
+
string command = args[2];
|
|
161
|
+
|
|
162
|
+
IntPtr hToken = IntPtr.Zero;
|
|
163
|
+
IntPtr hRestrictedToken = IntPtr.Zero;
|
|
164
|
+
IntPtr hJob = IntPtr.Zero;
|
|
165
|
+
IntPtr pSidsToDisable = IntPtr.Zero;
|
|
166
|
+
IntPtr pSidsToRestrict = IntPtr.Zero;
|
|
167
|
+
IntPtr networkSid = IntPtr.Zero;
|
|
168
|
+
IntPtr restrictedSid = IntPtr.Zero;
|
|
169
|
+
IntPtr lowIntegritySid = IntPtr.Zero;
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
// 1. Setup Token
|
|
173
|
+
IntPtr hCurrentProcess = GetCurrentProcess();
|
|
174
|
+
if (!OpenProcessToken(hCurrentProcess, TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_DEFAULT, out hToken)) {
|
|
175
|
+
Console.Error.WriteLine("Failed to open process token");
|
|
176
|
+
return 1;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
uint sidCount = 0;
|
|
180
|
+
uint restrictCount = 0;
|
|
181
|
+
|
|
182
|
+
// "networkAccess == false" implies Strict Sandbox Level 1.
|
|
183
|
+
if (!networkAccess) {
|
|
184
|
+
if (ConvertStringSidToSid("S-1-5-2", out networkSid)) {
|
|
185
|
+
sidCount = 1;
|
|
186
|
+
int saaSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
|
|
187
|
+
pSidsToDisable = Marshal.AllocHGlobal(saaSize);
|
|
188
|
+
SID_AND_ATTRIBUTES saa = new SID_AND_ATTRIBUTES();
|
|
189
|
+
saa.Sid = networkSid;
|
|
190
|
+
saa.Attributes = 0;
|
|
191
|
+
Marshal.StructureToPtr(saa, pSidsToDisable, false);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// S-1-5-12 is Restricted Code SID
|
|
195
|
+
if (ConvertStringSidToSid("S-1-5-12", out restrictedSid)) {
|
|
196
|
+
restrictCount = 1;
|
|
197
|
+
int saaSize = Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
|
|
198
|
+
pSidsToRestrict = Marshal.AllocHGlobal(saaSize);
|
|
199
|
+
SID_AND_ATTRIBUTES saa = new SID_AND_ATTRIBUTES();
|
|
200
|
+
saa.Sid = restrictedSid;
|
|
201
|
+
saa.Attributes = 0;
|
|
202
|
+
Marshal.StructureToPtr(saa, pSidsToRestrict, false);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (!CreateRestrictedToken(hToken, DISABLE_MAX_PRIVILEGE, sidCount, pSidsToDisable, 0, IntPtr.Zero, restrictCount, pSidsToRestrict, out hRestrictedToken)) {
|
|
207
|
+
Console.Error.WriteLine("Failed to create restricted token");
|
|
208
|
+
return 1;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// 2. Set Integrity Level to Low
|
|
212
|
+
if (ConvertStringSidToSid("S-1-16-4096", out lowIntegritySid)) {
|
|
213
|
+
TOKEN_MANDATORY_LABEL tml = new TOKEN_MANDATORY_LABEL();
|
|
214
|
+
tml.Label.Sid = lowIntegritySid;
|
|
215
|
+
tml.Label.Attributes = SE_GROUP_INTEGRITY;
|
|
216
|
+
int tmlSize = Marshal.SizeOf(tml);
|
|
217
|
+
IntPtr pTml = Marshal.AllocHGlobal(tmlSize);
|
|
218
|
+
try {
|
|
219
|
+
Marshal.StructureToPtr(tml, pTml, false);
|
|
220
|
+
SetTokenInformation(hRestrictedToken, TokenIntegrityLevel, pTml, (uint)tmlSize);
|
|
221
|
+
} finally {
|
|
222
|
+
Marshal.FreeHGlobal(pTml);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// 3. Handle Internal Commands or External Process
|
|
227
|
+
if (command == "__read") {
|
|
228
|
+
string path = args[3];
|
|
229
|
+
return RunInImpersonation(hRestrictedToken, () => {
|
|
230
|
+
try {
|
|
231
|
+
using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
|
|
232
|
+
using (StreamReader sr = new StreamReader(fs, System.Text.Encoding.UTF8)) {
|
|
233
|
+
char[] buffer = new char[4096];
|
|
234
|
+
int bytesRead;
|
|
235
|
+
while ((bytesRead = sr.Read(buffer, 0, buffer.Length)) > 0) {
|
|
236
|
+
Console.Write(buffer, 0, bytesRead);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return 0;
|
|
240
|
+
} catch (Exception e) {
|
|
241
|
+
Console.Error.WriteLine(e.Message);
|
|
242
|
+
return 1;
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
} else if (command == "__write") {
|
|
246
|
+
string path = args[3];
|
|
247
|
+
return RunInImpersonation(hRestrictedToken, () => {
|
|
248
|
+
try {
|
|
249
|
+
using (StreamReader reader = new StreamReader(Console.OpenStandardInput(), System.Text.Encoding.UTF8))
|
|
250
|
+
using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None))
|
|
251
|
+
using (StreamWriter writer = new StreamWriter(fs, System.Text.Encoding.UTF8)) {
|
|
252
|
+
char[] buffer = new char[4096];
|
|
253
|
+
int bytesRead;
|
|
254
|
+
while ((bytesRead = reader.Read(buffer, 0, buffer.Length)) > 0) {
|
|
255
|
+
writer.Write(buffer, 0, bytesRead);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return 0;
|
|
259
|
+
} catch (Exception e) {
|
|
260
|
+
Console.Error.WriteLine(e.Message);
|
|
261
|
+
return 1;
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// 4. Setup Job Object for external process
|
|
267
|
+
hJob = CreateJobObject(IntPtr.Zero, null);
|
|
268
|
+
if (hJob != IntPtr.Zero) {
|
|
269
|
+
JOBOBJECT_EXTENDED_LIMIT_INFORMATION limitInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
|
|
270
|
+
limitInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
|
271
|
+
int limitSize = Marshal.SizeOf(limitInfo);
|
|
272
|
+
IntPtr pLimit = Marshal.AllocHGlobal(limitSize);
|
|
273
|
+
try {
|
|
274
|
+
Marshal.StructureToPtr(limitInfo, pLimit, false);
|
|
275
|
+
SetInformationJobObject(hJob, JobObjectInfoClass.ExtendedLimitInformation, pLimit, (uint)limitSize);
|
|
276
|
+
} finally {
|
|
277
|
+
Marshal.FreeHGlobal(pLimit);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// 5. Launch Process
|
|
282
|
+
STARTUPINFO si = new STARTUPINFO();
|
|
283
|
+
si.cb = (uint)Marshal.SizeOf(si);
|
|
284
|
+
si.dwFlags = STARTF_USESTDHANDLES;
|
|
285
|
+
si.hStdInput = GetStdHandle(-10);
|
|
286
|
+
si.hStdOutput = GetStdHandle(-11);
|
|
287
|
+
si.hStdError = GetStdHandle(-12);
|
|
288
|
+
|
|
289
|
+
string commandLine = "";
|
|
290
|
+
for (int i = 2; i < args.Length; i++) {
|
|
291
|
+
if (i > 2) commandLine += " ";
|
|
292
|
+
commandLine += QuoteArgument(args[i]);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
PROCESS_INFORMATION pi;
|
|
296
|
+
if (!CreateProcessAsUser(hRestrictedToken, null, commandLine, IntPtr.Zero, IntPtr.Zero, true, CREATE_SUSPENDED | CREATE_UNICODE_ENVIRONMENT, IntPtr.Zero, cwd, ref si, out pi)) {
|
|
297
|
+
Console.Error.WriteLine("Failed to create process. Error: " + Marshal.GetLastWin32Error());
|
|
298
|
+
return 1;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
try {
|
|
302
|
+
if (hJob != IntPtr.Zero) {
|
|
303
|
+
AssignProcessToJobObject(hJob, pi.hProcess);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
ResumeThread(pi.hThread);
|
|
307
|
+
WaitForSingleObject(pi.hProcess, INFINITE);
|
|
308
|
+
|
|
309
|
+
uint exitCode = 0;
|
|
310
|
+
GetExitCodeProcess(pi.hProcess, out exitCode);
|
|
311
|
+
return (int)exitCode;
|
|
312
|
+
} finally {
|
|
313
|
+
CloseHandle(pi.hProcess);
|
|
314
|
+
CloseHandle(pi.hThread);
|
|
315
|
+
}
|
|
316
|
+
} catch (Exception e) {
|
|
317
|
+
Console.Error.WriteLine("Unexpected error: " + e.Message);
|
|
318
|
+
return 1;
|
|
319
|
+
} finally {
|
|
320
|
+
if (hRestrictedToken != IntPtr.Zero) CloseHandle(hRestrictedToken);
|
|
321
|
+
if (hToken != IntPtr.Zero) CloseHandle(hToken);
|
|
322
|
+
if (hJob != IntPtr.Zero) CloseHandle(hJob);
|
|
323
|
+
if (pSidsToDisable != IntPtr.Zero) Marshal.FreeHGlobal(pSidsToDisable);
|
|
324
|
+
if (pSidsToRestrict != IntPtr.Zero) Marshal.FreeHGlobal(pSidsToRestrict);
|
|
325
|
+
if (networkSid != IntPtr.Zero) LocalFree(networkSid);
|
|
326
|
+
if (restrictedSid != IntPtr.Zero) LocalFree(restrictedSid);
|
|
327
|
+
if (lowIntegritySid != IntPtr.Zero) LocalFree(lowIntegritySid);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
private static string QuoteArgument(string arg) {
|
|
332
|
+
if (string.IsNullOrEmpty(arg)) return "\"\"";
|
|
333
|
+
|
|
334
|
+
bool hasSpace = arg.IndexOfAny(new char[] { ' ', '\t' }) != -1;
|
|
335
|
+
if (!hasSpace && arg.IndexOf('\"') == -1) return arg;
|
|
336
|
+
|
|
337
|
+
// Windows command line escaping for arguments is complex.
|
|
338
|
+
// Rule: Backslashes only need escaping if they precede a double quote or the end of the string.
|
|
339
|
+
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
340
|
+
sb.Append('\"');
|
|
341
|
+
for (int i = 0; i < arg.Length; i++) {
|
|
342
|
+
int backslashCount = 0;
|
|
343
|
+
while (i < arg.Length && arg[i] == '\\') {
|
|
344
|
+
backslashCount++;
|
|
345
|
+
i++;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (i == arg.Length) {
|
|
349
|
+
// Escape backslashes before the closing double quote
|
|
350
|
+
sb.Append('\\', backslashCount * 2);
|
|
351
|
+
} else if (arg[i] == '\"') {
|
|
352
|
+
// Escape backslashes before a literal double quote
|
|
353
|
+
sb.Append('\\', backslashCount * 2 + 1);
|
|
354
|
+
sb.Append('\"');
|
|
355
|
+
} else {
|
|
356
|
+
// Backslashes don't need escaping here
|
|
357
|
+
sb.Append('\\', backslashCount);
|
|
358
|
+
sb.Append(arg[i]);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
sb.Append('\"');
|
|
362
|
+
return sb.ToString();
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
private static int RunInImpersonation(IntPtr hToken, Func<int> action) {
|
|
366
|
+
using (WindowsIdentity.Impersonate(hToken)) {
|
|
367
|
+
return action();
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { type EnvironmentSanitizationConfig } from './environmentSanitization.js';
|
|
7
7
|
import { type SandboxManager } from './sandboxManager.js';
|
|
8
|
+
import type { SandboxConfig } from '../config/config.js';
|
|
8
9
|
import { type ExecutionHandle, type ExecutionOutputEvent, type ExecutionResult } from './executionLifecycleService.js';
|
|
9
10
|
/**
|
|
10
11
|
* An environment variable that is set for shell executions. This can be used
|
|
@@ -33,6 +34,7 @@ export interface ShellExecutionConfig {
|
|
|
33
34
|
disableDynamicLineTrimming?: boolean;
|
|
34
35
|
scrollback?: number;
|
|
35
36
|
maxSerializedLines?: number;
|
|
37
|
+
sandboxConfig?: SandboxConfig;
|
|
36
38
|
}
|
|
37
39
|
/**
|
|
38
40
|
* Describes a structured event emitted during shell command execution.
|