Modellskanning
En modellfil kan kjøre kode når den lastes. Et PyTorch-sjekkpunkt er en Python-pickle, og å unpickle den kan importere og kalle hva som helst. Keras-lag av typen Lambda, chatmaler i GGUF og egendefinerte ONNX-operatorer er andre veier inn. fremforge skanner modellfiler overalt der de havner i organisasjonen din, og tar vare på én vurdering per fil. Organisasjonens policy bestemmer hva som skjer med en fil skanningen finner.
Ingen modell blir noen gang lastet eller kjørt for å skanne den. Skanneren leser strukturen i filen: importlisten i picklen, headerne i safetensors og GGUF, ONNX-grafen og Keras-konfigurasjonen.
Hvor modellfiler blir funnet
| Flate | Når den skannes | Hva håndheving gjør |
|---|---|---|
| Git LFS | Ved opplasting | Avviser opplastingen med 422 |
| Pakker (generiske, og alle typer der opplastingsbodyen er selve filen) | Ved opplasting | Avviser opplastingen med 422 |
Containerregister (ModelPack, KitOps, Docker ai/ og modellfiler inne i vanlige imager) | Etter push | Avviser en pull som ville servert laget, med 403 |
| Avhengighetsproxy (containerimager) | Ved første pull | Avviser senere pulls av laget med 403 |
| Actions-artefakter | Etter at kjøringen er ferdig | Ingenting. Artefakter får bare funn |
En fil gjenkjennes som en modell ut fra de første bytene, ikke navnet. En pickle lagret som weights.txt blir likevel funnet.
Formater og vurderinger
| Format | Hva som sjekkes |
|---|---|
Pickle, joblib, PyTorch (.pt, .pth, .bin, eldre format og zip), NumPy-objekttabeller | Hver import i picklen mot en tillatelsesliste. Tillatelseslisten er det PyTorchs torch.load(weights_only=True) godtar, pluss NumPy-typene en state dict trenger |
| safetensors | Headeren: lengder, datatyper og forskyvninger, og at filen ikke også kan åpnes som en zip eller en pickle |
| GGUF | Metadataene, chatmalen (mot et trygt utvalg av Jinja) og de samme zip- og pickle-sjekkene |
| ONNX | Domener for egendefinerte operatorer, og stier til eksterne data som går utenfor modellens katalog |
Keras (.keras, .h5) | Lambda-lag og egendefinerte objekter utenfor Keras-navnerommet |
Hver fil får én vurdering, som deles av alle organisasjoner som har de samme bytene:
- clean: ingenting funnet.
- suspicious: en import utenfor tillatelseslisten (
pickle-unknown-import), en klasse fra et kjent ML-rammeverk (pickle-framework-object, se Rammeverk-pickles), en konstruksjon i en GGUF-mal utenfor det trygge utvalget, en egendefinert ONNX-operator, eller en fil som også kan åpnes som et annet format. - malicious: en import på skannerens blokkeringsliste (som
os.systemellerbuiltins.eval), eller et Keras-Lambda-lag. - unscannable: filen kunne ikke leses til slutten: en ødelagt zip, et 7z-arkiv, en avkuttet strøm.
- format-verified: en safetensors- eller GGUF-fil over 4 GiB som besto strukturkontrollen. Se Over 4 GiB.
Skanneren er åpen kildekode: picklescan for gjennomgangen av picklen, med fremforges tillatelsesliste på toppen.
Organisasjonens policy
Policyen har tre moduser. Sett den under Sikkerhet › Policyer › Modellskanning eller med API-et.
| Modus | Hva som skjer |
|---|---|
| Skygge (standard) | Hver fil skannes, og filene policyen ville blokkert, listes som funn. Ingenting avvises. |
| Håndhev | Som shadow, og filene med et åpent funn avvises, slik det står i Hvor modellfiler blir funnet. |
| Av | Filene skannes fortsatt og funnene listes fortsatt, men ingenting avvises eller telles som «ville blitt blokkert». |
Under enforce blokkerer policyen en fil med vurderingen malicious, unscannable eller suspicious, med mindre funnet er avvist. En fil med clean eller format-verified slipper alltid gjennom.
Slik ser håndheving ut
En opplasting som avvises, svarer 422 med vurderingen, funnkodene og filens sha256:
{
"error": "model file rejected",
"rule": "suspicious",
"verdict": "suspicious",
"findings": ["pickle-unknown-import"],
"sha256": "d24ec017bdcf45a8737b4a9398e6eea64fa37a5821f473041cb3bc03f8489687"
}En fil som ikke er skannet før, skannes under opplastingen. Det legger til høyst noen få sekunder for en fil på opptil 256 MiB. En safetensors- eller GGUF-fil over 256 MiB sjekkes ut fra headeren og de siste 64 KiB. Andre modellfiler over 256 MiB godtas og skannes rett etter opplastingen, så de dukker opp som et funn et minutt senere i stedet for å bli avvist.
Hvis skanneren ikke kan nås, svarer en opplasting av en modellfil i en organisasjon som håndhever, med 503 og Retry-After: 30. Opplastinger av andre filer påvirkes ikke.
En container-pull som ville servert et blokkert lag, svarer 403 DENIED, med årsaken model-malicious, model-suspicious eller model-unscannable og lagets digest. Et modellag du nettopp har pushet, skannes i løpet av omtrent et minutt. Fram til da svarer en pull 403 med årsaken model-scan-pending, på samme måte som et image med et lag som fortsatt skannes for skadevare. Pulls fra runnere hostet av fremforge holdes ikke tilbake for en skanning som venter.
Uploading failed due to unsupported Content-Type header(s), og git lfs push --object-id avslutter med 0. En vanlig git push feiler derimot. Årsaken står i svarbodyen, og filen listes som et funn under Modellskanning.Rammeverk-pickles
Noen sjekkpunkter lagrer hele Python-objekter, ikke bare vekter: en YOLO-modell, en TrainingArguments-fil, en scikit-learn-pipeline. Å laste en slik kjører koden til klassen. Skanneren merker disse pickle-framework-object når hver import utenfor tillatelseslisten for vekter kommer fra et kjent rammeverk: PyTorch-moduler, Transformers, Ultralytics, scikit-learn, joblib, timm, Lightning, SpeechBrain eller Diffusers.
De er suspicious som enhver annen ukjent import. For å slippe dem gjennom enforce slår du på Tillat pickles fra kjente ML-rammeverk (allow_framework_pickles). En fil med andre funn blokkeres fortsatt.
Avvise et funn
En eier av organisasjonen kan avvise et funn for én fil (én sha256), med en begrunnelse og en utløpsdato: 90 dager som standard, høyst 365. En avvist fil slipper gjennom enforce og forsvinner fra funnlisten. Avvisninger gjelder per organisasjon; en annen organisasjon som har de samme bytene, påvirkes ikke. En avvisning kan tilbakekalles når som helst.
Over 4 GiB
Skadevareskanneren, ClamAV, kan ikke lese mer enn 4 GiB av én fil, og fremforge avviser en fil den ikke kan skanne. For modellvekter, som ofte er større enn 4 GiB, finnes det ett unntak, i alle moduser: en safetensors- eller GGUF-fil som består strukturkontrollen, godtas som format-verified. Disse formatene inneholder bare tensorer og metadata, og strukturkontrollen beviser at filen ikke inneholder noe annet. Filen skannes ikke for skadevare.
Alle andre filer over 4 GiB, inkludert alle pickles, avvises fortsatt. Grensen for én fil er 10 GiB. Store modeller publiseres som shards på 5 GB eller mindre, så dette er sjelden grensen som betyr noe.
Actions-artefakter
Når en workflow-kjøring er ferdig, sjekkes filene den lastet opp med actions/upload-artifact, for modellfiler, og disse skannes. Et funn listes under Modellskanning med repositoryet, kjøringsnummeret og artefaktet. Artefakter blir aldri avvist eller slettet: å blokkere en opplasting ville fått workflowen din til å feile uten noen måte å overstyre det på.
AI-oversikt
Sikkerhet › Komponenter › AI-oversikt lister maskinlæringsmodellene organisasjonen din har, og dem CI-en henter. Den er skrivebeskyttet; policyen og avvisningene ligger fortsatt på siden for modellskanning.
Modellfiler
Én rad per modellfil (per sha256) funnet i Git LFS, pakker, containerimager, pulls gjennom avhengighetsproxyen og Actions-artefakter, med:
- format og størrelse, og vurderingen (pending mens den venter på skanning);
- lisensen, slik den er deklarert (se Hvor lisensene kommer fra), med hvor den ble deklarert. En modell uten deklarert lisens viser unknown. fremforge gjetter ikke en lisens ut fra et filnavn;
- hva headeren oppgir: antall parametere, datatyper for tensorene, og for GGUF arkitekturen og modellnavnet;
- hvor den forekommer: hvert repository, hver pakke, hvert image eller artefakt den er sett i.
Hver modellfil står også i komponentoversikten som pkg:generic/<file name>@<sha256>, så et komponentsøk finner den, og «hvor brukes den» fungerer også for modeller. En modell CI-en din henter fra Hugging Face, står der som pkg:huggingface/<org>/<name>@<revision>, ved repositoryet med workflowen som henter den.
Hvor lisensene kommer fra
fremforge leser en lisens bare fra metadata som allerede er lagret på fremforge, og spør ingen andre: ingenting om modellene dine forlater plattformen. I denne rekkefølgen:
- Selve filen: GGUF
general.license, eller en lisensnøkkel i metadataene til en safetensors-fil. - Modellartefaktet filen er et lag i, når du pusher det til organisasjonens register eller henter det gjennom avhengighetsproxyen. fremforge leser de små metadatablobbene til artefaktet fra sitt eget lager, aldri vektene og aldri upstream-registeret:
Pakking Leser ModelPack ( modctl)descriptor.licensesi konfigurasjonenKitOps ( kit)Kitfile: licensei en modelldel for den delen, derettermodel.license, deretterpackage.licenseDocker Model Runner ( docker model,ai/…)GGUF general.licensei modellkonfigurasjonen, ellers lisensfilen i artefaktet (application/vnd.docker.ai.license): Apache-2.0 og MIT gjenkjennes på teksten, andre lisenser på tittelen, somLLAMA 3.2 COMMUNITY LICENSE AGREEMENTalle disse manifest-annotasjonen org.opencontainers.image.licenses
API-et returnerer hvor hver lisens ble deklarert, som licence_from, for eksempel ModelPack config descriptor.licenses; AI-oversikten viser det ved siden av lisensen. En lisens fra et image du har pushet, vises bare for organisasjonen din. En modell hentet før 13. oktober 2026 får lisensen fra artefaktet innen en time, når artefaktet fortsatt er lagret.
Modeller CI-en din henter
Den daglige workflow-skanningen leser hver workflow på standardbranchen i hvert repository, og Python- og shellskriptene en workflow kjører fra det samme repositoryet (python scripts/fetch.py, bash ci/prepare.sh). Den finner:
| Verktøy | Funnet som |
|---|---|
| Hugging Face | from_pretrained("org/name"), hf_hub_download(repo_id=…), snapshot_download(…), huggingface-cli download, hf download |
| Ollama | ollama pull name:tag |
| Docker | docker model pull ref |
| KitOps | kit pull ref |
| ModelPack | modctl pull ref |
En referanse er låst når den ikke kan endres under bygget ditt: en Hugging Face-modell med en full commit-sha på 40 tegn som revision (revision="<sha>" eller --revision <sha>), og en Ollama-, Docker-, KitOps- eller ModelPack-modell med en @sha256:-digest. En branch eller tag som main eller v1.0 er ikke låst. Hver ulåst referanse er et funn, som en action som er låst til en tag i stedet for en commit.
Et modellnavn som ikke står skrevet i filen, som from_pretrained(model_name), listes som name set at run time. En HF_ENDPOINT satt i samme fil vises, fordi pullen da går til det endepunktet i stedet for huggingface.co. En referanse du fjerner, forsvinner innen tre dager.
Finnes ikke: oras pull (et ORAS-artefakt er en modell bare ut fra medietypen, som kommandoen ikke viser; hentet gjennom avhengighetsproxyen klassifiseres det ut fra manifestet), og Python-kode utenfor skriptene en workflow kjører.
Lisensen til en Hugging Face-modell CI-en din henter ved navn, vises som unknown: fremforge kontakter ikke Hugging Face, eller noen andre, for å slå den opp. En modell CI-en din henter som et OCI-artefakt gjennom avhengighetsproxyen, får lisensen fra artefaktet (se Hvor lisensene kommer fra).
ML-BOM
Last ned ML-BOM (CycloneDX) på siden, eller GET /ai/ml-bom, returnerer oversikten som et CycloneDX 1.6-dokument. Hver modellfil er en komponent av typen machine-learning-model med sha256, deklarert lisens (hvor den ble deklarert, er egenskapen fremforge:model:licence_from), arkitekturen som modelCard.modelParameters.modelArchitecture når headeren oppgir en, og format, vurdering, flater, størrelse, antall parametere og datatyper som fremforge:model:*-egenskaper. Bare fakta lest fra filen oppgis.
SBOM-ene CI-en din laster opp, endres ikke: de er filene dine. ML-BOM-en er et eget dokument.
Compliance-rapport
Compliance-rapporten har en del om AI-oversikt: antall modellfiler, filene policyen din blokkerer eller ville blokkert, filene med et avvist funn, modus for modellskanning, CI-ens modellhentinger uten fast revisjon, og filene per deklarert lisens. CSV-en lister hver modellfil. Delen dekker alltid hele organisasjonen, også i en rapport for ett repository.
Revisjonslogg
| Hendelse | Når |
|---|---|
security_policy.model_scan.updated | Modusen eller innstillingen for rammeverk-pickles ble endret |
security_policy.model_scan.dismissed | Et funn ble avvist, eller en avvisning fornyet |
security_policy.model_scan.dismissal_revoked | En avvisning ble tilbakekalt |
registry.pull.blocked med gate: model | En pull ble avvist av modellpolicyen |
En avvist pakkeopplasting eller container-pull står også i tilgangsloggen for registeret, med årsaken model_policy:<rule>. Tilgangsloggen dekker ikke Git LFS.
API
| Kall | Scope |
|---|---|
GET /_app/api/v1/orgs/{org}/security/model-policy | policy:read |
PUT /_app/api/v1/orgs/{org}/security/model-policy | policy:write |
GET /_app/api/v1/orgs/{org}/security/model-findings?status=open|dismissed|all | findings:read |
POST /_app/api/v1/orgs/{org}/security/model-findings/{sha256}/dismiss | policy:write |
DELETE /_app/api/v1/orgs/{org}/security/model-findings/{sha256}/dismissal | policy: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-bom | components:read |
GET /_app/api/v1/orgs/{org}/ai/references?tool=&unpinned=true&repository=&model= | components:read |
PUT erstatter hele policyen: et felt du utelater, får standardverdien.
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Å avvise krever policy:write, ikke findings:write, fordi en avvist fil slipper gjennom enforce. Runner-tokenet til en CI-jobb har det aldri.
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>/dismissSe API-referansen for formen på svarene.
Hva som ikke dekkes
- Filer lagt ved issues, pull requests og releaser, og pakkeopplastinger der bodyen inneholder mer enn filen (PyPI, NuGet og andre multipart-opplastinger). Disse skannes for skadevare som før.
- Modeller i de vanlige Git-objektene i repositoryene dine. Store modellfiler hører hjemme i Git LFS.
- Å laste eller kjøre en modell, og å finne en bakdør i vektene. Ingen skanner kan skille en forgiftet vekt fra en normal.