Description
allow_shell_exec is a security-sensitive flag in BotConfig that controls whether the TutorBot can execute shell commands via the exec tool. However, it cannot be persistently set to true due to three separate code omissions in the current v1.4.2 codebase.
Bugs Found
1. auto_start_bots does not pass allow_shell_exec to BotConfig
File: deeptutor/services/tutorbot/manager.py (around line 985)
When the server starts and auto_start_bots() runs, it reads config.yaml from disk but creates a BotConfig without passing allow_shell_exec. The field defaults to False even if the YAML file has allow_shell_exec: true.
# Current code — allow_shell_exec is missing:
config = BotConfig(
name=data.get("name", bid),
description=data.get("description", ""),
persona=data.get("persona", ""),
channels=data.get("channels", {}),
model=data.get("model"),
llm_selection=data.get("llm_selection"),
# ⚠️ allow_shell_exec not passed — defaults to False
)
This means any bot with auto_start: true will always start with allow_shell_exec: false, regardless of what the config file contains. Saving the config later persists the false value back to disk, overwriting the user's intended setting.
2. UpdateBotRequest does not include allow_shell_exec
File: deeptutor/api/routers/tutorbot.py (line 80-86)
class UpdateBotRequest(BaseModel):
name: str | None = None
description: str | None = None
persona: str | None = None
channels: dict | None = None
model: str | None = None
llm_selection: dict[str, str] | None = None
# ⚠️ allow_shell_exec is missing
The PATCH endpoint accepts the field (Pydantic silently ignores unknown fields) but never applies it.
3. _apply_payload does not handle allow_shell_exec
File: deeptutor/api/routers/tutorbot.py (line 327-341)
Even if the request model included the field, the function that applies PATCH payloads to the bot config does not handle it:
def _apply_payload(target, payload):
cfg = getattr(target, "config", target)
if payload.name is not None: cfg.name = payload.name
if payload.description is not None: cfg.description = payload.description
if payload.persona is not None: cfg.persona = payload.persona
if payload.channels is not None: cfg.channels = payload.channels
if payload.model is not None: cfg.model = payload.model
if "llm_selection" in payload.model_fields_set: cfg.llm_selection = ...
# ⚠️ allow_shell_exec not handled
Impact
- Users who manually edit
config.yaml to set allow_shell_exec: true will find it reset to false after every container restart or bot restart.
- The
exec tool cannot be enabled through the API (PATCH endpoint ignores the field).
- Skills that depend on shell execution (deep-question, deep-research, deep-solve, notebook, knowledge-base via CLI commands) remain inaccessible through TutorBot's chat interface.
Expected Behavior
auto_start_bots() should pass allow_shell_exec=data.get("allow_shell_exec", False) to the BotConfig constructor.
UpdateBotRequest should include allow_shell_exec: bool | None = None.
_apply_payload() should handle allow_shell_exec (e.g., if payload.allow_shell_exec is not None: cfg.allow_shell_exec = payload.allow_shell_exec).
Environment
- DeepTutor version: 1.4.2
- Docker image: ghcr.io/hkuds/deeptutor:latest (built 2026-05-28)
- Deployment: Docker with bind mount for data volume
Related
This is similar in spirit to the config-wipe bug fixed in #331 / #332 (v1.1.1), which addressed the same overwrite problem for the channels field.
Description
allow_shell_execis a security-sensitive flag inBotConfigthat controls whether the TutorBot can execute shell commands via theexectool. However, it cannot be persistently set totruedue to three separate code omissions in the current v1.4.2 codebase.Bugs Found
1.
auto_start_botsdoes not passallow_shell_execto BotConfigFile:
deeptutor/services/tutorbot/manager.py(around line 985)When the server starts and
auto_start_bots()runs, it readsconfig.yamlfrom disk but creates aBotConfigwithout passingallow_shell_exec. The field defaults toFalseeven if the YAML file hasallow_shell_exec: true.This means any bot with
auto_start: truewill always start withallow_shell_exec: false, regardless of what the config file contains. Saving the config later persists thefalsevalue back to disk, overwriting the user's intended setting.2.
UpdateBotRequestdoes not includeallow_shell_execFile:
deeptutor/api/routers/tutorbot.py(line 80-86)The PATCH endpoint accepts the field (Pydantic silently ignores unknown fields) but never applies it.
3.
_apply_payloaddoes not handleallow_shell_execFile:
deeptutor/api/routers/tutorbot.py(line 327-341)Even if the request model included the field, the function that applies PATCH payloads to the bot config does not handle it:
Impact
config.yamlto setallow_shell_exec: truewill find it reset tofalseafter every container restart or bot restart.exectool cannot be enabled through the API (PATCH endpoint ignores the field).Expected Behavior
auto_start_bots()should passallow_shell_exec=data.get("allow_shell_exec", False)to the BotConfig constructor.UpdateBotRequestshould includeallow_shell_exec: bool | None = None._apply_payload()should handleallow_shell_exec(e.g.,if payload.allow_shell_exec is not None: cfg.allow_shell_exec = payload.allow_shell_exec).Environment
Related
This is similar in spirit to the config-wipe bug fixed in #331 / #332 (v1.1.1), which addressed the same overwrite problem for the
channelsfield.