Hoppa till huvudinnehållet

fremforge CLI

fremforge CLI är en fristående binär som omsluter det offentliga REST API:t. Samma verb, samma behörighetsmodell, samma scopes. Distribueras enbart från PoP:ar i EU; inget npm-register, ingen Docker Hub, inget beroende av Sigstore Fulcio.

Supportperiod, säkerhetsuppdateringar och SBOM

Supportperiod5 år från lanseringsdatumet för varje minor-version. Det är supportperioden i den mening som avses i artikel 13.8 i Cyberresiliensförordningen (förordning (EU) 2024/2847), och den är knuten till den släppta versionen, inte till din prenumeration.
SäkerhetsrättningarKostnadsfria, alltid, och aldrig låsta bakom en plan. Rättningar levereras framåt som en ny release på samma URL:er, täckta av samma signerade SHA256SUMS. Kör du en ersatt version? Uppgradera för att få rättningen.
Rapportera en sårbarhetsecurity@frem.sh: samordnat avslöjande, detaljer på www.frem.sh/security.
SBOMCycloneDX JSON på cli.frem.sh/cli/SBOM.cdx.json, per version på cli.frem.sh/cli/v<version>/SBOM.cdx.json.
AvtalsvillkorAnvändarvillkoren §7.5: licens, garanti och ansvar specifikt för binären.

SBOM:en är kort, och det är hela poängen. CLI:t deklarerar noll npm-beroenden från tredje part. Det har två beroenden, båda våra egna: @fremverk/audit-chain, samma hashkedjekod som API:t självt kör (delad i stället för omimplementerad så att audit-verify inte kan glida isär från det den verifierar), och @fremforge/tlog-verify, som kontrollerar inkludering i transparensloggen för attest-verify. Inget av dem har egna beroenden; båda importerar bara Nodes inbyggda moduler, så hela ytan från tredje part i den levererade binären är Bun-körtiden som bäddas in vid kompileringen. Från v0.3.1 listar SBOM:en även de två förstapartspaketen, markerade som våra, så att den namnger varje komponent och inte bara den från tredje part.

SBOM:ens hash finns i SHA256SUMS, så den täcks av samma Ed25519-signatur som binärerna. Verifiera den på samma sätt (se §”Verifiera Ed25519-signaturen” nedan; det gäller varje fil som listas i manifestet, inte bara binärerna):

curl -fsSL https://cli.frem.sh/cli/SBOM.cdx.json -o SBOM.cdx.json
curl -fsSL https://trust.frem.sh/SHA256SUMS -o SHA256SUMS
grep SBOM.cdx.json SHA256SUMS | shasum -a 256 -c -

CLI:t är valfritt, med ett undantag. Varje åtgärd det utför finns tillgänglig via REST API:t, så om din policy är att inte köra leverantörers binärer förlorar du ingen funktionalitet på att avstå. Undantaget är audit-verify, som räknar om din granskningshashkedja på din egen dator. Det kan ett API inte göra åt dig, eftersom hela poängen med att räkna om en hashkedja är att inte lita på den part som har tagit fram den. De råa raderna tillhandahålls av GET /orgs/{org}/audit/chain, så du kan göra beräkningen i dina egna verktyg i stället; det du inte kan göra är att låta oss göra den och kalla resultatet för verifiering.

Installera

En rad (rekommenderas)

curl -sSfL https://cli.frem.sh/cli/install.sh | sh

Installationsprogrammet identifierar automatiskt ditt operativsystem (Linux eller macOS) och din arkitektur (arm64 eller x86_64), laddar ned motsvarande binär från https://cli.frem.sh/cli/, laddar ned den kanoniska SHA256SUMS från https://trust.frem.sh/ (en separat värd med en separat skrivbehörighet, så att ett intrång enbart på binärvärden inte kan förfalska en matchning), verifierar SHA-256 och installerar till ~/.local/bin/fremforge eller /usr/local/bin/fremforge.

Ändra installationsplatsen med FREMFORGE_INSTALL_DIR:

curl -sSfL https://cli.frem.sh/cli/install.sh | FREMFORGE_INSTALL_DIR=/opt/fremforge/bin sh

Lås en viss version:

curl -sSfL https://cli.frem.sh/cli/install.sh | FREMFORGE_VERSION=0.1.0 sh

Manuell nedladdning

