slsa-framework / slsa

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

Relaxation of requirements on hermeticity and reproducibility of builds for specific use-cases #277

Open shaunmlowry opened 2 years ago

shaunmlowry commented 2 years ago

There are certain things we'd like to do as part of producing usable artifacts which are necessarily not executable in a hermetic context or easily reproducible, an example being authenticode signing of EXEs and DLLs on Windows systems. Authenticode signing is highly desirable from a security perspective as it plugs in to Windows' pre-existing native trust model and provides some level of protection from malicious code modification, but the process of creating an authenticode signature is neither hermetic nor reproducible as it requires an authenticated timestamp from a trusted external source. It's not hermetic as it requires network access to a secure timestamp server and it's not reproducible because every time you get a signature it has a fresh timestamp and hence the bits produced as the artifact will be different every time.

Is there scope for declaring in provenance data the reasons for breaking specific requirements to allow artifacts with build requirements of this type to still conform to the SLSA level where the requirement exists? Or should we consider relaxing the wording on the hermeticity and reproducibility requirements to allow for certain classes of use-case which would otherwise violate them?

mlieberman85 commented 2 years ago

SLSA as it stands now doesn't have any requirements are transitivity of dependencies, e.g. you can make a SLSA4 artifact that includes SLSA1 dependencies. We're still ironing out the details on that and the security properties you might get transitive vs. non-transitive.

Also just because a particular artifact can't reach a certain level doesn't innately make it less secure, it just might require mitigating controls. For example, if an artifact is reproducible I might be able to build that artifact multiple times and then trust that no one has compromised multiple build systems (ignoring for a second that the software the build systems are built on could themselves be compromised). So your build might not be reproducible, which might mean you need to have additional controls around the build system for you to feel comfortable about the artifacts coming out of them.

shaunmlowry commented 2 years ago

I think how much transitive dependencies affect the security of artifacts is highly variable. The affect an untrustworthy build of libxml2 on a build of the perl XML-LibXML distribution which thinly wraps it is much higher than the affect a build of pkg-config used purely at build time might have on the build of libxslt for example. I can see that we'd be able to indicate to users the SLSA level on an artifact-by-artifact basis but you're right, giving users a guide to the level of trust they can put into that build overall is tricky. I look forward to seeing the results of that "ironing out" :)

Agreed that an artifact not meeting a SLSA level doesn't necessarily make it less secure, but how do we express the level of trust we think a 3rd party should have in that artifact without making every user examine every detail of the build system? If they can do that and understand the ramifications of everything that happened in the production of an artifact, the SLSA level is largely irrelevant because they already have a good idea of the level of trust they can put in that artifact. We, and our users we're hearing, would like to use the SLSA level as a proxy for that level of understanding and so we're looking either for a way to say that an artifact would have technically made SLSA 4 except for these caveats or have wording in the requirements that would allow these exceptions. We already have that to some extent in that even for SLSA4 we have the generic get-out of "best effort" for hermeticity and reproducibility but we'd like a way to express why our best efforts couldn't meet those requirements in a way that gives consumers of our artifacts enough to judge for themselves the level of trust they should apply.

MarkLodato commented 2 years ago

In my opinion this is an important topic that we need to address.

Assuming this is just for non-hermetic "attached" signatures, then a few initial ideas for solutions:

TomHennen commented 2 years ago

I have a slight preference for a combination of second and third options.

  1. Generate provenance for unsigned artifacts & then another for the signed artifacts chaining back to the unsigned ones.
  2. State that non-hermetic signing is acceptable.
shaunmlowry commented 2 years ago

Agree with Tom as this also simplifies treating tarballs/zipfiles containing signed files as artifacts even if the signatures are detached.

We've come across other cases where builds aren't easily performed hermetically (e.g. the python core on Windows which normally downloads its dependencies, the whole Alien-* perl ecosystem etc.) but we've been able to create hermetic variations for all of those. The only case I'm currently aware of for which there is no mitigation is authenticode signing.

shaunmlowry commented 2 years ago

We found another case for breaking hermeticity - CRL checking. Unless your build process uses a CRL service (and, by implication, complete PKI) which is wholly under your control, downloading source code and/or artifacts from within your build infrastructure over channels secured with e.g. HTTPS necessarily requires contacting a CRL service to validate trust in the serving entity.

TomHennen commented 2 years ago

My view has been that the process that fetches all the build inputs is outside of the hermetic boundary. E.g. The fetching is done by some trusted process that is told what to fetch. That system should be able to check CRLs when downloading code & artifacts.

I'd always figured the hermetic requirement was to isolate the user-defined, potentially very complex, build steps, from the much simpler steps of fetching dependencies and signing outputs.

Maybe we need to do a better job of defining where the 'box' for hermeticity gets drawn?

mlieberman85 commented 2 years ago

I'd always figured the hermetic requirement was to isolate the user-defined, potentially very complex, build steps, from the much simpler steps of fetching dependencies and signing outputs.

This was my understanding as well. I think it might be useful to figure out some things that would examples of hermetic vs. non-hermetic and try and clarify?

For example in the past what I've done is:

  1. Build step with network access that only runs source download and has write access to shared storage X
  2. Build step with network access that runs dependency install that has read/write access to shared storage X
  3. Build step without network access runs the build with read access to shared storage X but write access to shared storage Y. There are no inputs, the build is just something like some_build /shared/X /shared/Y
  4. Build step with network access has read access to storage Y publishes to artifact storage.

I personally think that's more or less hermetic?

arewm commented 1 year ago

Commenting on this issue to bring awareness here -- I commented on https://github.com/slsa-framework/slsa/issues/230#issuecomment-1561687408 about hermetic requirements. I don't see them as requiring full network isolation as much as requiring that the build platform is involved in all network dependency. Lack of network access is a potential implementation detail to a hermetic build.

When it comes to signing or needing a timestamp, if that can be processed by the build platform and associated as something like a resolved dependency, then I don't see that as violating hermetic properties off hand.