Gå til hovedindhold

Modelscanning

En modelfil kan køre kode, når den indlæses. Et PyTorch-checkpoint er en Python-pickle, og når den unpickles, kan den importere og kalde hvad som helst. Keras-Lambda-lag, GGUF-chatskabeloner og brugerdefinerede ONNX-operatorer er andre veje ind. fremforge scanner modelfiler, uanset hvor de lander i din organisation, og gemmer én dom pr. fil. Din organisations politik afgør, hvad der sker med en fil, som scanningen finder noget i.

Ingen model bliver nogensinde indlæst eller kørt for at blive scannet. Scanneren læser filens struktur: pickle-filens importliste, safetensors- og GGUF-headerne, ONNX-grafen og Keras-konfigurationen.

Hvor modelfiler findes

OverfladeHvornår den scannesHvad håndhævelse gør
Git LFSVed uploadAfviser uploaden med 422
Pakker (generiske og alle typer, hvor uploadens body er selve filen)Ved uploadAfviser uploaden med 422
Container-registry (ModelPack, KitOps, Docker ai/ og modelfiler i almindelige images)Efter pushetAfviser et pull, der ville levere laget, med 403
Afhængighedsproxy (container-images)Første gang den hentesAfviser senere pulls af laget med 403
Actions-artefakterNår kørslen er færdigIntet. Artefakter får kun fund

En fil genkendes som en model på sine første bytes, ikke på sit navn. En pickle, der er gemt som weights.txt, bliver stadig fundet.

Formater og domme

FormatHvad kontrolleres
Pickle, joblib, PyTorch (.pt, .pth, .bin, ældre format og zip), NumPy-objektarraysHver import i pickle-filen mod en tilladelsesliste. Tilladelseslisten er det, PyTorchs torch.load(weights_only=True) accepterer, plus de NumPy-typer, et state dict har brug for
safetensorsHeaderen: længder, datatyper og offsets, og at filen ikke også kan åbnes som zip eller pickle
GGUFMetadata, chatskabelonen (mod en sikker delmængde af Jinja) og de samme zip- og pickle-kontroller
ONNXDomæner for brugerdefinerede operatorer og stier til eksterne data, der peger uden for modellens mappe
Keras (.keras, .h5)Lambda-lag og brugerdefinerede objekter uden for Keras-navnerummet

Hver fil får én dom, som deles af alle organisationer, der har de samme bytes:

  • Ren: intet fundet.
  • Mistænkelig: en import uden for tilladelseslisten (pickle-unknown-import), en klasse fra et kendt ML-framework (pickle-framework-object, se Framework-pickles), en GGUF-skabelonkonstruktion uden for den sikre delmængde, en brugerdefineret ONNX-operator eller en fil, der også kan åbnes som et andet format.
  • Ondsindet: en import på scannerens blokeringsliste (som os.system eller builtins.eval) eller et Keras-Lambda-lag.
  • Kan ikke scannes: filen kunne ikke læses til ende: en ødelagt zip, et 7z-arkiv, en afkortet strøm.
  • Formatverificeret: en safetensors- eller GGUF-fil over 4 GiB, hvis strukturkontrol bestod. Se Over 4 GiB.

Scanneren er open source: picklescan til gennemgangen af pickle-filer, med fremforges tilladelsesliste ovenpå.

Din organisations politik

Politikken har tre tilstande. Sæt den under Sikkerhed › Politikker › Modelscanning eller med API’et.

TilstandHvad sker der
Skygge (standard)Hver fil scannes, og de filer, politikken ville blokere, vises som fund. Intet afvises.
HåndhævSom skygge, og filer med et åbent fund afvises som beskrevet i Hvor modelfiler findes.
FraFiler scannes stadig, og fundene vises stadig, men intet afvises eller tælles som ville-være-blokeret.

Ved håndhævelse blokerer politikken en fil, hvis dom er Ondsindet, Kan ikke scannes eller Mistænkelig, medmindre fundet er afvist. En fil, der er Ren eller Formatverificeret, går altid igennem.

Sådan ser håndhævelse ud

En upload, der afvises, svarer 422 med dommen, fundkoderne og filens sha256:

