slsa icon indicating copy to clipboard operation
slsa copied to clipboard

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

Open shaunmlowry opened this issue 4 years ago • 9 comments

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?

shaunmlowry avatar Jan 26 '22 18:01 shaunmlowry

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.

mlieberman85 avatar Jan 26 '22 19:01 mlieberman85

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.

shaunmlowry avatar Jan 26 '22 20:01 shaunmlowry

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

  • Are there use cases other than signing? If not, then perhaps we should limit this issue's scope to just signing for now.
  • This only affects "attached" signatures that mutate the object, correct? Because you can always generate provenance before the non-hermetic steps for detached signatures, since the signing process wouldn't affect the hash in that case.
  • Note that we already have a carve-out for reproducibility, by requiring a justification instead.
  • Related: #230 discusses a bit the motivation and splitting the requirement into "pinning" and "no network access". But I'm not sure if it really affects this issue.

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

  • Leave the requirements as-is. Generate provenance for the unsigned artifact using the authenticode hash as the subject rather than the raw hash over the bits. (Depends on support for "digest kind".) Then when you sign the artifact afterward, it doesn't affect the hash so the provenance stays valid.
  • Leave the requirements as-is (maybe?). Generate provenance for the unsigned artifact, then generate a separate provenance for the signing step. This signing step would indicate that it's not hermetic, but would be limited to just the signing step. (Tough we'd probably want some change to the requirements to say that this is ok.)
  • Add a specific carve-out in the requirements to allow non-hermetic signing.
  • Add a general carve-out in the requirements like we do for reproducibility.

MarkLodato avatar Jan 27 '22 14:01 MarkLodato

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.

TomHennen avatar Jan 27 '22 14:01 TomHennen

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 avatar Jan 27 '22 17:01 shaunmlowry

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.

shaunmlowry avatar Apr 28 '22 20:04 shaunmlowry

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?

TomHennen avatar Apr 29 '22 19:04 TomHennen

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?

mlieberman85 avatar Apr 29 '22 19:04 mlieberman85

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.

arewm avatar May 24 '23 18:05 arewm