From e0e60ef8285506a2aa29bea51e7c50ed67d46343 Mon Sep 17 00:00:00 2001 From: Thomas Stallinger Date: Mon, 21 Sep 2026 13:25:56 +0200 Subject: [PATCH] Fix: Cross-Org-Reaktivierung derselben Hardware crasht mit HTTP 500 Bare-Metal-Fund (21.09.2026): dieselbe physische Testmaschine wurde mit Aktivierungscodes zweier verschiedener Organisationen aktiviert (device_ fingerprint bleibt hardware-gebunden stabil, anders als bei VM-Testumgebungen mit Snapshot-Reset zwischen Laeufen). load_or_create_device() wirft dafuer bewusst einen RuntimeError, der bisher ungefangen bis zu FastAPI durchschlug (HTTP 500 "Internal Server Error" statt einer klaren Ablehnung) - fuer den Installer nicht von einem echten Serverfehler unterscheidbar. Jetzt sauber abgefangen und als strukturierte success:false-Antwort zurueckgegeben, analog zum bestehenden invalid_activation_code-Fall. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01DWKevK2QUK5tsGmqfSD6Yy --- app.py | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/app.py b/app.py index a3d623f..71cbceb 100644 --- a/app.py +++ b/app.py @@ -3824,23 +3824,35 @@ def activate(payload: ActivationRequest, request: Request): device = None device_created = False hardware_snapshot_id = None + device_conflict = False if success: hostname = resolve_hostname_for_activation( organization_id, payload.device_fingerprint, payload.hostname ) - device, device_created = load_or_create_device( - organization_id, - payload.device_fingerprint, - hostname, - ) - hardware_snapshot_id = store_hardware_snapshot( - device["id"], - payload.hardware, - ) + try: + device, device_created = load_or_create_device( + organization_id, + payload.device_fingerprint, + hostname, + ) + except RuntimeError: + # Bare-Metal-Fund (21.09.2026): dieselbe physische Hardware + # (device_fingerprint bleibt stabil, anders als bei VM-Testumgebungen + # mit Snapshot-Reset) mit einem Aktivierungscode einer ANDEREN + # Organisation erneut aktiviert - load_or_create_device() wirft dafuer + # bewusst einen RuntimeError, der bisher ungefangen bis zu FastAPI + # durchschlug (HTTP 500 statt einer klaren, erwarteten Ablehnung). + success = False + device_conflict = True + else: + hardware_snapshot_id = store_hardware_snapshot( + device["id"], + payload.hardware, + ) - if enrollment_session is not None: - consume_enrollment_session(enrollment_session["session_id"]) + if enrollment_session is not None: + consume_enrollment_session(enrollment_session["session_id"]) write_log({ "timestamp": datetime.now(timezone.utc).isoformat(), @@ -3853,6 +3865,13 @@ def activate(payload: ActivationRequest, request: Request): "client_version": payload.client_version }) + if device_conflict: + return { + "success": False, + "error": "device_belongs_to_other_organization", + "message": "Dieses Gerät ist bereits einer anderen Organisation zugeordnet." + } + if not success: return { "success": False,