Gå til hovedinnhold

Transparenslogg for proveniens

fremforge signerer en provenienattestering for hvert artefakt som bygges på plattformen. En signatur beviser at attesteringen kom fra oss. Den beviser ikke i seg selv at vi ikke senere har byttet den ut med en annen – den samme nøkkelen ville signert erstatningen like overbevisende.

Transparensloggen tetter det hullet. Hver attestering føres inn i et Merkle-tre som bare kan utvides, publisert på log.frem.sh, og loggen signerer jevnlig et sjekkpunkt (checkpoint): en erklæring om treets størrelse og rothash på et gitt tidspunkt. Fordi treet bare kan utvides og hvert sjekkpunkt beviselig må bygge videre på det forrige, kan vi ikke fjerne eller endre en attestering i ettertid uten å lage et sjekkpunkt som motsier et som allerede er publisert.

Hva som står i loggen, og hva som ikke gjør det

Et blad er en digest, ikke en attestering. Hver oppføring er SHA-256 av en DSSE-konvolutt, og ingenting annet.

Dette er bevisst, og det er det som gjør at loggen kan være helt offentlig. Har du din egen konvolutt, kan du bevise at den står i loggen – hash bytene, hent et inklusjonsbevis og sjekk det mot et sjekkpunkt. Alle som ikke har konvolutten din, får bare vite at en verdi på 32 byte ble logget på en bestemt indeks. Navn på repositoryer, commit-SHA-er, artefaktnavn og byggetidspunkter forblir private.

Å publisere selve konvoluttene ville ikke tilført beviset ditt noe, men ville gjort hvert bygg hos hver kunde permanent mulig å kartlegge – i en struktur som per definisjon aldri kan slette noe.

Hva den beviser i dag, og hva den ikke beviser

Les dette før du stoler på den.

Et sjekkpunkt har fremforges signatur og én medsignatur fra et vitne.

Signaturen vår gjør loggen manipulasjonsavslørende: hvis du har et bevis og vi senere skriver om historikken, slutter beviset ditt å verifisere, og du kan påvise motsigelsen.

Vitnets medsignatur er det vår egen signatur aldri kan være – en tredjepart som nekter å medsignere to inkonsistente sjekkpunkter. Siden 16. september 2026 har hvert sjekkpunkt vært medsignert av witness.stagemole.eu, som drives av Mullvad VPN AB. Den har også et tidsstempel, noe et C2SP-sjekkpunkt ikke har noe felt for: uten det kan et utdatert, men gyldig signert sjekkpunkt ikke skilles fra et aktuelt.

Ett vitne er ikke et beslutningsdyktig flertall, og vi vil heller si det enn å la ordet «vitne» gjøre mer enn det kan. Én enkelt medsignatar gjør det dyrere å vise deg et annet tre enn alle andre ser; det gjør det ikke umulig, fordi den ikke kan oppdage samarbeid mellom loggen og dens eneste vitne. Operatøren beskriver også denne instansen som staging, ikke produksjon.

Verdt å vite hvis du vurderer uavhengighet: de eneste vitnene av produksjonskvalitet i EU – Glasklar Teknik, Mullvad VPN og Tillitis – har samme morselskap, Amagicom AB, noe deres egne vedlikeholdere publiserer. Å legge til flere av dem ville gitt tilgjengelighet, ikke uavhengighet. Vi kommer ikke til å beskrive den gruppen som uavhengige parter.

Tillitsroten publiserer den gjeldende listen under transparency_log.witnesses. fremforge attest-verify sjekker hver oppføring og rapporterer hvor mange den verifiserte.

En manglende medsignatur gjør nå at verifiseringen feiler.

Fordi tillitsroten oppgir et vitne, krever attest-verify minst én medsignatur for å verifisere. Hvis vitnet ikke kan nås når vi publiserer, går sjekkpunktet ut med bare vår signatur, og sjekken din feiler – vitnesjekken rapporterer 0/1 verified.

Det er tilsiktet oppførsel: et oppgitt vitne som stille er fraværende, er akkurat det tilfellet du vil få beskjed om. Men det betyr at en kjøring som feiler, ikke automatisk er bevis på manipulasjon. Les hvilken sjekk som feilet før du trekker en konklusjon, og se Endepunkter for å hente sjekkpunktet selv.

Endepunkter

StiInnhold
https://log.frem.sh/checkpointDet gjeldende signerte sjekkpunktet
https://log.frem.sh/tile/<level>/<index>Fliser (tiles) i Merkle-treet
https://log.frem.sh/tile/entries/<index>Oppføringsbunter (de loggede digestene)

Formatene er C2SP-fellesskapsstandardene tlog-checkpoint, signed-note og tlog-tiles – ikke en fremforge-oppfinnelse, så eksisterende verktøy fra tredjeparter kan lese dem.

Bekreft at attesteringen din er logget

Én kommando, og den krever ingen 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)

Den avslutter med en annen kode enn null hvis en sjekk feiler, så den kan brukes i CI som den er.

Et nylig utgitt artefakt står kanskje ikke i loggen før om noen minutter. Loggen tar inn oppføringer i en syklus på femten minutter, så en attestering kan være signert og publisert før den dukker opp i treet. attest-verify vil rapportere NOT LOGGED og avslutte med en annen kode enn null i det tidsrommet – med rette, fordi den ikke er der ennå. Kjør på nytt litt senere. Hvis artefaktet er eldre enn omtrent femten minutter og fortsatt gir NOT LOGGED, er det en reell feil som du bør ta opp med oss.

Hver hash og signatur beregnes på nytt på din maskin. Vi blir bare bedt om bytes: tillitsroten, sjekkpunktet, flisene. Ingenting i utdataene er en dom vi har gitt deg – og det er hele poenget, for et verifiseringsverktøy som spør den som verifiseres om alt er i orden, har ikke verifisert noe.

En .intoto.jsonl er JSON Lines: én konvolutt per artefakt, så en utgivelsesbunt har én per binærfil pluss SBOM-en. Alle sjekkes.

Ta vare på tilstandsfilen

attest-verify registrerer treet den så i ~/.config/fremforge/tlog-state.json (overstyr med --state=<path>), og ved neste kjøring sjekker den at det nye treet fortsatt inneholder det samme treet uendret. Dette er sjekken som ikke trenger noen tredjepart, og det er den som fanger opp en delt visning rettet mot akkurat deg – så kjør den mer enn én gang, fra et sted du tar vare på, og ikke slett filen for å bli kvitt en feil. Den flytter bevisst ikke det registrerte treet fremover når sjekken feiler, så en oppdaget omskriving forblir oppdaget ved hver senere kjøring.

Eller gjør det for hånd

Kommandoen er en bekvemmelighet, ikke en avhengighet. Hvis du heller ikke vil stole på binærfilen vår – en rimelig holdning til det ene verktøyet som har som jobb å mistro oss – bruker gjennomgangen nedenfor ikke annet enn curl, jq og sha256sum, og formatene er fellesskapsstandarder som tlog-tiles-klienter fra tredjeparter også leser.

Du trenger konvolutten <asset>.intoto.jsonl, som leveres sammen med artefaktet.

# 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.json

vkey har formen log.frem.sh+<keyhash>+<base64 key>. Del den bare ved de to første + – det siste feltet er base64 og inneholder selv +.

# 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/checkpoint

Et sjekkpunkt består av opphavet, trestørrelsen, rothashen i base64, en tom linje og én eller flere signaturlinjer som begynner med en lang tankestrek (—). Digesten din står i en av oppføringsbuntene under tile/entries/; posisjonen er bladindeksen, og flisene under tile/<level>/ gir inklusjonsbeviset fra det bladet til rothashen som sjekkpunktet forplikter seg til.

Enhver tlog-tiles-klient kan gjøre denne gjennomgangen for deg. Hvis du heller ikke vil kjøre en, er den nyttige egenskapen enklere og fortsatt verdt å sjekke: digesten din må stå der, og sjekkpunktets trestørrelse må bare noensinne vokse.

Bekreft at loggen ikke har skrevet om historikken

fremforge attest-verify gjør dette for deg på tvers av kjøringer – se Ta vare på tilstandsfilen over. For hånd:

Ta vare på alle sjekkpunkter du har sett. Hent senere et nyere, og be loggen om et konsistensbevis mellom de to størrelsene. Hvis det nyere treet ikke bygger videre på det eldre, kan beviset ikke lages – og en logg som ikke kan lage det, har skrevet om historikken.

Dette er sjekken som et vitne utfører kontinuerlig, og derfor betyr vitner mer enn noen enkelt verifisering du gjør for hånd.

Forholdet til de andre integritetsmekanismene

fremforge driver tre separate ting som er lette å blande sammen:

MekanismeDekkerHvor
RevisjonskjedeAdministrative handlinger i organisasjonen dinHashkjede per kunde, forankret i WORM-lagring
Nøkkelfri commit-signeringGit-commitsSelvhostet Fulcio + RFC3161-TSA, ingen Rekor
Denne loggenAttesteringer av byggeprovenienslog.frem.sh

De er uavhengige av hverandre. Særlig bruker nøkkelfri commit-signering fortsatt ingen transparenslogg – integritetsprimitiven der er RFC3161-tidsstempelet, som dokumentert i sikkerhetsoversikten. Denne loggen dekker bare provenienattesteringer.

Suverenitet

Loggen kjører på T Cloud Public i eu-de, signert med en Ed25519-nøkkel som fremforge har. Den er ikke Rekor og er ikke avhengig av sigstore.dev, noen USA-drevet logg eller et offentlig CDN utenfor EU.

Vitner er et bevisst unntak under utforming: verdien av et vitne er at det ikke er oss, så et vitne kan godt drives et annet sted. Et vitne ser bare sjekkpunkter – et opphav, en trestørrelse og en rothash – aldri repositoryene, artefaktene eller byggene dine. Alle vitner vi legger til, blir oppført i tillitsroten, så settet kan revideres i stedet for å tas for gitt.