fix(runtime): enforce local control across Cookbook wrappers

This commit is contained in:
Alexandre Teixeira
2026-10-02 23:39:13 +01:00
parent bcc0e54e1b
commit 3834cd72b1
6 changed files with 68 additions and 10 deletions
+9
View File
@@ -426,6 +426,13 @@ def setup_cookbook_routes() -> APIRouter:
if not claimed:
_require_admin(request)
router = APIRouter(tags=["cookbook"], dependencies=[Depends(protect_native_control)])
def protect_local_model_producer(request, remote_host):
# Scoped wrappers can call endpoint functions directly, without FastAPI
# dependencies. Enforce native control at the actual producer as well.
if not remote_host and getattr(request.state, "local_model_authority", None) is None:
from routes.shell_routes import _require_admin
_require_admin(request)
_cookbook_state_path = Path(COOKBOOK_STATE_FILE)
_state_get_cache = {"ts": 0.0, "mtime": 0.0, "value": None}
_tasks_status_cache = {"ts": 0.0, "value": None}
@@ -1100,6 +1107,7 @@ def setup_cookbook_routes() -> APIRouter:
"""Download a HuggingFace model in a tmux session.
Uses `hf download` CLI directly — runs in tmux via `script -qc`
for real TTY progress, streams ANSI-stripped output via log file."""
protect_local_model_producer(request, req.remote_host)
require_admin(request)
# Defence-in-depth: even though this endpoint is admin-gated, refuse
# values that would land in shell contexts with metacharacters.
@@ -2018,6 +2026,7 @@ def setup_cookbook_routes() -> APIRouter:
keep strict validation, but serving local cached models must not require
a fake org/name wrapper.
"""
protect_local_model_producer(request, req.remote_host)
require_admin(request)
# Defence-in-depth: reject values that could break out of shell contexts.
validate_remote_host(req.remote_host)