Zum Hauptinhalt springen

Paketrichtlinien

Eine Paketrichtlinie entscheidet Datei für Datei, ob ein Paket in der Registry deiner Organisation heruntergeladen werden darf. Sie deckt die Registry-Typen ab, die fremforge hostet: npm, Maven, PyPI, NuGet, Cargo, Go, Conda, CRAN, Debian, RPM, Helm und generische Pakete sowie Container-Images (siehe Container-Images). Jede Organisation hat eine Richtlinie, mit optionalen Einstellungen pro Pakettyp.

Die Durchsetzung ist seit dem 2026-10-11 eingeschaltet. Eine Richtlinie im Modus Durchsetzen lehnt die Downloads ab, die gegen sie verstoßen. Eine Richtlinie im Modus Schatten, dem Standard, erfasst sie weiterhin nur. Eine Datei, die bekannte Malware enthält, wird für jede Organisation abgelehnt, unabhängig vom Modus. Deine Bewertungen, die Ansicht Wäre blockiert worden und die Paketbefunde werden dir angezeigt. Siehe Was sich mit dem Start der Durchsetzung geändert hat.

Was eine Richtlinie prüft

Wenn eine Datei veröffentlicht wird, entpackt fremforge sie, listet die darin mitgelieferten Komponenten auf und liest die vom Paket selbst angegebene Lizenz (siehe SBOMs). Jede Komponente wird mit den OSV-Advisories abgeglichen, und das jeden Tag aufs Neue. Die Richtlinie wird gegen diese Ergebnisse ausgewertet, und die Bewertung wird für die Datei gespeichert: allow, warn oder block. Eine Änderung an der Richtlinie, einer Liste oder einer Ausnahme bewertet jede Datei sofort neu, ohne erneuten Scan.

Beim Download entscheidet die gespeicherte Bewertung. Das gilt für Downloads über die Registry-API (/api/packages/…, die jeder Paketmanager nutzt) und über die Weboberfläche. Paket-Metadaten, etwa ein npm-Packument oder ein PyPI Simple Index, werden nie gefiltert. Sobald die Durchsetzung eingeschaltet ist, erhält ein Resolver, der eine blockierte Version anfragt, für diese Datei 403; er wird nicht auf eine andere Version umgelenkt.

Schwachstellen

EinstellungBedeutung
vuln_min_severityBlockiert eine Datei mit einer offenen Advisory ab diesem Schweregrad: low, medium, high oder critical.
vuln_min_cvssBlockiert ab diesem CVSS-Basiswert (0–10). Der Wert wird aus dem CVSS-Vektor der Advisory berechnet.
vuln_require_fix_availableZählt nur Advisories, für die es eine behobene Version gibt.
vuln_min_epssZählt nur Advisories, deren EPSS-Wahrscheinlichkeit mindestens diesen Wert erreicht (0–1). Eine Advisory ohne EPSS-Wert zählt nicht.

Die Schwachstellenregel ist nur eingeschaltet, wenn ein Schwellenwert für den Schweregrad oder für CVSS gesetzt ist. Sind beide gesetzt, zählt eine Advisory, die einen der beiden erreicht.

Lizenzen

Lizenzen sind SPDX-Kennungen und werden sowohl gegen die angegebene Lizenz als auch gegen die in mitgelieferten Komponenten erkannten Lizenzen geprüft.

Die Lizenzlisten werden auf der Seite Lizenzrichtlinie festgelegt, ein Regelsatz für Pull Requests und Downloads. Die Seite Paketrichtlinien verlinkt dorthin. Die folgenden Felder sind die Download-Seite dieser Richtlinie, und PUT /orgs/{org}/package-policy akzeptiert sie weiterhin.

EinstellungBedeutung
licence_allowWenn nicht leer, sind nur diese Lizenzen erlaubt.
licence_denyDiese Lizenzen blockieren.
licence_warnDiese Lizenzen lösen eine Warnung aus.
licence_unknown_actionWas passiert, wenn eine Lizenz kein gültiger SPDX-Ausdruck ist oder fehlt: allow, warn oder block.
licence_multiple_modeFür einen Ausdruck mit mehreren Lizenzen (MIT OR GPL-3.0-only): any_allowed besteht, wenn eine davon erlaubt ist, all_allowed verlangt alle.