Om du helst inte vill skicka ett fjärrskript direkt till sh går binärerna att nå direkt. Välj det par som passar:

OSArkitekturURL
macOSarm64https://cli.frem.sh/cli/fremforge-darwin-arm64
macOSx86_64https://cli.frem.sh/cli/fremforge-darwin-x64
Linuxarm64https://cli.frem.sh/cli/fremforge-linux-arm64
Linuxx86_64https://cli.frem.sh/cli/fremforge-linux-x64
Windowsx86_64https://cli.frem.sh/cli/fremforge-windows-x64.exe

Arkitektursuffixet är x64 (inte x86_64) och arm64; de motsvarar Buns --target-token. uname -m rapporterar x86_64 på Intel/AMD, så översätt det till x64 när du bygger URL:en för hand (installationsraden gör det åt dig).

Verifiera mot den kanoniska hashen på trust.frem.sh innan du kör binären:

# 0. Map uname -m's x86_64 to the published x64 token
arch=$(uname -m); [ "$arch" = x86_64 ] && arch=x64

# 1. Download the binary
curl -fsSL https://cli.frem.sh/cli/fremforge-$(uname -s | tr A-Z a-z)-$arch \
  -o fremforge

# 2. Download the canonical SHA256SUMS (separate host, separate credential)
curl -fsSL https://trust.frem.sh/SHA256SUMS -o SHA256SUMS

# 3. Verify
sha256sum --check --ignore-missing SHA256SUMS

# 4. Install
chmod +x fremforge
sudo install -m 0755 fremforge /usr/local/bin/fremforge

Verifiera Ed25519-signaturen (valfritt, rekommenderas)

Utöver SHA-256-matchningen signeras varje release som ett DSSE-inslaget in-toto-uttalande under samma förtroenderot som fremforges SLSA-byggproveniens. Verifieraren laddar ned den publika förtroenderoten från www.frem.sh/.well-known/slsa-trust-root.json och kontrollerar Ed25519-signaturen på bytena i SHA256SUMS.

Använd inte slsa-verifier verify-artifact. Det underkommandot saknar flaggan --trusted-root, och det kan varken läsa fremforges JSON-förtroenderot eller ett DSSE-kuvert med ren Ed25519; det förväntar sig ett paket i Sigstore-stil. Den här sidan visade tidigare ett sådant kommando; det hade aldrig kunnat köras. Verifiera direkt i stället, med verktyg som din distribution redan har.

SHA256SUMS.intoto.jsonl är JSON Lines: ett DSSE-kuvert per publicerad binär. Verifiera varje rad du bryr dig om.

# Pull the trust root and the signed envelopes
curl -fsSL https://www.frem.sh/.well-known/slsa-trust-root.json -o slsa-trust-root.json
curl -fsSL https://trust.frem.sh/SHA256SUMS.intoto.jsonl -o SHA256SUMS.intoto.jsonl

# Extract the builder public key: v2, the active key since 2026-09-12. An envelope's
# .signatures[0].keyid names its key; one signed before 2026-09-12 needs ...-v1.
jq -r '.trusted_keys[] | select(.kid=="fremforge-slsa-builder-v2") | .pem' \
  slsa-trust-root.json > builder.pub

# Verify every envelope: rebuild the DSSE pre-authentication encoding and check it
while read -r line; do
  pt=$(printf '%s' "$line" | jq -r .payloadType)
  printf '%s' "$line" | jq -r .payload | base64 -d > payload.bin
  printf '%s' "$line" | jq -r '.signatures[0].sig' | base64 -d > sig.bin
  { printf 'DSSEv1 %s %s %s ' "${#pt}" "$pt" "$(wc -c < payload.bin)"; cat payload.bin; } > pae.bin
  openssl pkeyutl -verify -pubin -inkey builder.pub -rawin -in pae.bin -sigfile sig.bin \
    && jq -r '.subject[] | .name + "  " + .digest.sha256' payload.bin
done < SHA256SUMS.intoto.jsonl

Varje verifierat kuvert skriver ut alla artefakter det täcker och den digest som fremforge signerade för var och en. Jämför den digesten med binären du laddade ned; det är den jämförelsen som är poängen, signaturen talar bara om att digesten kommer från oss.

