Show model provider/org in the trust_remote_code consent dialog (#6537)

* Show model provider/org in the trust_remote_code consent dialog

The consent dialog showed only the trailing model name (modelName.split('/').pop()),
dropping the owner. The HF org/owner is the 'who do I trust' signal the prompt is
asking about, so render it: 'NVIDIA-Nemotron-3-Nano-4B from "unsloth"'. A null
provider for local paths and bare names leaves those renders unchanged. Applies to
the enable/blocked/malware variants (shared description block).

* Only show consent provider tag for a confident single Hub repo

Tighten parseModelDisplay so the 'from "<provider>"' tag is shown only for a
canonical owner/repo Hub id (exactly one slash, both segments non-empty) that is
not a local path and not part of a multi-repo scan. This avoids misattributing a
relative local directory name (models/llama/7b) or a LoRA base/external repo's
finding to the wrong publisher in a trust decision. Extract a ProviderSuffix
component so both description branches render the clause identically via &&.

* Tighten consent provider-tag comments

* Source the consent provider tag from the backend

The dialog inferred the provider client-side from the model id, using
scanCreatedRepos (a cleanup-only list) to detect multi-repo scope and a
regex that missed bare relative paths like a local owner/model dir. Both
could attribute the scanned code to the wrong publisher.

Move the decision to the backend, where locality and scan scope are
known: _consent_provider returns the owner only for a single, non-local,
canonical owner/repo Hub id, and the route returns it as payload[provider].
The frontend now renders scan.provider directly.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Suppress consent provider tag when external auto_map code is scanned

A single Hub repo can declare an auto_map that loads code from another repo
(owner/other--module.Class). The scanner fingerprints that external repo's
Python, but security_targets still held only the primary, so the dialog
attributed the custom code to the primary publisher. Pass the external refs
collected during the scan to _consent_provider and return no provider when any
are present, so attribution is shown only for genuinely self-contained repos.

* Trim comments to be more succinct

---------

Co-authored-by: Daniel Han <michaelhan2050@gmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
Daniel Han 2026-06-22 02:11:18 -07:00 committed by GitHub
commit 4e8d0da8f9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 82 additions and 3 deletions

View file

@ -1582,6 +1582,23 @@ async def get_model_config(
)
def _consent_provider(
model_name: str,
scanned_targets: List[str],
external_refs: Optional[List[str]] = None,
) -> Optional[str]:
"""HF org for the consent dialog's `from "<provider>"` tag, or None.
Returns the owner only for a single, non-local, canonical ``owner/repo`` id; a LoRA's
extra base, a local path, or an external ``auto_map`` ref yields None so the dialog
never misattributes scanned code.
"""
if len(scanned_targets) != 1 or external_refs or is_local_path(model_name):
return None
parts = model_name.split("/")
return parts[0] if len(parts) == 2 and all(parts) else None
@router.post("/remote-code-scan")
async def scan_model_remote_code(
model_name: str = Body(..., embed = True),
@ -1645,12 +1662,14 @@ async def scan_model_remote_code(
except Exception:
pass
external_refs: list = []
for _target in security_targets:
# Use the pre-base-resolution snapshot for the primary (see above).
_mark_scan_created(
_target, preexisting = _primary_preexisting if _target == model_name else None
)
for _ext in external_auto_map_repos(_target, hf_token):
external_refs.append(_ext)
_mark_scan_created(_ext)
decision = preflight_remote_code_consent_for_targets(security_targets, hf_token = hf_token)
payload = decision.response_payload()
@ -1658,6 +1677,8 @@ async def scan_model_remote_code(
# created_by_scan = primary flag (older clients); scan_created_repos drives cleanup.
payload["created_by_scan"] = model_name in scan_created_repos
payload["scan_created_repos"] = scan_created_repos
# Provider tag decided here, where locality/scan scope/external refs are known.
payload["provider"] = _consent_provider(model_name, security_targets, external_refs)
# Malware gate (metadata-only): surface HF-flagged unsafe files so the dialog can
# hard-block. Orthogonal to remote code -- a poisoned pickle needs no auto_map.

View file

@ -815,6 +815,39 @@ class TestRemoteCodeScan:
assert not scan_remote_code_files({"modeling_x.py": _SCAN_MALICIOUS}).clean
class TestConsentProvider:
"""_consent_provider attributes the dialog's `from "<provider>"` tag only when safe."""
@staticmethod
def _fn():
from routes.models import _consent_provider
return _consent_provider
def test_single_hub_id_returns_owner(self):
assert self._fn()("NVIDIA/Nemotron", ["NVIDIA/Nemotron"]) == "NVIDIA"
assert self._fn()("NVIDIA/Nemotron", ["NVIDIA/Nemotron"], []) == "NVIDIA"
def test_multi_target_lora_returns_none(self):
# A LoRA scans adapter + base; attributing to one would mislead.
assert self._fn()("user/adapter", ["user/adapter", "NVIDIA/base"]) is None
def test_external_auto_map_ref_returns_none(self):
# A single repo whose auto_map pulls code from another repo: don't attribute it.
assert self._fn()("owner/repo", ["owner/repo"], ["evilorg/evilrepo"]) is None
def test_local_path_returns_none(self, tmp_path):
d = tmp_path / "org" / "model"
d.mkdir(parents = True)
assert self._fn()(str(d), [str(d)]) is None
assert self._fn()("/home/me/model", ["/home/me/model"]) is None
def test_non_canonical_id_returns_none(self):
fn = self._fn()
assert fn("a/b/c", ["a/b/c"]) is None
assert fn("/repo", ["/repo"]) is None
assert fn("plainname", ["plainname"]) is None
class TestScannerCoversAllExecutableCode:
"""repo_remote_code_files must collect every .py the loader could execute, so the fingerprint can't certify unscanned code."""

View file

@ -39,6 +39,7 @@ interface RemoteCodeScanResponse {
scan_created_repos?: string[];
unsafe_files?: Array<{ path?: string; level?: string }>;
security_blocked?: boolean;
provider?: string | null;
}
/** Scan a model's auto_map code for the consent dialog (backend reads config + repo
@ -93,6 +94,7 @@ export async function getRemoteCodeScan(
(data.created_by_scan ? [data.model_name ?? modelName] : []),
unsafeFiles,
securityBlocked: Boolean(data.security_blocked),
provider: data.provider ?? null,
};
}

View file

@ -161,6 +161,24 @@ function FindingCard({ finding }: { finding: RemoteCodeFinding }) {
);
}
/** Last path segment of the model id, for display. */
function modelDisplayName(modelName?: string): string {
if (!modelName) return "This model";
return modelName.split("/").pop() || modelName;
}
/** ` from "<provider>"` clause, rendered only when a provider was resolved. */
function ProviderSuffix({ provider }: { provider: string | null }) {
if (!provider) return null;
return (
<>
{" "}
from{" "}
<span className="font-medium text-foreground">"{provider}"</span>
</>
);
}
/** App-wide consent dialog for trust_remote_code loads: shows scan findings with the
* flagged code in context; CRITICAL is a hard block. Mounted once in the root layout. */
export function RemoteCodeConsentDialog() {
@ -168,7 +186,8 @@ export function RemoteCodeConsentDialog() {
const scan = useRemoteCodeConsentDialogStore((s) => s.scan);
const resolve = useRemoteCodeConsentDialogStore((s) => s.resolve);
const displayName = scan?.modelName?.split("/").pop() || "This model";
const displayName = modelDisplayName(scan?.modelName);
const provider = scan?.provider ?? null;
const blocked = scan ? !scan.approvable : false;
const findings = scan?.findings ?? [];
const unsafeFiles = scan?.unsafeFiles ?? [];
@ -218,7 +237,8 @@ export function RemoteCodeConsentDialog() {
<>
<span className="font-medium text-foreground">
{displayName}
</span>{" "}
</span>
<ProviderSuffix provider={provider} />{" "}
contains files that Hugging Face's security scan flagged as
unsafe (for example, a malicious pickle that would run code
when the model loads). It cannot be loaded. The flagged
@ -228,7 +248,8 @@ export function RemoteCodeConsentDialog() {
<>
<span className="font-medium text-foreground">
{displayName}
</span>{" "}
</span>
<ProviderSuffix provider={provider} />{" "}
declares custom Python code in its repository.{" "}
{blocked
? "A security scan flagged CRITICAL issues, so it cannot be enabled."

View file

@ -42,6 +42,7 @@ export async function confirmRemoteCodeIfNeeded({
scanCreatedRepos: [],
unsafeFiles: [],
securityBlocked: false,
provider: null,
};
}

View file

@ -43,4 +43,5 @@ export interface RemoteCodeScan {
scanCreatedRepos: string[];
unsafeFiles: UnsafeFile[]; // files HF flagged unsafe; non-empty => hard block
securityBlocked: boolean; // blocked specifically by the malware gate
provider: string | null; // HF org for the "from <provider>" tag; null when unattributable
}