From ca7e0cb52768fc1bcf26b2a368ea03d39e84fa87 Mon Sep 17 00:00:00 2001 From: danielhanchen Date: Fri, 17 Jul 2026 13:38:07 +0000 Subject: [PATCH] Send the HF token as a header, not a URL query param The model config, vision-check, and embedding-check requests appended the Hugging Face token as ?hf_token=..., which leaks it into server access logs, proxy logs, and browser history for gated/private models. Send it via the existing X-Unsloth-HF-Token header (hubTokenHeader) instead, and read it on the backend through the standard get_hf_token dependency, matching the picker's template routes. Also drop two catch-block comments that just restated the code. --- studio/backend/routes/models.py | 6 +++--- .../src/features/training/api/models-api.ts | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/studio/backend/routes/models.py b/studio/backend/routes/models.py index b8526c75e7..92dac00347 100644 --- a/studio/backend/routes/models.py +++ b/studio/backend/routes/models.py @@ -1796,7 +1796,7 @@ def _get_model_size_bytes(model_name: str, hf_token: Optional[str] = None) -> Op @router.get("/config/{model_name:path}") async def get_model_config( model_name: str, - hf_token: Optional[str] = Query(None), + hf_token: Optional[str] = Depends(get_hf_token), current_subject: str = Depends(get_current_subject), ): """Get configuration for a specific model (wraps load_model_defaults).""" @@ -2517,7 +2517,7 @@ async def get_lora_base_model(lora_path: str, current_subject: str = Depends(get @router.get("/check-vision/{model_name:path}", response_model = VisionCheckResponse) async def check_vision_model( model_name: str, - hf_token: Optional[str] = Query(None), + hf_token: Optional[str] = Depends(get_hf_token), current_subject: str = Depends(get_current_subject), ): """ @@ -2549,7 +2549,7 @@ async def check_vision_model( @router.get("/check-embedding/{model_name:path}", response_model = EmbeddingCheckResponse) async def check_embedding_model( model_name: str, - hf_token: Optional[str] = Query(None), + hf_token: Optional[str] = Depends(get_hf_token), current_subject: str = Depends(get_current_subject), ): """ diff --git a/studio/frontend/src/features/training/api/models-api.ts b/studio/frontend/src/features/training/api/models-api.ts index e5fd8b043d..2ccc49f9e5 100644 --- a/studio/frontend/src/features/training/api/models-api.ts +++ b/studio/frontend/src/features/training/api/models-api.ts @@ -2,6 +2,7 @@ // Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0 import { authFetch } from "@/features/auth"; +import { hubTokenHeader } from "@/features/hub"; interface VisionCheckResponse { model_name: string; @@ -98,10 +99,10 @@ export async function checkVisionModel( hfToken?: string | null, ): Promise { const encoded = encodeURIComponent(modelName); - const query = hfToken?.trim() ? `?hf_token=${encodeURIComponent(hfToken.trim())}` : ""; - const response = await authFetch(`/api/models/check-vision/${encoded}${query}`); + const response = await authFetch(`/api/models/check-vision/${encoded}`, { + headers: hubTokenHeader(hfToken?.trim() || null), + }); if (!response.ok) { - // If the check fails (e.g. network error), default to non-vision return false; } const data = (await response.json()) as VisionCheckResponse; @@ -114,10 +115,10 @@ export async function checkEmbeddingModel( hfToken?: string | null, ): Promise { const encoded = encodeURIComponent(modelName); - const query = hfToken?.trim() ? `?hf_token=${encodeURIComponent(hfToken.trim())}` : ""; - const response = await authFetch(`/api/models/check-embedding/${encoded}${query}`); + const response = await authFetch(`/api/models/check-embedding/${encoded}`, { + headers: hubTokenHeader(hfToken?.trim() || null), + }); if (!response.ok) { - // If the check fails (e.g. network error), default to non-embedding return false; } const data = (await response.json()) as EmbeddingCheckResponse; @@ -130,8 +131,10 @@ export async function getModelConfig( hfToken?: string, ): Promise { const encoded = encodeURIComponent(modelName); - const params = hfToken ? `?hf_token=${encodeURIComponent(hfToken)}` : ""; - const response = await authFetch(`/api/models/config/${encoded}${params}`, { signal }); + const response = await authFetch(`/api/models/config/${encoded}`, { + headers: hubTokenHeader(hfToken), + signal, + }); if (!response.ok) { throw new Error(`Failed to fetch model config (${response.status})`); }