Ausdrücke werden pro Operand ausgewertet. OR besteht, wenn irgendein Operand erlaubt ist, AND verlangt jeden Operanden, und X WITH exception wird als X ausgewertet.

Zulassungs- und Sperrlisten

Eine Listenregel nennt einen Pakettyp (oder jeden Typ), ein Namensmuster (Platzhalter * und ?, zum Beispiel @acme/* oder org.apache.logging.log4j:log4j-core) und optional einen Versionsbereich in vers:-Syntax, zum Beispiel vers:maven/<2.17.1. Bereiche folgen den Versionsregeln des jeweiligen Ökosystems für npm, Cargo und Go (Semver), PyPI (PEP 440), Maven und NuGet.

  • match_target: package trifft auf das Paket zu, das du veröffentlicht hast.
  • match_target: component trifft auf eine darin mitgelieferte Komponente zu.

Eine deny-Regel blockiert. Eine allow-Regel für ein Paket lässt es an den Regeln für Schwachstellen, Lizenzen und Alter vorbei, und eine allow-Regel für eine Komponente nimmt diese Komponente von den Regeln für Schwachstellen und Lizenzen aus. Allow-Regeln heben nie bekannte Malware oder eine deny-Regel auf. Eine Regel kann ein Ablaufdatum tragen.

Mindestalter

min_age_hours hält Dateien zurück, die vor weniger als so vielen Stunden veröffentlicht wurden, optional nur für die Typen in age_types. Das Alter wird im Moment des Downloads bestimmt, sodass eine Datei herunterladbar wird, sobald sie alt genug ist. Das Speichern des Release-Alters der Organisation setzt es auf entsprechend viele Tage (0 schaltet es aus); ein Typ mit eigenem Mindestalter in type_overrides behält dieses.

Eine Version, die eine bekanntermaßen ausgenutzte Schwachstelle behebt (eine CVE, die in der EU Vulnerability Database der ENISA oder im KEV-Katalog der CISA geführt wird), wird nicht zurückgehalten: Eine Korrektur für eine Schwachstelle, die tatsächlich ausgenutzt wird, soll nicht warten. Die Altersregel erscheint trotzdem in der Entscheidung, als aufgehoben markiert mit der CVE, für die sie aufgehoben wurde, sodass die Aufhebung in der Bewertung, im Audit-Log und im SIEM sichtbar ist. Eine Korrektur für eine CVE, die nicht als ausgenutzt bekannt ist, wartet wie gewohnt.

Immer aktiv

Zwei Prüfungen laufen unabhängig davon, was die Richtlinie sagt, auch im Modus Aus:

  • Bekannte Malware. Eine Datei, die ein Paket enthält, das in einer OSV-Advisory MAL-* geführt wird, wird in jedem Modus mit 403 abgelehnt, auch in Schatten und Aus. Um eine einzelne Datei durchzulassen, braucht es eine genehmigte Ausnahme für die Regel malware. Siehe Schädliche Pakete.
  • Namenskollision. Eine Advisory, die den Namen und die Version deines eigenen Pakets nennt, meist weil ein öffentliches Paket denselben Namen trägt, erzeugt eine Warnung. Sie blockiert nie.

Container-Images

Ein Container-Image wird pro Manifest-Digest gegen dieselben Regeln ausgewertet, mit den eigenen Eingaben des Images:

  • Schwachstellen sind die CVE-Befunde des Container-Image-Scannings für diesen Digest (oder seinen Tag), mit Schweregrad und CVSS-Wert. Image-Befunde haben keinen EPSS-Wert, daher zählt eine Richtlinie mit gesetztem vuln_min_epss sie nicht. Ein verworfener Befund zählt nicht.
  • Malware ist ein offener Befund zu schädlichen Paketen für diesen Digest.
  • Lizenzen sind die, die der Image-Scan für die Pakete im Image meldet. Ein Paket ohne Lizenz zählt als unbekannt.
  • Zulassungs- und Sperrlisten treffen auf das Image als Typ container (sein Name und Tag) und auf die Pakete darin als Komponenten zu.
  • Mindestalter zählt ab dem Push des Tags, wenn container in age_types steht (oder age_types leer ist).

Das Image wird beim Pull geprüft (docker pull oder jeder Client, der /v2/…/manifests/… liest), für jedes Manifest, das der Pull ausliefert, einschließlich jeder Plattform eines Multi-Plattform-Images. Images laufen nur im Schattenmodus: Ein Pull, der gegen die Richtlinie verstößt, wird unter Wäre blockiert worden erfasst und nie abgelehnt, egal welchen Modus du wählst. Image-Befunde werden mindestens alle 12 Stunden neu bewertet, und sofort, wenn du die Richtlinie, eine Liste oder eine Ausnahme änderst.

Das ist unabhängig von den bestehenden Pull-Sperren für Images, die unverändert bleiben: Die Einstellung block_pull des Container-Image-Scannings und die Sperre für schädliche Pakete lehnen Pulls schon heute ab.

Signaturen

signature_requirement prüft die Signaturen von npm-Paketen, die deine Organisation über den Abhängigkeits-Proxy von fremforge von npmjs.org bezieht, sobald der Abhängigkeits-Proxy für deine Organisation verfügbar ist, und zwar bevor der Tarball ausgeliefert wird:

  • die Registry-Signatur, die npmjs.org über jede Version erstellt (name@version:integrity), geprüft gegen die von npm veröffentlichten Registry-Schlüssel;
  • die Build-Provenienz, wenn die Version eine hat: eine mit Sigstore signierte SLSA-Attestierung, offline gegen den öffentlichen Sigstore-Trust-Root geprüft und an den SHA-512 des Tarballs gebunden.
EinstellungBedeutung
offNicht geprüft. Der Standard.
if_presentEine vorhandene Signatur oder Provenienz muss gültig sein. Eine Version ohne besteht.
requireWie if_present, und eine Version muss eine gültige Signatur tragen (oder, wenn Signierer eingetragen sind, vertrauenswürdige Provenienz).

signature_identities listet die Build-Identitäten auf, denen du vertraust, jeweils ein OIDC-issuer und eine subject_regex, auf die das gesamte Zertifikats-Subject passen muss. Ist mindestens eine eingetragen, zählt nur Provenienz von einer davon; eine Registry-Signatur allein nicht, denn sie belegt, was npmjs.org ausgeliefert hat, nicht, wer es gebaut hat. Für Pakete, die mit GitHub Actions in einer Organisation gebaut werden:

"signature_requirement": "require",
"signature_identities": [
  { "issuer": "https://token.actions.githubusercontent.com",
    "subject_regex": "https://github\\.com/sigstore/.+" }
]

Wie jede Regel folgt sie dem Modus der Richtlinie. Eine Version, die durchfällt, wird mit der Regel signature und einem Grund wie no provenance from a trusted identity oder the registry signature does not verify erfasst. Eine genehmigte Ausnahme mit der Regel signature lässt sie durch.

Was nicht geprüft wird: Pakete, die auf frem.sh veröffentlicht wurden (die Registry speichert für sie keine npm-Signatur und keine Provenienz, daher gilt die Regel für sie überhaupt nicht), und alle anderen Pakettypen. Maven-Signaturen (.asc) und NuGet-Signaturen werden nicht geprüft.

Herabgestufte Provenienz

provenance_downgrade erkennt eine Version, deren Build-Provenienz schwächer ist als die der vorigen Version. Das ist die typische Spur eines Releases, das von einem Laptop oder mit einem gestohlenen Token veröffentlicht wurde, nachdem die früheren Releases aus der CI kamen. Es nutzt dieselben geprüften Fakten wie die Signaturen und gilt daher für npm-Pakete, die über den Abhängigkeits-Proxy von npmjs.org bezogen werden.

Die vorige Version ist die höchste niedrigere Version, die früher veröffentlicht wurde. Ein Backport auf einer älteren Linie, etwa eine Sicherheitskorrektur 4.5.x, die nach 5.4.x erscheint, wird also mit dem vorigen Release dieser Linie verglichen, nicht mit dem neuesten. Ältere Linien werden oft noch ohne Provenienz gebaut.

Eine Version gilt als Herabstufung, wenn die vorige Version Build-Provenienz hatte und diese Version:

  • gar keine Provenienz hat;
  • Provenienz hat, die nicht verifiziert werden kann; oder
  • von einem anderen Signierer gebaut wurde: einem anderen OIDC-Aussteller, Quell-Repository oder Build-Workflow, oder auf einem selbst gehosteten Runner, wo die vorige Version auf einem gehosteten lief. Diese Angaben werden aus dem geprüften Sigstore-Zertifikat gelesen. Ein neuer Tag desselben Workflows ist derselbe Signierer.

Die erste Version eines Pakets und eine Version, deren Vorgänger keine Provenienz hatte, bestehen immer. Diese Regel vergleicht Versionen. Um Provenienz für jede Version zu verlangen, nutze signature_requirement.

EinstellungBedeutung
offNicht geprüft. Der Standard.
warnEine Herabstufung wird als Warnung erfasst; die Version wird ausgeliefert.
blockEine Herabstufung blockiert die Version. Wie bei jeder Regel entscheidet der Modus der Richtlinie: enforce lehnt den Download ab, shadow erfasst ihn nur.
"provenance_downgrade": "block"

In der Konsole findest du sie unter Richtlinien › Paketrichtlinien › Signaturen. Mit Terraform ist es das Argument provenance_downgrade von fremforge_package_signature_policy. Sie lässt sich auch für einen einzelnen Pakettyp in type_overrides setzen.

Eine Version, die durchfällt, wird mit der Regel provenance_downgrade und einem Grund erfasst, der die vorige Version nennt, zum Beispiel 2.4.1 has no build provenance, but the previous version 2.4.0 had oder ... built by a different signer than the previous version 2.4.0: source repository https://github.com/acme/lib -> https://github.com/fork/lib. Eine genehmigte Ausnahme mit der Regel signature und dem Selektor provenance_downgrade nimmt nur diese Regel aus. Eine Ausnahme mit der Regel signature ohne Selektor nimmt beide Signaturregeln aus.

Wo sie noch nicht gilt:

ÖkosystemWarum
PyPIPyPI veröffentlicht Attestierungen nach PEP 740, aber fremforge prüft sie noch nicht.
Maven Central, RubyGemsSignieren mit Sigstore ist upstream optional und wird vom Proxy nicht geprüft.
Cargo, Go, NuGet, Composer, Helm, conda, Debian, RPM, Terraform-ModuleUpstream gibt es keine Build-Provenienz pro Version. Signaturen von Repositorys oder Prüfsummen-Datenbanken belegen die Integrität, nicht, wer eine Version gebaut hat.
Auf frem.sh veröffentlichte PaketeFür sie wird keine Provenienz erfasst.

Auch die Lockfile-Prüfung des Proxys und seine Filterung von Paket-Metadaten wenden sie nicht an; bewertet wird beim Download eines Tarballs.

Einstellungen pro Typ

type_overrides setzt jede der obigen Regeln für einen Pakettyp anders, zum Beispiel eine strengere Lizenzliste für npm. "enabled": false schaltet die Richtlinie für diesen Typ aus, abgesehen von der Malware-Prüfung.

Modi

ModusWas passiert
offNur bekannte Malware und Namenskollisionen werden geprüft.
shadowJede Regel wird ausgewertet. Nichts wird abgelehnt, und jeder Download, der abgelehnt worden wäre, wird erfasst. Das ist der Standard.
enforceEin Download, der gegen die Richtlinie verstößt, wird mit 403 abgelehnt. Die Antwort nennt die zutreffenden Regeln und verlinkt auf die Seite der Richtlinie.

pending_action legt fest, was mit einer Datei passiert, deren Bewertung noch nicht abgeschlossen ist, etwa einer Datei, die vor Sekunden veröffentlicht wurde. allow (der Standard) lässt sie durch. refuse antwortet mit 503 und Retry-After, nur im Modus enforce.

Ausnahmen

Eine Ausnahme lässt ein Paket für begrenzte Zeit an einer Regel vorbei. Sie braucht eine zweite Person: Die antragstellende Person kann ihren eigenen Antrag nicht genehmigen, und die genehmigende Person muss Owner der Organisation sein oder auf der Genehmigungsliste der Organisation stehen.

Eine Ausnahme hat:

  • einen Geltungsbereich: eine Datei, einen Versionsbereich eines Pakets, jede Version eines Pakets oder eine mitgelieferte Komponente (per purl);
  • eine Regel: vuln, licence, age, deny_list, name_clash oder malware, optional eingeschränkt auf eine Advisory-ID oder eine SPDX-Lizenz;
  • eine Begründung;
  • ein Ablaufdatum höchstens 366 Tage in der Zukunft. Es ist Pflicht.

Eine Ausnahme wird beantragt und dann genehmigt oder abgelehnt. Eine genehmigte Ausnahme kann jederzeit widerrufen werden und wird bei ihrem Ablauf automatisch widerrufen. Jeder Schritt wird ins Audit-Log geschrieben (package_policy.exception.*).

Ausnahmen von der Paketrichtlinie teilen sich Warteschlange, API und Einstellungen mit Ausnahmen für Befunde: siehe Ausnahmen, wo auch das Genehmigungs-Team, die Obergrenze für das Ablaufdatum und der automatische Widerruf beschrieben sind.

Die Ansicht „Wäre blockiert worden"

Öffne die Admin-Seiten deiner Organisation unter Sicherheit › Richtlinien › Paketrichtlinien. Die Seite hat vier Ansichten:

  • Richtlinie legt den Modus und die Regeln fest und zeigt die aktuellen Bewertungen deiner veröffentlichten Dateien. Um zu sehen, was neue Einstellungen blockieren würden, bevor du sie speicherst, nutze den Testlauf in der API (unten).
  • Zulassungs- und Sperrlisten enthält die Listenregeln.
  • Ausnahmen zeigt Anträge, die Genehmigungswarteschlange und den Verlauf. Bei deinen eigenen Anträgen fehlt die Schaltfläche Freigeben.
  • Wäre blockiert worden listet die Downloads der letzten 14 Tage auf, die die Richtlinie abgelehnt hat oder im Schattenmodus abgelehnt hätte: eine Zeile pro Datei, Regel, Nutzer und Tag, mit der Zahl der Downloads. Das ist der Nachweis, den du prüfen solltest, bevor du eine Organisation auf Durchsetzen umstellst.

Auf diese Weise abgelehnte oder erfasste Downloads stehen auch im Zugriffsprotokoll der Registry mit der Entscheidung would_block oder blocked.

Was sich mit dem Start der Durchsetzung geändert hat

Am 2026-10-11:

  • Der Modus Durchsetzen lehnt ab. Vorher erfasste Durchsetzen dieselben Ergebnisse wie Schatten. Stand deine Richtlinie bereits auf Durchsetzen, werden Downloads, die gegen sie verstoßen, jetzt abgelehnt. Prüfe zuerst Wäre blockiert worden, oder stelle auf Schatten um, bis du das getan hast.
  • Bekannte Malware wird für alle abgelehnt. Vorher wurde sie nur erfasst.
  • Deine Ergebnisse werden angezeigt. Bewertungen von Dateien, Wäre blockiert worden, Paketbefunde sowie die APIs für Bewertung, Testlauf, Entscheidungen und Befunde antworten jetzt für deine Organisation. Seitdem erzeugen Paketbefunde und Richtlinienentscheidungen auch Ereignisse im Audit-Log (und damit SIEM- und Webhook-Ereignisse), Sicherheitswarnungen per E-Mail, Zeilen im wöchentlichen Digest und Zeilen im Tab Malware, für Änderungen ab diesem Tag. Wäre blockiert worden listet auch die Downloads auf, die in den 14 Tagen davor erfasst wurden.
  • Container-Images sind unverändert: weiterhin nur Schattenmodus, siehe Container-Images.

API

Nutze ein Token mit policy:read oder policy:write (findings:read für Paketbefunde). Basis-URL: https://frem.sh/_app/api/v1. Die vollständigen Request- und Response-Strukturen stehen in der API-Referenz.

Methode und PfadWas es tut
GET /orgs/{org}/package-policyDie Richtlinie, mit ihrer version.
PUT /orgs/{org}/package-policyDie Richtlinie ändern. Sende die version, die du gelesen hast; eine veraltete Version erhält 409 policy-version-conflict.
GET, POST /orgs/{org}/package-policy/rulesZulassungs- und Sperrregeln auflisten oder hinzufügen. Eine Regel braucht list, name_glob und reason.
DELETE /orgs/{org}/package-policy/rules/{id}Eine Regel entfernen.
GET, PUT /orgs/{org}/package-policy/approversDie benannten genehmigenden Personen neben den Ownern. PUT nimmt {"logins": [...]}.
GET, POST /orgs/{org}/package-policy/exceptionsAusnahmen auflisten (Filter mit status) oder eine beantragen.
GET /orgs/{org}/package-policy/exceptions/{id}Eine Ausnahme.
POST /orgs/{org}/package-policy/exceptions/{id}/approveGenehmigen. Abgelehnt mit self-approve für die antragstellende Person und mit not-an-approver für alle anderen, die nicht genehmigen dürfen.
POST /orgs/{org}/package-policy/exceptions/{id}/rejectAblehnen.
DELETE /orgs/{org}/package-policy/exceptions/{id}Widerrufen.
GET /orgs/{org}/package-policy/evaluation?type=&name=&version=Die Bewertung jeder Datei einer Paketversion, mit Gründen, Befunden und Lizenzen.
POST /orgs/{org}/package-policy/evaluateTestlauf. Mit {"policy": {...}} meldet er, was jede aktuelle Datei unter diesen Einstellungen bekäme, und schreibt nichts. Mit {"components": [{"purl": "...", "licence": "..."}]} bewertet er eine Liste von Komponenten, zum Beispiel aus einem CI-Schritt, bevor du veröffentlichst.
GET /orgs/{org}/package-policy/decisionsDie Daten für Wäre blockiert worden: days (1–90, Standard 14), decision (blocked, would_block oder pending_refused).
GET /orgs/{org}/findings/packagesAdvisory-Befunde zu Registry-Paketen. Blättere mit cursor (der next_cursor der vorigen Seite) und limit (bis zu 500).

Eine Richtlinie im Schattenmodus, die hohe und kritische Advisories sowie AGPL blockiert und neue npm-Releases 24 Stunden lang zurückhält:

TOKEN=ffp_...
ORG=acme
V=$(curl -sS -H "Authorization: Bearer $TOKEN" \
  "https://frem.sh/_app/api/v1/orgs/$ORG/package-policy" | jq .version)

curl -sS -X PUT -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  "https://frem.sh/_app/api/v1/orgs/$ORG/package-policy" \
  -d "{\"version\": $V, \"mode\": \"shadow\", \"vuln_min_severity\": \"high\",
       \"licence_deny\": [\"AGPL-3.0-only\", \"AGPL-3.0-or-later\"],
       \"min_age_hours\": 24, \"age_types\": [\"npm\"]}"

log4j-core unter 2.17.1 sperren, wo immer es mitgeliefert wird:

curl -sS -X POST -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  "https://frem.sh/_app/api/v1/orgs/$ORG/package-policy/rules" \
  -d '{"list": "deny", "pkg_type": "maven", "name_glob": "org.apache.logging.log4j:log4j-core",
       "version_range": "vers:maven/<2.17.1", "match_target": "component",
       "reason": "Log4Shell"}'

Audit

Jede Änderung steht im Audit-Log: package_policy.updated (mit dem, was sich geändert hat), package_policy.rule.created und .deleted, package_policy.approvers.updated, die Ausnahme-Ereignisse und package_policy.verdict_changed, wenn eine Datei von allow in Richtung warn oder block wechselt. Ein abgelehnter oder ein Download, der abgelehnt worden wäre, wird als package_policy.download_blocked oder package_policy.download_would_block erfasst, einmal pro Datei, Regel, Nutzer und Tag.

Verwandte Themen