The SLSA framework helps organizations measure the level of assurance that the Software Artifacts they produce actually contain and use what they intended (integrity), by ensuring that the whole build and release process, and all of the involved sources and dependencies cannot be tampered with.
In this document, we use the version 0.1 of the specification.
Our current SLSA level is 2. The following is a detail of the levels achieved on each of the requirements:
Requirement | Level | |
| 4 | |
| 4 | |
| 4 | |
| 3 | |
| 4 | |
| 4 | |
| 4 | |
| 4 | |
| 2 | |
| 4 | |
| 4 | |
| 3 | |
| 4 | |
| 4 | |
| 4 | |
| 4 | |
| 4 | |
| 4 | |
| 3 | |
| 3 |
For clarity, this is how SLSA definitions map into our infrastructure:
/proc
, /dev
, /dev/shm
, and /dev/pts
, and uses a private PID, mount, network, IPC, and UTS namespace to isolate itself from other processes in the system.Every change to the source is tracked in a version control system that meets the following requirements:
Change history: There exists a record of the history of changes that went into the revision. Each change contains: the identities of the uploader and reviewers (if any), timestamps of the reviews (if any) and submission, the change description/justification, the content of the change, and the parent revisions.
For example: MR 28742.
Every change in the revision’s history needs to pass through a Merge Request.
To create or approve a Merge Request both the author and the reviewer need to be strongly authenticated into GitLab. The authentication process requires 2FA, and the dates of the change are recorded in the Merge Request.
Only users who were previously granted access by a platform Admin can create or review Merge Requests.
For example: MR 28742.
The revision and its change history are preserved indefinitely and cannot be deleted or modified (not even with multi-party approval).
At the moment, no legal requirement impedes us to preserve indefinitely our change history, and no obliteration policy is in effect. In fact, our source code is Free and Open Source Software: Change History.
Every change within the revision's history must be approved by at least one trusted individual before submission. Moreover, each of these trusted individuals must authenticate into the platform using 2FA before granting approval.
All build steps were fully defined using GitLab CI/CD, Makes and Nix.
Manual commands are not necessary to invoke the build script. A new build is triggered automatically each time new changes are pushed to the repository.
All build steps run on GitLab CI/CD.
All build steps have been stored and versioned in the Git Repository: .gitlab-ci.yml.
Our build service runs each build step inside a container that is provisioned solely for each build and not reused from a prior build. For example: Container Image.
Additionally, the Nix package manager provides an ephemeral environment to each of the derivations.
Our build service ensures that the build steps run in an isolated environment free of influence from other build instances, whether prior or concurrent, by using containerization technologies.
Builds are executed using the Nix package manager, which prevents builds from accessing any external environment variables, network resources, sockets, or paths in the file system. It provides private versions of /proc
, /dev
, /dev/shm
, and /dev/pts
, and uses a private PID, mount, network, IPC, and UTS namespace to isolate the build from other builds happening concurrently in the system.
Input-addressed build caches are used to speed-up the pipeline.
The build output cannot be affected by user parameters other than the build entry point and the top-level source location.
To modify the build output, a change to the source code must happen first.
Builds are executed using the Nix package manager, which prevents builds from accessing any external environment variables, network resources, sockets, or paths in the file system.
All transitive build steps, sources, and dependencies are fully declared up front with immutable references. For example: makes.nix.
The Nix package manager:
All of our build scripts are intended to be reproducible.
The reproducibility guarantees of our build scripts are that of the Nix package manager.
If a build fails to be reproducible, we do not explicitly define why.
In SLSA, "Provenance" is a piece of verifiable information about software artifacts describing where, when and how they were produced.
The purpose of this requirement is to protect consumers from using a compromised package:
At Fluid Attacks consumers and builders are the same entity. We don't use artifacts or packages as a mean of distribution.
Instead, consumers use Makes, a source identifier, and the target artifact identifier, and then all sources, dependencies and intermediate artifacts are built locally in the consumer machine using the Nix package manager by following the steps and environment defined as-code in the source.
Provenance is produced by Makes, and exposed by the build service as a JSON document together with the artifacts produced by the build.
Only builds that produce artifacts generate provenance, because if a build does not produce artifacts, then there wouldn't be something to verify the provenance of.
The authenticity of the provenance comes from the fact that it can be downloaded from the build service itself, and therefore the authenticity claim is as strong as the Build and Source Requirements are secure.
The integrity of the provenance is displayed in the logs and generated by Makes.
The data in the provenance is exposed by the build service, and is generated by Makes.
Regular users of the service are not able to inject or alter the contents because a build is fully determined and automated by its configuration, and the configuration comes directly from the source.
The provenance cannot be falsified by the build service's users:
The provenance contains all the dependencies that were available while running the build steps.
This is guaranteed by the fact that builds are hermetic (see Build - Hermetic). So for a build to succeed, all of its dependencies must be declared, and therefore the build tool (Makes and Nix) who fetched them at build time, have strong knowledge of their existence.
For more information see Fluid Attacks's security page.