{
  "error": "model file rejected",
  "rule": "suspicious",
  "verdict": "suspicious",
  "findings": ["pickle-unknown-import"],
  "sha256": "d24ec017bdcf45a8737b4a9398e6eea64fa37a5821f473041cb3bc03f8489687"
}

En fil, der ikke er scannet før, scannes under uploaden. Det tager højst et par sekunder ekstra for en fil på op til 256 MiB. En safetensors- eller GGUF-fil over 256 MiB kontrolleres på sin header og sine sidste 64 KiB. Andre modelfiler over 256 MiB accepteres og scannes lige efter uploaden, så de dukker op som et fund et minut senere i stedet for at blive afvist.

Kan scanneren ikke nås, svarer en upload af en modelfil i en organisation, der håndhæver, 503 med Retry-After: 30. Uploads af andre filer påvirkes ikke.

Et container-pull, der ville levere et blokeret lag, svarer 403 DENIED med årsagen model-malicious, model-suspicious eller model-unscannable og lagets digest. Et modellag, du lige har pushet, scannes inden for cirka et minut. Indtil da svarer et pull 403 med årsagen model-scan-pending, på samme måde som et image med et lag, der stadig malwarescannes. Pulls fra runners hostet af fremforge holdes ikke tilbage af en ventende scanning.

git-lfs skjuler årsagen. Ved en afvist upload skriver git-lfs Uploading failed due to unsupported Content-Type header(s), og git lfs push --object-id afslutter med 0. Et almindeligt git push fejler. Årsagen står i svarets body, og filen vises som et fund under Modelscanning.

Framework-pickles

Nogle checkpoints gemmer hele Python-objekter, ikke kun vægte: en YOLO-model, en TrainingArguments-fil, en scikit-learn-pipeline. Når en af dem indlæses, kører den pågældende klasses kode. Scanneren mærker dem pickle-framework-object, når alle importer uden for vægt-tilladelseslisten kommer fra et kendt framework: PyTorch-moduler, Transformers, Ultralytics, scikit-learn, joblib, timm, Lightning, SpeechBrain eller Diffusers.

De er Mistænkelig som enhver anden ukendt import. For at lade dem passere håndhævelse skal du slå Tillad pickles fra kendte ML-frameworks (allow_framework_pickles) til. En fil med et hvilket som helst andet fund blokeres stadig.

Afvisning af et fund

En ejer af organisationen kan afvise et fund for én fil (én sha256) med en begrundelse og en udløbsdato: 90 dage som standard, højst 365. En afvist fil går igennem håndhævelse og forsvinder fra listen over fund. Afvisninger gælder pr. organisation; en anden organisation med de samme bytes påvirkes ikke. En afvisning kan til enhver tid tilbagekaldes.

Over 4 GiB

Malwarescanneren, ClamAV, kan ikke læse mere end 4 GiB af én fil, og fremforge afviser en fil, den ikke kan scanne. For modelvægte, som ofte er større end 4 GiB, er der én undtagelse i alle tilstande: en safetensors- eller GGUF-fil, hvis strukturkontrol består, accepteres som Formatverificeret. Disse formater indeholder kun tensorer og metadata, og strukturkontrollen beviser, at filen ikke indeholder andet. Filen malwarescannes ikke.

Alle andre filer over 4 GiB, herunder alle pickles, afvises stadig. Grænsen for én fil er 10 GiB. Store modeller udgives som shards på 5 GB eller mindre, så det er sjældent denne grænse, der betyder noget.

Actions-artefakter

Når en workflow-kørsel er færdig, kontrolleres de filer, den uploadede med actions/upload-artifact, for modelfiler, og de scannes. Et fund vises under Modelscanning med repositoriet, kørselsnummeret og artefaktet. Artefakter afvises eller slettes aldrig: at blokere en upload ville få dit workflow til at fejle uden mulighed for at tilsidesætte det.

AI-beholdning

Sikkerhed › Komponenter › AI-beholdning viser de maskinlæringsmodeller, din organisation har, og dem, dens CI henter. Siden er skrivebeskyttet; politikken og afvisningerne ligger stadig på siden for modelscanning.

Modelfiler

