-
Notifications
You must be signed in to change notification settings - Fork 1
fix: harden Docker sandbox, MCP bridge, and code runner #194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
cf5e5e7
4f62ca6
a093d4d
bc1cd55
e777e9b
106ec1c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2101,7 +2101,7 @@ Tool execution requires safety boundaries proportional to the risk of each tool | |
| | Backend | Isolation | Latency | Dependencies | Status | | ||
| |---------|-----------|---------|--------------|--------| | ||
| | `SubprocessSandbox` | Process-level: env filtering (allowlist + denylist), restricted PATH (configurable via `extra_safe_path_prefixes`), workspace-scoped cwd, timeout + process-group kill, library injection var blocking, explicit transport cleanup on Windows | ~ms | None | **Implemented** | | ||
| | `DockerSandbox` | Container-level: ephemeral container, mounted workspace, no network, resource limits (CPU/memory/time) | ~1-2s cold start | Docker | Planned | | ||
| | `DockerSandbox` | Container-level: ephemeral container, mounted workspace, no network, resource limits (CPU/memory/time) | ~1-2s cold start | Docker | **Implemented** | | ||
| | `K8sSandbox` | Pod-level: per-agent containers, namespace isolation, resource quotas, network policies | ~2-5s | Kubernetes | Future | | ||
|
|
||
| #### Default Layered Configuration | ||
|
|
@@ -2728,7 +2728,8 @@ Circular inheritance is detected via chain tracking and raises `TemplateInherita | |
| | **Web UI** | Vue 3 + Vite | Modern, fast, good ecosystem. Simpler than React for dashboards | | ||
| | **Real-time** | WebSocket (Litestar channels plugin) | Built-in pub/sub broadcasting, per-channel history, backpressure management. Real-time agent activity, task updates, chat feed | | ||
| | **Containerization** | Docker + Docker Compose | Isolated code execution, reproducible environments | | ||
| | **Tool Integration** | MCP (Model Context Protocol) | Industry standard for LLM-to-tool integration | | ||
| | **Docker API** | aiodocker | Async-native Docker API client for `DockerSandbox` backend | | ||
| | **Tool Integration** | MCP SDK (`mcp`) | Industry standard for LLM-to-tool integration | | ||
| | **Agent Comms** | A2A Protocol compatible | Future-proof inter-agent communication | | ||
| | **Config Format** | YAML + Pydantic validation | Human-readable config with strict validation | | ||
| | **CLI** | TBD (future, if needed) | Thin wrapper around the REST API for terminal use. May not be needed — interactive Scalar docs at `/docs/api` and `curl`/`httpie` may suffice | | ||
|
|
@@ -2960,7 +2961,10 @@ ai-company/ | |
| │ │ │ ├── task_routing.py # TASK_ROUTING_* constants | ||
| │ │ │ ├── template.py # TEMPLATE_* constants | ||
| │ │ │ ├── tool.py # TOOL_* constants | ||
| │ │ │ └── workspace.py # WORKSPACE_* constants | ||
| │ │ │ ├── workspace.py # WORKSPACE_* constants | ||
| │ │ │ ├── code_runner.py # CODE_RUNNER_* constants | ||
| │ │ │ ├── docker.py # DOCKER_* constants | ||
| │ │ │ └── mcp.py # MCP_* constants | ||
| │ │ ├── processors.py # Log processors | ||
| │ │ ├── setup.py # Logging setup | ||
| │ │ └── sinks.py # Log output backends | ||
|
|
@@ -3015,9 +3019,21 @@ ai-company/ | |
| │ │ ├── _git_base.py # Base class for git tools (workspace, subprocess, sandbox integration) | ||
| │ │ ├── _process_cleanup.py # Subprocess transport cleanup utility (Windows ResourceWarning prevention) | ||
| │ │ ├── git_tools.py # Git operations — 6 built-in tools (sandbox-aware) | ||
| │ │ ├── code_runner.py # Code execution (M7) | ||
| │ │ ├── docker_config.py # Docker sandbox configuration | ||
| │ │ ├── docker_sandbox.py # DockerSandbox backend (aiodocker) | ||
| │ │ ├── sandboxing_config.py # Top-level sandboxing config (backend selection) | ||
| │ │ ├── code_runner.py # Code execution tool | ||
| │ │ ├── web_tools.py # HTTP, search (M7) | ||
| │ │ └── mcp_bridge.py # MCP server integration (M7) | ||
| │ │ └── mcp/ # MCP bridge subpackage | ||
| │ │ ├── __init__.py # Package exports | ||
| │ │ ├── bridge_tool.py # McpBridgeTool (BaseTool integration) | ||
| │ │ ├── cache.py # Tool schema caching | ||
| │ │ ├── client.py # MCP client wrapper | ||
| │ │ ├── config.py # MCP server/bridge config models | ||
| │ │ ├── errors.py # MCP error hierarchy | ||
| │ │ ├── factory.py # McpBridgeTool factory | ||
|
||
| │ │ ├── models.py # MCP domain models | ||
| │ │ └── result_mapper.py # MCP result → ToolExecutionResult mapping | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| │ ├── security/ # Security & approval (M7, stubs only) | ||
| │ │ ├── approval.py # Approval workflow gates (M7) — domain model is in core/approval.py | ||
| │ │ ├── secops_agent.py # Security operations agent (M7) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| FROM node:22-slim AS node-base | ||
|
|
||
| FROM python:3.14-slim | ||
|
|
||
| COPY --from=node-base /usr/local/bin/node /usr/local/bin/node | ||
| COPY --from=node-base /usr/local/lib/node_modules /usr/local/lib/node_modules | ||
| RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm | ||
|
|
||
| RUN apt-get update && apt-get install -y --no-install-recommends git \ | ||
| && apt-get clean && rm -rf /var/lib/apt/lists/* | ||
|
|
||
|
Comment on lines
+9
to
+11
|
||
| RUN mkdir -p /workspace \ | ||
| && useradd --uid 65534 --gid 65534 --no-create-home --shell /usr/sbin/nologin sandbox | ||
|
greptile-apps[bot] marked this conversation as resolved.
Outdated
|
||
|
|
||
| WORKDIR /workspace | ||
|
|
||
| USER sandbox | ||
|
|
||
| CMD ["bash"] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| """Code runner tool event constants.""" | ||
|
|
||
| from typing import Final | ||
|
|
||
| CODE_RUNNER_EXECUTE_START: Final[str] = "code_runner.execute.start" | ||
| CODE_RUNNER_EXECUTE_SUCCESS: Final[str] = "code_runner.execute.success" | ||
| CODE_RUNNER_EXECUTE_FAILED: Final[str] = "code_runner.execute.failed" | ||
| CODE_RUNNER_INVALID_LANGUAGE: Final[str] = "code_runner.invalid_language" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| """Docker sandbox event constants.""" | ||
|
|
||
| from typing import Final | ||
|
|
||
| DOCKER_EXECUTE_START: Final[str] = "docker.execute.start" | ||
| DOCKER_EXECUTE_SUCCESS: Final[str] = "docker.execute.success" | ||
| DOCKER_EXECUTE_FAILED: Final[str] = "docker.execute.failed" | ||
| DOCKER_EXECUTE_TIMEOUT: Final[str] = "docker.execute.timeout" | ||
| DOCKER_CONTAINER_CREATED: Final[str] = "docker.container.created" | ||
| DOCKER_CONTAINER_STOPPED: Final[str] = "docker.container.stopped" | ||
| DOCKER_CONTAINER_REMOVED: Final[str] = "docker.container.removed" | ||
| DOCKER_CONTAINER_STOP_FAILED: Final[str] = "docker.container.stop_failed" | ||
| DOCKER_CONTAINER_REMOVE_FAILED: Final[str] = "docker.container.remove_failed" | ||
| DOCKER_CLEANUP: Final[str] = "docker.cleanup" | ||
| DOCKER_HEALTH_CHECK: Final[str] = "docker.health_check" | ||
| DOCKER_DAEMON_UNAVAILABLE: Final[str] = "docker.daemon.unavailable" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| """MCP bridge event constants.""" | ||
|
|
||
| from typing import Final | ||
|
|
||
| MCP_CLIENT_CONNECTING: Final[str] = "mcp.client.connecting" | ||
| MCP_CLIENT_CONNECTED: Final[str] = "mcp.client.connected" | ||
| MCP_CLIENT_DISCONNECTED: Final[str] = "mcp.client.disconnected" | ||
| MCP_CLIENT_RECONNECTING: Final[str] = "mcp.client.reconnecting" | ||
| MCP_CLIENT_CONNECTION_FAILED: Final[str] = "mcp.client.connection_failed" | ||
| MCP_DISCOVERY_START: Final[str] = "mcp.discovery.start" | ||
| MCP_DISCOVERY_COMPLETE: Final[str] = "mcp.discovery.complete" | ||
| MCP_DISCOVERY_FAILED: Final[str] = "mcp.discovery.failed" | ||
| MCP_DISCOVERY_FILTERED: Final[str] = "mcp.discovery.filtered" | ||
| MCP_INVOKE_START: Final[str] = "mcp.invoke.start" | ||
| MCP_INVOKE_SUCCESS: Final[str] = "mcp.invoke.success" | ||
| MCP_INVOKE_FAILED: Final[str] = "mcp.invoke.failed" | ||
| MCP_INVOKE_TIMEOUT: Final[str] = "mcp.invoke.timeout" | ||
| MCP_RESULT_MAPPED: Final[str] = "mcp.result.mapped" | ||
| MCP_RESULT_ATTACHMENT: Final[str] = "mcp.result.attachment" | ||
| MCP_CACHE_HIT: Final[str] = "mcp.cache.hit" | ||
| MCP_CACHE_MISS: Final[str] = "mcp.cache.miss" | ||
| MCP_CACHE_EVICT: Final[str] = "mcp.cache.evict" | ||
| MCP_CONFIG_VALIDATION_FAILED: Final[str] = "mcp.config.validation_failed" | ||
| MCP_CLIENT_DISCONNECT_FAILED: Final[str] = "mcp.client.disconnect_failed" | ||
| MCP_FACTORY_START: Final[str] = "mcp.factory.start" | ||
| MCP_FACTORY_COMPLETE: Final[str] = "mcp.factory.complete" | ||
| MCP_FACTORY_SERVER_SKIPPED: Final[str] = "mcp.factory.server_skipped" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The DESIGN_SPEC.md describes
cache.pyas "Tool schema caching" but the actual module provides MCP tool result caching (TTL+LRU), not schema caching. The comment should read something like "MCP result cache (TTL + LRU)".