Förtroenderoten är densamma som används för byggproveniens på artefakter som din runner producerar: samma Ed25519-nyckel, samma builderId, samma verifieringsrecept. Vi anger ingen SLSA-nivå; säkerhetssidan förklarar varför.

Autentisering

CLI:t stöder tre sätt att ange inloggningsuppgifter, som avgörs i den här ordningen: flaggan --token=…, miljövariabeln FREMFORGE_TOKEN och sedan den sparade inloggningen i ~/.config/fremforge/auth.json.

Rekommenderas: inloggning i webbläsaren (inget att klistra in)

fremforge auth login

Öppnar webbläsaren mot frem.sh, du godkänner enheten, token hamnar i ~/.config/fremforge/auth.json (läge 600) och laddas sedan automatiskt vid varje anrop. Det är samma OAuth2 + PKCE-flöde som din git push redan använder, så om du återkallar token på frem.sh/user/settings/applications återkallas både git-åtkomsten och CLI-åtkomsten i ett steg.

fremforge auth status      # show current login + expiry
fremforge auth logout      # revoke + delete the local file

Token fungerar mot både fremforges REST API (/_app/api/v1/orgs/…) OCH Forgejos eget API (/api/v1/repos/…): Forgejo accepterar sina egna OAuth-bearer-token direkt, och fremforges API validerar dem via introspektion mot Forgejos /api/v1/user. Samma identitet, båda ytorna.

CI och skript: PAT

För icke-interaktiva sammanhang (CI-jobb, skript, agenter), skapa en PAT med avgränsade scopes. Enklast är att använda CLI:t självt när du väl har loggat in interaktivt en gång (fremforge auth tokens create --name=… --scopes=…; se Skapa en avgränsad PAT för CI), eller skapa en på https://frem.sh/user/settings/applications. Sedan:

export FREMFORGE_TOKEN='<your PAT>'
fremforge whoami

Ändra bas-URL:en med FREMFORGE_URL= (måste vara HTTPS); standard är https://frem.sh.

Kommandon

fremforge auth login                              Browser-based OAuth2+PKCE login.
fremforge auth logout                             Revoke + delete the stored token.
fremforge auth status                             Show current login + expiry.
fremforge whoami                                  Print the user the token authenticates as.
fremforge data-export start <slug>                Queue a full data export for the org.
fremforge data-export list <slug>                 List recent export jobs.
fremforge dependency-updates enable <slug>        Enable hosted Renovate for the org.
fremforge dependency-updates disable <slug>       Disable hosted Renovate for the org.
fremforge dependency-updates run-now <slug>       Trigger an out-of-cycle Renovate run (1/h cap).
fremforge audit-log <slug>                        Fetch the org audit-log slice.
                  [--since=DATE] [--actor=…] [--action=…] [--limit=N]
fremforge audit-verify <slug>                     RECOMPUTE the per-tenant audit hash chain
                  [--human] [--full]              locally, then cross-check our own verdict.
                                                  Exit 0=ok, 2=partial, 3=broken,
                                                  4=anchor_mismatch, 5=local ok but we
                                                  disagreed. --full walks from the chain
                                                  epoch instead of the latest anchor.
fremforge sbom <owner>/<repo> <tag>               Download a release SBOM.
                  [--format=spdx|cyclonedx]
fremforge runs <owner>/<repo>                     List recent CI runs (JSON; --human for a table).
                  [--limit=N] [--status=…] [--event=…]
fremforge runs logs <owner>/<repo> <run-id>       Fetch a run's logs (text/plain, all jobs).
fremforge auth tokens create                      Mint a scoped PAT (printed once).
                  --name=N --scopes=a,b [--ttl-days=N]
fremforge auth tokens list                        List your PATs (--human for a table).
fremforge auth tokens revoke <token-id>           Revoke a PAT.
fremforge findings <type> <slug>                  Security findings. type ∈ secrets |
                  [--status=…] [--repo=…]         dependencies | signed-commits | attestations.
fremforge secrets list <slug>                     List org Actions/CI secret names.
fremforge secrets set <slug> <NAME>               Set a secret (value via FREMFORGE_SECRET_VALUE).
fremforge secrets delete <slug> <NAME>            Delete a secret.
fremforge seats list <slug>                       List org members + seat usage.
fremforge seats add <slug> --email=E              Add a member (--username=, --full-name= optional).
fremforge seats remove <slug> <username>          Remove a member.
fremforge work start <org>/<repo>                 Declare work before the first push (Active work).
                  --title=TEXT [--intent=TEXT]    Prints the branch to create and related work.
                  [--areas=a,b] [--branch=NAME]
fremforge work list <org>/<repo>                  Who is building what in a repository.
                  [--area=AREA]
fremforge version                                 Print the CLI version.

Kör fremforge --help för den kanoniska referensen, eller lägg till --human på de kommandon som stöder det för utdata formaterad som tabell.

Exempel

Verifiera din granskningskedja själv (använd i CI)

audit-verify frågar inte oss om din granskningslogg är intakt. Det laddar ned de råa raderna, räknar om varje hash och varje länk på din dator, och jämför först därefter sitt resultat med vårt. Avslutskoden är ditt resultat, inte vårt påstående, och om de två inte stämmer överens rapporteras själva oenigheten och kommandot misslyckas.

Den skillnaden är skälet till att kommandot finns. Fram till augusti 2026 läste det fältet integrity_status ur ett API-svar och översatte det till en avslutskod, vilket innebar att den part som granskades räknade ut svaret och ”verifieringsverktyget” bara förde det vidare. Ingenting du kunde köra skulle ha upptäckt ett komprometterat eller oärligt API. Nu gör något det.

export FREMFORGE_TOKEN='<your PAT, audit:read scope>'

# Human-readable, for terminals
fremforge audit-verify acme --human

# Script-friendly. The exit code reflects the LOCAL walk:
#   0 = ok
#   2 = partial          — some of the chain could not be checked (see below)
#   3 = broken           — a row's content or its link does not match. Investigate.
#   4 = anchor_mismatch  — the WORM-anchored tip is not present in your chain
#   5 = we disagreed     — your walk was clean but our verdict was not
#   6 = bad signature    — the anchor's signature failed against our published key
fremforge audit-verify acme || {
  echo "audit verification failed with exit code $?"
  exit 1
}

# Walk the entire chain from its first row instead of just the tail since the
# last anchor. Slower and much larger; appropriate for a quarterly review.
fremforge audit-verify acme --full --human

Läs resultaten ärligt, eftersom ett verifieringsverktyg som överdriver sin egen förmåga är värre än inget alls:

  • partial är inte godkänt. Det betyder att trunkering har dolt en del av kedjan, så raderna utanför fönstret är overifierade. Vi rapporterar ok i det fallet, och CLI:t gör medvetet inte det.
  • Raderade och maskerade rader stämmer inte med sin hash, avsiktligt. GDPR-radering och rensningen av nyttolaster efter 90 dagar skriver om radernas innehåll i efterhand, så de raderna stämmer inte längre med sin egen hash. De räknas separat (tenant_erased_count, payload_redacted_count) och är inte manipulation. Deras länkar kontrolleras fortfarande.
  • WORM-ankaret är signerat, och CLI:t kontrollerar det mot en förtroenderot som det hämtar själv. audit-verify hämtar www.frem.sh/.well-known/slsa-trust-root.json direkt, aldrig en nyckel från API:t, verifierar Ed25519-DSSE-signaturen och bekräftar att kuvertet är bundet till just det här ankaret och inte till något annat. Avslutskod 6 betyder att signaturen kontrollerades och inte godkändes; behandla det som en incident. NOT CHECKED (avslutskoden oförändrad) betyder antingen att ankaret är äldre än signeringen (2026-08-04) eller att förtroenderoten inte gick att nå från din dator. Inget av det är ett fel, och CLI:t säger vilket det är.

För att göra samma sak utan binären, läs raderna från GET /orgs/{org}/audit/chain och hasha varje rads kanoniska JSON med nycklarna ordnade action, actor, created_at_iso, fields_json, prev_hash, tenant_id. Behåll fields_json byte för byte: tolka och serialisera inte om det, annars stämmer inte dina digester.

Se granskningskedjans integritet för hela garantin.

Dataexport med självbetjäning

# Kick off
fremforge data-export start acme | jq .

# Poll
fremforge data-export list acme | jq '.[] | {id, status, created_at}'

Se dataexport för artefaktformatet, lagringstiden och nedladdningsflödet med signerad URL.

Beroendeuppdateringar (hostad Renovate)

fremforge dependency-updates enable acme
fremforge dependency-updates run-now acme   # 1/h rate-limit applies

Se beroendeuppdateringar för vad som tas med och hur du avgränsar det per repo.

Nedladdning av SBOM

fremforge sbom acme/api v1.4.0 --format=spdx > sbom.spdx.json
fremforge sbom acme/api v1.4.0 --format=cyclonedx > sbom.cyclonedx.json

Utdrag ur granskningsloggen

fremforge audit-log acme --since=2026-05-01 --action=push-protection-override | jq .

CI-körningar och loggar

Lista de senaste körningarna och hämta sedan en körnings fullständiga loggar (alla jobb sammanslagna) via dess globala körnings-id:

# List the 20 most recent runs as a table
fremforge runs acme/api --human

# Script-friendly: grab the newest run id, then fetch its logs
run_id=$(fremforge runs acme/api --limit=1 | jq -r '.workflow_runs[0].id')
fremforge runs logs acme/api "$run_id"

# Tail just the failing step
fremforge runs logs acme/api "$run_id" | grep -iE "error|failed|exit code" | tail

<run-id> är det globala körnings-id som fremforge runs visar (fältet .workflow_runs[].id), inte körningsnumret per arbetsflöde i webbgränssnittets URL. Logg-endpointen returnerar text/plain med alla jobb i ett och samma svar; ingen nedladdning av artefakter per jobb behövs.

Skapa en avgränsad PAT för CI

Efter din första fremforge auth login kan du skapa undertoken med snäva scopes för CI utan att lämna terminalen. Token skrivs ut en gång, så spara den direkt:

fremforge auth tokens create --name=ci-readonly --scopes=findings:read,orgs:read --ttl-days=30 \
  | jq -r .token
fremforge auth tokens list --human
fremforge auth tokens revoke <token-id>

Du kan bara ge scopes som din egen token redan har, och jokertecknet (*) kan inte användas här.

Hantera CI-secrets

fremforge secrets list acme

# Pass the value via env (preferred — not in shell history or `ps`)
FREMFORGE_SECRET_VALUE="$(cat ./deploy-key)" fremforge secrets set acme DEPLOY_KEY

fremforge secrets delete acme OLD_TOKEN

Användare och medlemmar

fremforge seats list acme --human                       # cap + usage + roster
fremforge seats add acme --email=jane@acme.example --full-name="Jane Doe"
fremforge seats remove acme jane

Om du lägger till en medlem över det avtalade taket för antal användare får du 409 med en länk till faktureringen. Köp fler användare först.

Utdataformat

Som standard skriver varje kommando JSON till stdout, lämpligt för skript och pipes. Ange --human på de kommandon som stöder det (audit-verify, attest-verify, release verify, runs, auth tokens list, seats list och work) för en formaterad sammanfattning.

Uppdatera CLI:t

Installationsraden är idempotent: kör du den igen hämtas den senaste binären, kontrollsumman verifieras på nytt och den gamla binären skrivs över på plats:

curl -sSfL https://cli.frem.sh/cli/install.sh | sh

Om suveränitet

CLI:ts distributionsväg är helt EU-suverän:

  • Binärer: T Cloud Public OBS (eu-de, Magdeburg/Biere, Tyskland), bakom en Bunny-pull-zon som är begränsad till PoP:ar i EU.
  • SHA256SUMS + DSSE-kuvert: en separat OBS-bucket i T Cloud Public (trust.frem.sh) med en separat skrivbehörighet. Att binärvärden är skild från integritetsvärden betyder att ett intrång i den ena inte kan förfalska en matchning mot den andra.
  • Förtroenderot: en statisk JSON-fil som serveras från www.frem.sh (samma Bunny-routning enbart inom EU).
  • Inget beroende av npm-registret: registry.npmjs.com körs i AWS i USA; CLI:t rör det aldrig, varken vid installation eller användning.
  • Inget beroende av Docker Hub: av samma skäl.
  • Ingen Sigstore Fulcio/Rekor: Sigstores transparenslogg ligger i USA. fremforge kör en egen Ed25519-signerare och en statisk förtroenderot i stället för att vara beroende av Fulcio.

Underbiträden som berörs på installationsvägen listas i det offentliga registret över underbiträden och är samma som redan omfattar kundens personuppgifter enligt DPA:ns bilaga B.