Én række pr. modelfil (pr. sha256) fundet i dit Git LFS, dine pakker, container-images, pulls gennem afhængighedsproxyen og Actions-artefakter, med:

  • dens format og størrelse og dens dom (Venter på scanning, mens den venter på at blive scannet);
  • dens licens, som den er angivet (se Hvor licenser kommer fra), og hvor den blev angivet. En model uden angivet licens vises som Ukendt. fremforge gætter ikke en licens ud fra et filnavn;
  • hvad dens header oplyser: antal parametre, tensor-datatyper og for GGUF arkitekturen og modelnavnet;
  • hvor den forekommer: hvert repository, hver pakke, hvert image eller artefakt, den er set i.

Hver modelfil findes også i komponentbeholdningen som pkg:generic/<file name>@<sha256>, så en komponentsøgning finder den, og “hvor bruges den” også virker for modeller. En model, som din CI henter fra Hugging Face, står der som pkg:huggingface/<org>/<name>@<revision> ved det repository, hvis workflow henter den.

Hvor licenser kommer fra

fremforge læser kun en licens fra metadata, der allerede er gemt på fremforge, og spørger ingen andre: intet om dine modeller forlader platformen. I denne rækkefølge:

  1. Selve filen: GGUF general.license eller en licensnøgle i en safetensors-fils metadata.
  2. Det modelartefakt, filen er et lag i, når du pusher det til din organisations registry eller henter det gennem afhængighedsproxyen. fremforge læser artefaktets små metadata-blobs fra sit eget lager, aldrig vægtene og aldrig upstream-registryet:
    PakningLæses
    ModelPack (modctl)konfigurationens descriptor.licenses
    KitOps (kit)Kitfile: en modeldels license for den del, derefter model.license, derefter package.license
    Docker Model Runner (docker model, ai/…)GGUF general.license i modelkonfigurationen, ellers licensfilen i artefaktet (application/vnd.docker.ai.license): Apache-2.0 og MIT genkendes på deres tekst, andre licenser på deres titel, såsom LLAMA 3.2 COMMUNITY LICENSE AGREEMENT
    enhver af demmanifest-annotationen org.opencontainers.image.licenses

API’et returnerer, hvor hver licens blev angivet, som licence_from, for eksempel ModelPack config descriptor.licenses; AI-beholdningen viser det ved siden af licensen. En licens fra et image, du har pushet, vises kun for din organisation. En model, der er hentet før 13. oktober 2026, får sin licens fra artefaktet inden for en time, hvis artefaktet stadig er gemt.

Modeller, din CI henter

Den daglige workflow-scanning læser hvert workflow på hvert repositorys standardbranch og de Python- og shellscripts, et workflow kører fra det samme repository (python scripts/fetch.py, bash ci/prepare.sh). Den finder:

VærktøjFindes som
Hugging Facefrom_pretrained("org/name"), hf_hub_download(repo_id=…), snapshot_download(…), huggingface-cli download, hf download
Ollamaollama pull name:tag
Dockerdocker model pull ref
KitOpskit pull ref
ModelPackmodctl pull ref

En reference er fastlåst, når den ikke kan ændre sig under dit build: en Hugging Face-model med en fuld commit-sha på 40 tegn som revision (revision="<sha>" eller --revision <sha>), og en Ollama-, Docker-, KitOps- eller ModelPack-model med et @sha256:-digest. En branch eller et tag som main eller v1.0 er ikke fastlåst. Hver ikke-fastlåst reference er et fund, ligesom en action, der er fastlåst til et tag i stedet for et commit.

Et modelnavn, der ikke står i filen, såsom from_pretrained(model_name), vises som Navn sat ved kørsel. Et HF_ENDPOINT, der er sat i samme fil, vises, fordi pullet så går til det endpoint i stedet for huggingface.co. En reference, du fjerner, forsvinder inden for tre dage.

Findes ikke: oras pull (et ORAS-artefakt er kun en model i kraft af sin medietype, som kommandoen ikke viser; hentet gennem afhængighedsproxyen klassificeres det ud fra sit manifest) og Python-kode uden for de scripts, et workflow kører.

