RFE: .NET's build is deterministic/reproducible
- Dominant language
- No language data
- Stars
- 287
- Forks
- 145
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 10
Description
### Describe the Problem
Reproducible or Determinstic builds provide a very nice set of security advantages to a piece of software:
- Security and verification: It becomes possible to detect and deal with a whole new class of attacks in the supply chain - including on build servers. It becomes easier to verify items like SBOMs.
- Increasing user trust: Users can trust the binaries they have matches the sources, reducing risks of backdoors and other vulnerabilities.
- Auditing and Compliance: It becomes easier to verify that the sources and binaries match for compliance reasons.
For more details, see https://en.wikipedia.org/wiki/Reproducible_builds and https://reproducible-builds.org/
### Describe the Solution
It should be possible to build .NET in a way that the build can be reproduced by others. The general guidelines for making this happen are described at https://reproducible-builds.org/docs/commandments/.
It's okay to requires some extra set up - such as an env var like `SOURCE_DATE_EPOCH` - to make this happen.
Ideally, this should be the default configuration of building. But a custom configuration, or custom build flags to enable this behaviour, would be fine as a starting point (and maybe even as end-point, depending on the number/complexity).
### Additional Context
**.NET**:
- The https://github.com/dotnet/reproducible-builds project and it's READMEs such as [Reproducible-MSBuild/README.md](https://github.com/dotnet/reproducible-builds/blob/main/Documentation/Reproducible-MSBuild/README.md)
- https://github.com/dotnet/sourcelink/issues/601
- https://github.com/clairernovotny/DeterministicBuilds
- [`-deterministic` compile option](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/code-generation#deterministic)
- NuGet's [[Spec] Deterministic Pack](https://github.com/NuGet/Home/wiki/%5BSpec%5D-Deterministic-Pack)
**Arch Linux**: https://wiki.archlinux.org/title/Reproducible_builds
**Debian**: https://wiki.debian.org/ReproducibleBuilds and https://lists.debian.org/debian-devel-announce/2026/05/msg00001.html:
> we've decided it's time to say that Debian must ship reproducible packages. Since yesterday, we have enabled our migration software to block migration of new packages that can't be reproduced [2] or existing packages (in testing) that regress in reproducibility.
**Fedora**: https://fedoraproject.org/wiki/Changes/ReproduciblePackageBuilds and https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/thread/3OGIBZWPBB43QEVDXPEHNYEYJWMRPJ4E/
**Red Hat**: https://access.redhat.com/blogs/766093/posts/1976033
**SuSE**: https://www.zdnet.com/article/suse-bets-its-future-on-digital-sovereignty/
### Timing
The primary driver for this from our side that Fedora is looking to start testing reproducible builds formally in 2025 ([discussion](https://discussion.fedoraproject.org/t/f43-change-proposal-package-builds-are-expected-to-be-reproducible-system-wide/147320)). Fedora is going to report issues against software that doesn't comply with the reproducible-build guidelines by the end of 2025. Many other languages/runtimes - including Haskell, mingw and golang packages - are in the same position as .NET and are known to be non-reproducible at the moment. I don't expect Fedora to make reproducible builds a hard requirement in 2025.
### Breakdown
#### Phase 1: Local - Reliance on wall-clock time, randomness/GUIDs and file-system-ordering
This first phase is about rebuilding .NET VMR on the same identical system at the same paths multiple times and getting bit-identical SDKs.
- Arcade
- [x] https://github.com/dotnet/arcade/pull/16001
- [x] https://github.com/dotnet/arcade/pull/16787 Blocked by https://github.com/NuGet/NuGet.Client/pull/7020 and https://github.com/dotnet/arcade/issues/16623
- [x] https://github.com/dotnet/arcade/issues/15910
- [x] https://github.com/dotnet/arcade/pull/16954
- ASP.NET Core
- [x] Binaries like `shared/Microsoft.AspNetCore.App/10.0.0-dev/Microsoft.AspNetCore.Components.Endpoints.dll` and `Microsoft.AspNetCore.Http.Connections.dll` have a PE Time Stamp header that's different from build to build. (fixed by https://github.com/dotnet/aspnetcore/pull/64863)
- [x] `RemoveSharedFrameworkDependencies` task should create deterministic packages. Fixed by https://github.com/dotnet/aspnetcore/pull/64863
- FSharp
- [x] https://github.com/dotnet/fsharp/issues/19732 fixed by https://github.com/dotnet/fsharp/pull/19810
- [x] https://github.com/dotnet/fsharp/issues/19928 fixed by https://github.com/dotnet/fsharp/pull/19929
- IdentityModel Extension
- [x] https://github.com/dotnet/source-build-reference-packages/pull/1610
- MSBuild
- [x] https://github.com/dotnet/msbuild/pull/12811 (fixed https://github.com/dotnet/msbuild/issues/12818 )
- NuGet
- [x] https://github.com/NuGet/NuGet.Client/pull/6500
- [x] https://github.com/NuGet/NuGet.Client/pull/6963 (previously https://github.com/NuGet/NuGet.Client/pull/6649)
- [x] https://github.com/NuGet/NuGet.Client/pull/7020 (fixes https://github.com/NuGet/Home/issues/8601. See also the spec at https://github.com/NuGet/Home/pull/14785)
- [x] https://github.com/NuGet/NuGet.Client/pull/7410
- [x] https://github.com/NuGet/NuGet.Client/pull/7503
- source-build-assets
- [x] https://github.com/dotnet/source-build-assets/issues/1662
- VMR
- [x] https://github.com/dotnet/dotnet/pull/1584: Remove `DeterministicBuildOptOut=true` for `vstest.proj` and `nuget-client.proj` ( https://github.com/dotnet/dotnet/issues/1583 )
- [ ] https://github.com/dotnet/dotnet/pull/7817
#### Phase 2: Very host names, usernames and build paths
This phase is about rebuilding .NET VMR on different systems, and at different paths and getting bit-identical SDKs.
#### Nice-to-have
- [x] Make NuGet.Clients' nupkg generation repsect `SOURCE_BUILD_EPOCH` for timestamps of embedded files. Part of https://github.com/NuGet/NuGet.Client/pull/7020
- [x] Don't skip `.psmdcp` files in https://github.com/dotnet/dotnet/blob/591d6a4edeb47a71697bb3866a50979c38ed6732/eng/tools/BuildComparer/Utils.cs#L42-L46 Done in https://github.com/dotnet/dotnet/pull/8442
#### Questionable
- [x] ~Set `Deterministic=true` at each repo-level?~ `Deterministic=true` is already the default at SDK-level.
- [ ] Add Deterministic support to `System.IO.Packaging`?
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.