Skip to content
Database Protection

Database Protection

TeamWeb AI’s PostgreSQL database contains sensitive data: plugin configuration with API keys, user credentials, knowledge base embeddings, conversation history, and generated content. Protecting the database from unauthorized access — especially from code that runs inside the platform — is a critical concern.

Architecture Overview

TeamWeb AI runs as a set of Docker containers connected via a shared network:

ServiceRoleNetwork Access
webFlask application serverFull — connects to db and redis
workerCelery task workerFull — connects to db and redis
beatCelery schedulerFull — connects to db and redis
dbPostgreSQL with pgvectorAccepts connections from the application network
redisMessage broker and cacheAccepts connections from the application network

All application services share a Docker network and have full access to the database. This is necessary for normal operation — the web server, workers, and scheduler all need to read and write data.

Sandbox Isolation

The key security boundary is between the application services and the sandbox containers that execute user-provided code. When an assistant runs code via the execute_code tool or executes a sandboxable plugin tool, that code runs in a separate Docker container that is not connected to the application network.

Code Execution Sandboxes

Sandbox containers created by execute_code are isolated from the application services:

  • No network configuration — Containers are created without connecting to the application network, so they cannot reach the database on db:5432 or Redis on redis:6379
  • No volume mounts — Application code, configuration files, and the .env file are not mounted into the sandbox
  • No credentials — Database connection strings, API keys, and environment variables are not passed to the container
  • Minimal image — The sandbox uses a python:3.12-slim base image with data science packages but no database drivers

The sandbox can only interact with the outside world through the files it writes to its /sandbox/output/ directory, which are collected by the application after execution.

Sandboxable Plugin Tools

Plugin tools marked as sandboxable run in an even more restricted environment:

  • Network disabled — The container is created with network_mode: none, completely blocking all network access (not even DNS)
  • Read-only plugin mount — Only the plugin’s own code directory is mounted, and as read-only
  • Serialized context — Instead of live database sessions and service objects, the plugin receives a plain dictionary with minimal data (project name, assistant name, user email)
  • No application config — The app_config dictionary is passed as empty, preventing access to any infrastructure secrets
Technical Details

Code execution containers — When execute_code is called, a Docker container is created from the teamwebai-sandbox image using the Docker API. The client.containers.create() call does not include a network parameter, which means the container is attached to Docker’s default bridge network — not the application’s dev-default network where the database and Redis run. Without being explicitly connected to dev-default, the container has no route to any application service. The container is created with tty=True so it stays alive between executions within the same conversation.

Sandbox lifecycle — Each conversation gets its own sandbox container, tracked in Redis by conversation ID. The container persists across multiple execute_code calls within the same conversation (so installed packages and created files are preserved between calls). Between agent loop iterations, the output directory is cleaned but the container and its installed packages remain. A background cleanup task runs every 5 minutes and removes containers that have been idle for more than 10 minutes.

Sandboxable plugin containers — These use an even stricter configuration. The network_mode: "none" Docker runtime flag disables all network interfaces inside the container — there is no loopback, no bridge, no external access whatsoever. The plugin’s source directory is mounted at /plugin as read-only, so the tool code can be loaded and executed. A generated Python script dynamically imports the tool class, instantiates it, calls execute() with the serialized parameters and context, and prints the JSON result to stdout.

What is NOT shared with sandboxes:

  • The .env file (contains DATABASE_URL, SECRET_KEY, API keys)
  • The /app directory (application source code)
  • The /data/plugins directory (other plugins and their configs)
  • Docker socket access (only the worker has this, for container management)
  • Any environment variables from the host process

Docker Socket Access

The Celery worker requires access to the Docker socket (/var/run/docker.sock) to create and manage sandbox containers and MCP server containers. This is a privileged capability — the Docker socket allows creating containers, inspecting the host, and potentially escalating privileges.

Only the worker service has Docker socket access. The web server and beat scheduler do not. In production, consider using a Docker socket proxy to restrict which Docker API calls the worker can make.

MCP Server Containers

MCP server containers have a different isolation model than code execution sandboxes:

  • Docker-managed MCP servers are connected to the application network so the worker can communicate with them via HTTP or stdio
  • They do not receive database credentials or application environment variables beyond what you explicitly configure in their environment variable settings
  • External MCP servers connect via their configured URL and have no direct access to TeamWeb AI’s infrastructure

See MCP Servers for details on container lifecycle and transport types.

Best Practices

  • Restrict database access — In production, ensure the PostgreSQL instance only accepts connections from the application services, not from arbitrary containers or external hosts
  • Use Docker socket proxies — Tools like docker-socket-proxy can limit which Docker API operations the worker can perform
  • Audit MCP server environment variables — Any environment variables you configure on an MCP server are visible inside that container. Do not pass database credentials or other infrastructure secrets to MCP servers
  • Review plugin code — Sandboxable plugins run in isolation, but non-sandboxable plugins execute in the worker process with full database access. Only install trusted plugins
  • Network segmentation — Consider placing the database on a separate Docker network that only the application services (web, worker, beat) can access