slsa-framework / slsa

Supply-chain Levels for Software Artifacts
https://slsa.dev
Other
1.55k stars 225 forks source link

Could npm use VSAs instead of a custom 'publish' attestation? #801

Open TomHennen opened 1 year ago

TomHennen commented 1 year ago

npm has a custom publish attestation as a part of implementing this RFC.

I wonder if it would be possible to use a VSA instead? Perhaps with some tweaks to the spec?

My understanding is that the publish attestation is meant to say "the npm registry allowed this package" which is very similar to what the VSA is trying to get across. There may be some concern around npm not wanting to make an assertion about something's SLSA level, in which case I wonder if it would be helpful to add a SLSA_LEVEL_UNEVALUATED for the verifiedLevels field?

@feelepxyz, @laurentsimon, @joshuagl WDYT?

joshuagl commented 1 year ago

Thanks for filing this Tom! It would certainly be nice if we can standardise on fewer attestations where possible.

It might be useful to sketch out what an npm VSA would look like in this issue? cc @kommendorkapten

"_type": "https://in-toto.io/Statement/v1",
"subject": [{
  "name": "pkg:npm/@scope/package-foo@1.4.3",
  "digest": {"sha512": "41o0P/CEffYGDqvo2pHQXRBOfFOxvYY3WkwkQTy..."}
}],

// Predicate
"predicateType": "https://slsa.dev/verification_summary/v1-rc2",
"predicate": {
  "verifier": {
    "id": "https://registry.npmjs.org"
  },
  "timeVerified": "1985-04-12T23:20:50.52Z",
  "resourceUri": "pkg:npm/@scope/package-foo@1.4.3",
  "policy": {
    // global policy of checks npm performs prior to admitting a package
    "uri": "https://github.com/npm/package-acceptance.policy", 
    "digest": {"sha256": "1234..."}
  },
  "inputAttestations": [
    {
      // uri of the npm SLSA provenance
      "uri": "https://example.com/provenances/example-1.2.3.tar.gz.intoto.jsonl", 
      "digest": {"sha256": "abcd..."}
    }
  ],
  "verificationResult": "PASSED",
  "verifiedLevels": ["SLSA_LEVEL_UNEVALUATED"],
  "slsaVersion": "1.0"
}
TomHennen commented 1 year ago

Oh yeah great!

     // TBD: what would an appropriate policy URI being if the artifact is not being verified?
     // Could be a URI describing the authn checks performed by the registry?

I think that we should consider that the artifact itself is verified, after all the registry did decide to admit it. I think it would be fine to reference some global policy though?

  "verificationResult": "UNVERIFIED",

Per the above point I think this should arguably just be PASSED as the registry did decide to admit the thing.

laurentsimon commented 1 year ago

Per the above point I think this should arguably just be PASSED as the registry did decide to admit the thing.

+1 I also think the verification status should be about the entire policy passing or failing, not just levels.

joshuagl commented 1 year ago
     // TBD: what would an appropriate policy URI being if the artifact is not being verified?
     // Could be a URI describing the authn checks performed by the registry?

I think that we should consider that the artifact itself is verified, after all the registry did decide to admit it. I think it would be fine to reference some global policy though?

That seems sane and inline with what I was thinking, a global/uniform policy which describes the checks npm makes before accepting a package into the registry. 👍

  "verificationResult": "UNVERIFIED",

Per the above point I think this should arguably just be PASSED as the registry did decide to admit the thing.

Good call.

I've updated the JSON snippet in my comment above https://github.com/slsa-framework/slsa/issues/801#issuecomment-1497776568

TomHennen commented 1 year ago

It's also conceivable that a registry would have custom policies for some packages and they could indicate that in the policy field, but it's certainly not required that each package have its own policy.

MarkLodato commented 1 year ago

In my mind these are two distinct concepts:

TomHennen commented 1 year ago

I think with the introduction of verifiedLevels as a list VSAs aren't restricted to describing if something just met SLSA expectations, they can describe much more than that.

Internally we're using it as a generic token that the artifact is approved. It seems like it could easily do the same thing for others? Are there any downsides to doing so?

MarkLodato commented 1 year ago

Sorry, I didn't mean to be overly SLSA specific. Rather, I was pointing out that "approved" is not the same as "published". Would it be confusing if we use the same format to represent these two different concepts?

laurentsimon commented 1 year ago

Something I'm realizing is that VSAs don't have a good naming convention on the resource-uri, and it's probably optional to verify the resource-uri during verification (unless the naming convention is clear). At least, in the VSA we internally generate, it's not always easy to make sense out of the resource-uri.

On the other hand, the main goal of the publish attestation is to enforce this mapping between provenance and package, so verification MUST check it.

That's one argument for not re-purposing the VSA, because having this difference means it will be non-obvious for users, and harder for us to build safe verification APIs.

TomHennen commented 1 year ago

Yeah I think each ecosystem would need to establish their own convention for resources in VSAs.

My weak suggestion for npm would be to use purls with the package name and version (but not hash which is already in the VSA). e.g. pkg:npm/foobar@12.3.1

laurentsimon commented 1 year ago

I created https://github.com/slsa-framework/slsa/issues/808 to improve guidance on purl construction in the VSA.

What I like about the npm publish attestation is that it always contains a version, which lets users prevent rollback attacks if they want to. (in slsa-verifier, we provide a --package-version option for it)

kommendorkapten commented 1 year ago

I believe that having an explicit publish attestation allows for a simpler mental model to reason about during verification, as pointed out the concepts are slightly different. Then a VSA could be created to signal that both the build provenance and the publish attestations has been verified by a given policy.

The registry does not perform a deep evaluation of the provenance, I would compare it to more like a smoke test, that all the provided digests and signatures are consistent. Future improvements could change this to e.g. verify that certain attributes of the provenance matches the expected ones.

On a related note, this was discussed last week during Sigstore's clients group meeting, and other ecosystems expressed in generalizing the publish attestations we use for npm. The current attestation is not strictly bound to npm, so I think it might actually work in a general sense. So my counter-ask would be how the SLSA team feel about owning the specification for a publish attestation?

TomHennen commented 1 year ago

So my counter-ask would be how the SLSA team feel about owning the specification for a publish attestation?

This would make sense to me. I'm not sure if it needs to be SLSA specific attestation, but it would certainly make sense as an in-toto attestation.

kommendorkapten commented 1 year ago

This would make sense to me. I'm not sure if it needs to be SLSA specific attestation, but it would certainly make sense as an in-toto attestation.

Agreed, most important is that we can share the predicate type across multiple ecosystems.