fix(runtime): restore authorized local control paths

This commit is contained in:
Alexandre Teixeira
2026-10-02 23:15:51 +01:00
parent 6094e2abe6
commit b89d178291
10 changed files with 389 additions and 20 deletions
+10 -3
View File
@@ -408,8 +408,8 @@ def setup_cookbook_routes() -> APIRouter:
async def protect_native_control(request: Request):
if request.method in {"GET", "HEAD"}:
return
# Cookbook's UI records and session strings are not an application
# process registry. No loopback caller can use them as local authority.
# UI records/session strings are not process authority. Local tool
# launches require a one-use capability from their admitted producer.
path = request.url.path
from routes.shell_routes import _require_admin
if path in {"/api/cookbook/kill-pid", "/api/cookbook/state", "/api/cookbook/ssh-key"}:
@@ -417,7 +417,14 @@ def setup_cookbook_routes() -> APIRouter:
if path in {"/api/model/download", "/api/model/serve"}:
payload = await request.json()
if not payload.get("remote_host"):
_require_admin(request)
from src.agent_runtime.local_model_control import consume_model_control
from src.agent_runtime.resources import ResourceIdentityError
try:
claimed = consume_model_control(request, payload)
except (ResourceIdentityError, ValueError, TypeError):
raise HTTPException(403, "Local model capability denied") from None
if not claimed:
_require_admin(request)
router = APIRouter(tags=["cookbook"], dependencies=[Depends(protect_native_control)])
_cookbook_state_path = Path(COOKBOOK_STATE_FILE)
_state_get_cache = {"ts": 0.0, "mtime": 0.0, "value": None}
+8 -3
View File
@@ -59,12 +59,17 @@ from core.platform_compat import (
def _require_admin(request: Request):
"""Reject non-admin callers. Shell exec is admin-only — never expose to
regular users; that's RCE-after-signup."""
# Anonymous loopback is also reachable from an admitted native workload.
# It cannot be treated as a human admin or as process creation authority.
# Tool authentication is never human administration. Operator-disabled
# login has a separate direct-local transport contract below; it supplies
# no resource grant to model producers.
from src.agent_runtime.authority import is_internal_tool_request
if is_internal_tool_request(request):
from core.middleware import INTERNAL_TOOL_HEADER
if is_internal_tool_request(request) or request.headers.get(INTERNAL_TOOL_HEADER):
raise HTTPException(403, "Internal shell execution requires a dedicated resource-bound producer")
if _auth_disabled():
from src.auth_helpers import is_direct_loopback_request
if is_direct_loopback_request(request):
return
raise HTTPException(403, "Anonymous native process control has no resource authority")
auth_manager = getattr(request.app.state, "auth_manager", None)
if not auth_manager: