Transparenslogg för provenance
fremforge signerar en provenance-attestering för varje artefakt som byggs på plattformen. En signatur bevisar att attesteringen kom från oss. Den bevisar inte i sig att vi inte senare har ersatt den med en annan, eftersom samma nyckel skulle signera ersättningen lika övertygande.
Transparensloggen täpper till det. Varje attestering förs in i ett
Merkle-träd som bara kan utökas och som publiceras på log.frem.sh, och loggen
signerar regelbundet en checkpoint: ett påstående om trädets storlek och rothash vid
en viss tidpunkt. Eftersom trädet bara kan utökas och varje checkpoint bevisligen
måste bygga vidare på den föregående, kan vi inte ta bort eller ändra en attestering
i efterhand utan att skapa en checkpoint som motsäger en som redan publicerats.
Vad som finns i loggen, och vad som inte gör det
Ett löv är en digest, inte en attestering. Varje post är SHA-256 av ett DSSE-kuvert, och ingenting annat.
Det är avsiktligt, och det är det som gör att loggen kan vara helt publik. Har du ditt eget kuvert kan du bevisa att det finns i loggen: hasha byten, hämta ett inkluderingsbevis och kontrollera det mot en checkpoint. Den som inte har ditt kuvert får bara veta att ett 32-bytevärde loggades vid något index. Repo-namn, commit-SHA:er, artefaktnamn och byggtider förblir privata.
Att publicera själva kuverten skulle inte tillföra ditt bevis något, men skulle göra varje bygge i varje tenant permanent uppräkningsbart, i en struktur som av konstruktion aldrig kan ta bort något.
Vad den bevisar i dag, och vad den inte bevisar
Läs det här innan du förlitar dig på den.
En checkpoint har fremforges signatur och en vittnes medsignatur.
Vår signatur gör loggen manipulationsevident: om du har ett bevis och vi senare skriver om historiken slutar ditt bevis att verifieras, och du kan påvisa motsägelsen.
Vittnets medsignatur är det som vår egen signatur aldrig kan vara: en tredje part
som vägrar att medsignera två motstridiga checkpoints. Sedan den 16 september 2026
är varje checkpoint medsignerad av witness.stagemole.eu, som drivs av Mullvad VPN
AB. Den har också en tidsstämpel, vilket en C2SP-checkpoint saknar fält för:
utan den går en inaktuell men giltigt signerad checkpoint inte att skilja från en
aktuell.
Ett vittne är inte ett kvorum, och vi säger hellre det än låter ordet “vittne” göra mer än det kan. En enda medsignerare höjer kostnaden för att visa dig ett annat träd än alla andra ser; den gör det inte omöjligt, eftersom den inte kan upptäcka samverkan mellan loggen och dess enda vittne. Operatören beskriver också den här instansen som staging snarare än produktion.
Bra att veta om du bedömer oberoende: de enda vittnen av produktionsklass i Europeiska unionen, Glasklar Teknik, Mullvad VPN och Tillitis, har samma moderbolag, Amagicom AB, vilket deras egna förvaltare publicerar. Att lägga till fler av dem skulle ge tillgänglighet, inte oberoende. Vi kommer inte att beskriva den gruppen som oberoende parter.
Förtroenderoten publicerar den aktuella listan i transparency_log.witnesses.
fremforge attest-verify kontrollerar varje post och rapporterar hur många den verifierade.
En saknad medsignatur gör nu att verifieringen misslyckas.
Eftersom förtroenderoten anger ett vittne kräver attest-verify minst en
medsignatur för att verifiera. Om vittnet inte går att nå när vi publicerar,
skickas checkpointen ut med bara vår signatur och din kontroll misslyckas:
vittneskontrollen rapporterar 0/1 verified.
Det är det avsedda beteendet: ett angivet vittne som tyst saknas är precis det fall du vill bli informerad om. Men det betyder att en misslyckad körning inte automatiskt är bevis på manipulation. Läs vilken kontroll som misslyckades innan du drar en slutsats, och se Endpoints för att hämta checkpointen själv.
Endpoints
| Sökväg | Innehåll |
|---|---|
https://log.frem.sh/checkpoint | Den aktuella signerade checkpointen |
https://log.frem.sh/tile/<level>/<index> | Tiles i Merkle-trädet |
https://log.frem.sh/tile/entries/<index> | Postbuntar (de loggade digesterna) |
Formaten är C2SP-gemenskapens standarder tlog-checkpoint, signed-note och tlog-tiles, inte en fremforge-uppfinning, så befintliga verktyg från tredje part kan läsa dem.
Verifiera att din attestering är loggad
Ett kommando, och det kräver inget fremforge-konto:
fremforge attest-verify <asset>.intoto.jsonl --human✓ envelope signatures 6/6 verify under fremforge-slsa-builder-v2
✓ checkpoint signature signed by log.frem.sh
✓ tiles hash to the checkpoint root
✓ every attestation is in the log
6/6 at leaf indices: fremforge-linux-x64@255, …
✓ append-only since last run
✓ 7/7 checks passed (computed on this machine — the server was not asked
for a verdict)Det avslutar med en kod skild från noll om någon kontroll misslyckas, så det kan läggas in i CI som det är.
attest-verify rapporterar då NOT LOGGED och avslutar med
en kod skild från noll under det fönstret, vilket är korrekt eftersom den inte finns där än. Kör igen
om en stund. Om artefakten är äldre än ungefär femton minuter och fortfarande rapporterar
NOT LOGGED är det ett verkligt fel som du bör ta upp med oss.Varje hash och signatur beräknas om på din maskin. Vi ombeds bara om byte: förtroenderoten, checkpointen, tilesen. Ingenting i utdata är ett utlåtande som vi gav dig, och det är hela poängen: ett verifieringsverktyg som frågar den part som verifieras om allt är i sin ordning har inte verifierat någonting.
En .intoto.jsonl är JSON Lines: ett kuvert per artefakt, så en release-bunt
innehåller ett per binärfil plus SBOM:en. Alla kontrolleras.
Behåll tillståndsfilen
attest-verify registrerar trädet den såg i ~/.config/fremforge/tlog-state.json
(ändra med --state=<path>) och kontrollerar vid nästa körning att det nya trädet fortfarande
innehåller det trädet oförändrat. Det här är kontrollen som inte kräver någon tredje part, och
det är den som fångar en delad vy som riktas just mot dig. Kör den därför
mer än en gång, från ett ställe du behåller, och ta inte bort filen för att bli av med ett
fel. Den flyttar avsiktligt inte fram det registrerade trädet när kontrollen
misslyckas, så en upptäckt omskrivning förblir upptäckt vid varje följande körning.
Eller gör det för hand
Kommandot är en bekvämlighet, inte ett beroende. Om du inte heller vill lita på
vår binärfil, vilket är en rimlig hållning för det verktyg vars uppgift är att
misstro oss, använder genomgången nedan inget annat än curl, jq och sha256sum, och
formaten är gemenskapsstandarder som även tlog-tiles-klienter från tredje part
läser.
Du behöver ditt kuvert <asset>.intoto.jsonl, som levereras tillsammans med
artefakten.
# 1. The log's public key, from the trust root.
curl -sSfL https://www.frem.sh/.well-known/slsa-trust-root.json -o trust-root.json
jq -r '.transparency_log.vkey' trust-root.jsonVkey har formen log.frem.sh+<keyhash>+<base64 key>. Dela den bara vid de
två första +: det sista fältet är base64 och innehåller själv +.
# 2. The digest of YOUR envelope. This is the leaf content.
#
# ONE LINE AT A TIME, AND INCLUDING ITS TRAILING NEWLINE — that is the unit
# the log commits to. Hashing the bundle as a whole finds nothing, which
# looks exactly like "your attestation was never logged".
head -c $(( $(head -1 <asset>.intoto.jsonl | wc -c) )) <asset>.intoto.jsonl | sha256sum# 3. The current checkpoint, and the entries the log has published.
curl -sSfL https://log.frem.sh/checkpointEn checkpoint består av ursprunget, trädets storlek, rothashen i base64, en tom rad
och en eller flera signaturrader som börjar med ett tankstreck (—). Din digest
finns i en av postbuntarna under tile/entries/; dess position är dess
lövindex, och tilesen under tile/<level>/ ger inkluderingsbeviset från
det lövet till den rothash som checkpointen binder sig till.
Vilken tlog-tiles-klient som helst kan göra den här genomgången åt dig. Om du hellre inte kör en sådan är den användbara egenskapen enklare och ändå värd att kontrollera: din digest måste finnas med, och checkpointens trädstorlek får bara växa.
Verifiera att loggen inte har skrivit om historiken
fremforge attest-verify gör det här åt dig mellan körningar, se Behåll tillståndsfilen
ovan. För hand:
Behåll varje checkpoint du har sett. Hämta senare en nyare och be loggen om ett konsistensbevis mellan de två storlekarna. Om det nyare trädet inte bygger vidare på det äldre kan beviset inte tas fram, och en logg som inte kan ta fram det har skrivit om historiken.
Det är den här kontrollen som ett vittne utför kontinuerligt, och därför betyder vittnen mer än någon enskild verifiering du gör för hand.
Förhållande till de andra integritetsmekanismerna
fremforge kör tre separata saker som är lätta att blanda ihop:
| Mekanism | Omfattar | Var |
|---|---|---|
| Granskningskedja | Administrativa åtgärder i din organisation | Hashkedja per tenant, WORM-förankrad |
| Nyckellös commit-signering | Git-commits | Egen Fulcio + RFC3161 TSA, ingen Rekor |
| Den här loggen | Provenance-attesteringar för byggen | log.frem.sh |
De är oberoende av varandra. I synnerhet använder nyckellös commit-signering fortfarande ingen transparenslogg; dess integritetsprimitiv är RFC3161-tidsstämpeln, som beskrivs i säkerhetsöversikten. Den här loggen omfattar endast provenance-attesteringar.
Suveränitet
Loggen körs på T Cloud Public i eu-de och signeras med en Ed25519-nyckel som
fremforge innehar. Den är inte Rekor och är inte beroende av sigstore.dev, någon
USA-driven logg eller ett publikt CDN utanför EU.
Vittnen är ett medvetet undantag under framväxt: värdet med ett vittne är att det inte är vi, så ett vittne kan mycket väl drivas någon annanstans. Ett vittne ser bara checkpoints, ett ursprung, en trädstorlek och en rothash, aldrig dina repon, dina artefakter eller dina byggen. Varje vittne vi lägger till listas i förtroenderoten, så att gruppen kan granskas i stället för att tas för given.