Licensen for en Hugging Face-model, som din CI henter ved navn, vises som Ukendt: fremforge kontakter ikke Hugging Face eller nogen anden for at slå den op. En model, som din CI henter som et OCI-artefakt gennem afhængighedsproxyen, får sin licens fra artefaktet (se Hvor licenser kommer fra).

ML-BOM

Download ML-BOM (CycloneDX) på siden eller GET /ai/ml-bom returnerer beholdningen som et CycloneDX 1.6-dokument. Hver modelfil er en komponent af typen machine-learning-model med sin sha256, sin angivne licens (hvor den blev angivet, er egenskaben fremforge:model:licence_from), sin arkitektur som modelCard.modelParameters.modelArchitecture, når headeren navngiver en, og sit format, sin dom, sine overflader, sin størrelse, sit antal parametre og sine datatyper som fremforge:model:*-egenskaber. Kun fakta, der er læst fra filen, angives.

De SBOM’er, din CI uploader, ændres ikke: de er dine filer. ML-BOM’en er et separat dokument.

Compliance-rapport

Compliance-rapporten har et afsnit om AI-beholdning: antallet af modelfiler, de filer, din politik blokerer eller ville blokere, filer med et afvist fund, din tilstand for modelscanning, CI-modelpulls uden en fast revision og filerne pr. angivet licens. Dens CSV viser alle modelfiler. Afsnittet dækker altid hele organisationen, også i en rapport for ét repository.

Revisionslog

HændelseHvornår
security_policy.model_scan.updatedTilstanden eller indstillingen for framework-pickles blev ændret
security_policy.model_scan.dismissedEt fund blev afvist, eller en afvisning blev fornyet
security_policy.model_scan.dismissal_revokedEn afvisning blev tilbagekaldt
registry.pull.blocked med gate: modelEt pull blev afvist af modelpolitikken

En afvist pakkeupload eller et afvist container-pull står også i registry-adgangsloggen med årsagen model_policy:<rule>. Adgangsloggen dækker ikke Git LFS.

API

KaldScope
GET /_app/api/v1/orgs/{org}/security/model-policypolicy:read
PUT /_app/api/v1/orgs/{org}/security/model-policypolicy:write
GET /_app/api/v1/orgs/{org}/security/model-findings?status=open|dismissed|allfindings:read
POST /_app/api/v1/orgs/{org}/security/model-findings/{sha256}/dismisspolicy:write
DELETE /_app/api/v1/orgs/{org}/security/model-findings/{sha256}/dismissalpolicy:write
GET /_app/api/v1/orgs/{org}/ai/models?verdict=&format=&licence=&surface=components:read
GET /_app/api/v1/orgs/{org}/ai/models/{sha256}components:read
GET /_app/api/v1/orgs/{org}/ai/ml-bomcomponents:read
GET /_app/api/v1/orgs/{org}/ai/references?tool=&unpinned=true&repository=&model=components:read

PUT erstatter hele politikken: et felt, du udelader, får sin standardværdi.

curl -X PUT \
  -H "Authorization: Bearer ${FREMFORGE_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"mode":"enforce","allow_framework_pickles":false}' \
  https://frem.sh/_app/api/v1/orgs/acme/security/model-policy

En afvisning kræver policy:write, ikke findings:write, fordi en afvist fil går igennem håndhævelse. Et CI-jobs runner-token har det aldrig.

curl -X POST \
  -H "Authorization: Bearer ${FREMFORGE_PAT}" \
  -H "Content-Type: application/json" \
  -d '{"reason":"Our own YOLO checkpoint, built in CI","expires_at":"2027-01-31"}' \
  https://frem.sh/_app/api/v1/orgs/acme/security/model-findings/<sha256>/dismiss

Se API-referencen for svarenes format.

Hvad der ikke er dækket

  • Filer vedhæftet issues, pull requests og releases samt pakkeuploads, hvis body indeholder mere end filen (PyPI, NuGet og andre multipart-uploads). De malwarescannes som hidtil.
  • Modeller i dine repositoriers almindelige Git-objekter. Store modelfiler hører hjemme i Git LFS.
  • Indlæsning eller kørsel af en model og at finde en bagdør i dens vægte. Ingen scanner kan skelne en forgiftet vægt fra en normal.