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.
This commit is contained in:
danielhanchen 2026-07-17 13:38:07 +00:00
commit ca7e0cb527
2 changed files with 14 additions and 11 deletions

View file

@ -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),
):
"""

View file

@ -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<boolean> {
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<boolean> {
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<ModelConfigResponse> {
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})`);
}