content addressingはprovenanceではない
content-addressed artifactは強い整合性検証を可能にするが、それだけでsoftwareの由来を証明するわけではない。
Nixのstore pathは通常content-addressedではない で見たように、Nixのcontent-addressed store objectではactual contentからstore pathを計算できる。そのため、期待するcontent addressが既知であれば、取得元を全面的に信頼せずとも「受け取ったobjectが期待したcontentか」を検証できる。
しかし、ここで検証しているのは contentとaddressの対応 である。
悪意あるbinaryにも正しいSHA-256は存在する。攻撃者が作ったartifactをcontent-addressed storeへ入れれば、そのartifactにはその内容に対応した正当なaddressが付く。したがってcontent addressingからは、次のことは直接分からない。
- どのsource revisionから作られたか
- どのbuild instructionを使ったか
- どのbuilder/CIが作ったか
- dependencyやbuild environmentは何だったか
- project maintainerがそのartifactをreleaseしたのか
これらは checksum・signature・provenanceは別の保証をする でいうsignatureやprovenance側の問いである。
SLSA Build Provenanceは、artifactをbuild processとsource/inputへ結び付けるため、builder、build definition、resolved dependencies等を記録する。content digestはprovenance内でartifactを特定するためにも使えるが、digestそのものがprovenanceになるわけではない。
この違いはbinary cacheのtrustを考えると分かりやすい。binary cacheの公開鍵を追加することはbuilderを信頼することに近い のinput-addressed Nix objectでは、cache signerに「このstore pathのbuild resultはこれだ」と信頼を置く必要がある。一方、content-addressed objectならbytesの一致確認についてはcache signerへの依存を減らせる。しかし「なぜそのcontent addressを期待するのか」という上位metadataやbuild provenanceのtrustは残る。
したがってcontent addressingの価値は、artifact transfer/storage層のtrustを小さくできることにある。CDNやmirrorが正しいbytesを返したかはaddressで確認できる。一方でproducer/build pipelineのtrustまで消えるわけではない。
これはOCI image digest、Git object ID、CAS型build cache等にも共通する考え方である。content addressを導入すると「storageを信用しなくてよい」と言える場合はあるが、「software supply chainを信用しなくてよい」とまでは言えない。
またcontent addressはfreshnessも表さない。古い脆弱なartifactのdigestも永久に正しいままである。そのため 署名検証だけではrollback・freeze attackを防げない の問題も別に残る。
まとめると、content addressingが答えるのは主に what bytes? であり、provenanceが答えるのは where/how did these bytes come from? である。この二つを分離すると、package managerやbinary cacheのsecurity modelを過大評価しにくくなる。