What dotnet-fast is signed with, what it isn't, and exactly how to check a copy you've downloaded.
dotnet-fast is a tool you run inside your build, so it's reasonable to want to know where the bits
came from. This page states the position plainly, including the parts we don't cover — an
overstated supply-chain claim is worse than an honest gap.
| Artifact | Integrity | Signature | Build provenance |
|---|---|---|---|
NuGet package RDLL.dotnet-fast |
Package content hash, enforced by the NuGet client | nuget.org repository signature (Microsoft, DigiCert chain, RFC-3161 timestamped) | None published |
dotnet-fast-win-x64.exe (GitHub release asset) |
SHA-256 published beside it as .sha256 |
None | None published |
dotnet-fast-linux-x64 (GitHub release asset) |
SHA-256 published beside it as .sha256 |
None | None published |
The NuGet package is the artifact with a signature, and everything in that column comes from
nuget.org rather than from us: there is no author signature and no build attestation. Since
1.2.0 the standalone binary is also published, as a GitHub release asset with a checksum but no
signature (see below). The rest of this page is what each of those does and
doesn't buy you.
This is the supported install path, and the channel with the strongest guarantees.
dotnet tool install -g RDLL.dotnet-fastWhen nuget.org accepts a package it repository-signs it: a countersignature over the exact package content, made with a Microsoft-held code-signing certificate chaining to DigiCert, and RFC-3161 timestamped. The signature embeds the source service index and the package's owner list at the time of submission.
This is applied by nuget.org during ingestion — the package we push is unsigned when it leaves the build. Concretely, the repository signature proves:
- The package content is byte-identical to what nuget.org ingested. If a
.nupkgis modified after publication, the NuGet client rejects it withNU3008rather than installing it. - nuget.org accepted it under the
RDLLowner account, i.e. it went through that account's publishing credentials, not an anonymous upload. - When it was signed, via the trusted timestamp — so the signature remains checkable after the signing certificate expires.
It does not prove who built the package, from what source, or on what machine. It is a distribution-integrity signature, not a provenance statement.
Download the .nupkg and verify every signature on it:
curl -sSLO https://api.nuget.org/v3-flatcontainer/rdll.dotnet-fast/1.0.0/rdll.dotnet-fast.1.0.0.nupkg
dotnet nuget verify rdll.dotnet-fast.1.0.0.nupkg --allThat prints the real output for 1.0.0 — at the default verbosity, exactly this and nothing else:
Verifying RDLL.dotnet-fast.1.0.0
Content hash: WhLgD60/cnglAQfwaMXex+mCRO2cI4d1llIB3Ro8fGo6MbXtPomHwFUbjN5P8rDWgluA0DlYFdSA1fnvrWdkIg==
Signature type: Repository
Subject Name: CN=NuGet.org Repository by Microsoft, O=NuGet.org Repository by Microsoft, L=Redmond, S=Washington, C=US
SHA256 hash: 1F4B311D9ACC115C8DC8018B5A49E00FCE6DA8E2855F9F014CA6F34570BC482D
Valid from: 23/02/2024 00:00:00 to 19/05/2027 00:59:59
There is no success line at the default verbosity — check the exit code, not the text. 0 means
verified. Add -v normal to get an explicit
Successfully verified package 'RDLL.dotnet-fast.1.0.0'., or -v detailed to additionally print
Service index: https://api.nuget.org/v3/index.json and Owners: RDLL plus the full certificate and
timestamp chains.
Signature type: Repository is the only signature you should expect. If you ever see an
Author signature on this package, treat it as suspicious and
report it — we don't author-sign.
You don't need anything from us to harden this. Register nuget.org as a trusted repository pinned to this package's owner, then require signature validation:
dotnet nuget trust source nuget.org --owners RDLL
dotnet nuget trust listThat writes a trustedSigners entry with nuget.org's repository certificate fingerprints and
Trusted owners: RDLL. Pair it with signatureValidationMode in your nuget.config to turn it into
a hard gate:
<configuration>
<config>
<add key="signatureValidationMode" value="require" />
</config>
</configuration>With require set, restore fails unless the package carries a signature from a signer you've
trusted. Note this applies to every package you restore, not just this one — roll it out
deliberately.
Publication uses NuGet Trusted Publishing: the release job proves its identity to nuget.org with a short-lived OIDC token and receives a one-hour, single-use API key in exchange. There is no long-lived NuGet API key stored anywhere — nothing to leak, and nothing an attacker can steal and reuse later. Publication is started deliberately by the maintainer; nothing publishes on a code push, a merge, or a schedule.
That constrains who can publish. It does not, on its own, attest to what was built.
Since 1.2.0, each release attaches a self-contained dotnet-fast-win-x64.exe and a matching
dotnet-fast-win-x64.exe.sha256 to its GitHub release on this repository. Since 1.10.1, it also
attaches a static dotnet-fast-linux-x64 (with its own .sha256) — the same binary the
RDLL.dotnet-fast NuGet package carries under runtimes/linux-x64/native/. Every asset is built
from the commit the version was tagged at. Check the download against the published digest before
running it:
(Get-FileHash .\dotnet-fast-win-x64.exe -Algorithm SHA256).Hash
Get-Content .\dotnet-fast-win-x64.exe.sha256 # compare the two, case-insensitivelysha256sum -c dotnet-fast-win-x64.exe.sha256 # if you have coreutils
sha256sum -c dotnet-fast-linux-x64.sha256 # same, for the linux-x64 assetBe precise about what that proves. A checksum published next to the file it describes detects accidental corruption — a truncated download, a bad proxy, a flaky mirror. It is not a signature: anyone able to replace the binary on the release could replace the checksum beside it. Neither binary carries an Authenticode signature or a build attestation, so Windows SmartScreen may warn on the win-x64 asset's first run.
The NuGet package remains the recommended channel, precisely because its signature is issued by a
third party rather than by us. If what you want is a CI agent that doesn't pay a dotnet tool restore
per job, install once into a directory and cache that directory — that path still goes through NuGet:
dotnet tool install RDLL.dotnet-fast --tool-path ./.dotnet-fast--tool-path is documented in install.md.
Nothing we ship is Authenticode-signed, so Windows SmartScreen may warn on first run.
Windows x64 is the only validated platform — see support-matrix.md and versioning.md.
For 1.0 the position is: nuget.org's repository signature on the package, and no provenance or attestation claim beyond that. We considered the alternatives and are not adopting them for 1.0. The reasoning, so you can judge it rather than take it on trust:
GitHub artifact attestations (actions/attest-build-provenance) produce a Sigstore-signed
statement binding an artifact's digest to the workflow, repository, and commit that produced it —
genuinely useful, and the option we'd most want. Two things block it here. First, on GitHub Free,
Pro, and Team plans attestations are only available for public repositories; private repositories
require GitHub Enterprise Cloud. dotnet-fast is distributed as a binary under a
freeware license with its implementation kept closed, so the repository that builds
it is private and the feature is not available to it. Second, attestations for private repositories
are signed by GitHub's private Sigstore instance with no public transparency log, so an outside
consumer could not independently audit them even if we produced them. Publishing an attestation you
can't check isn't worth the badge.
SLSA. GitHub describes its attestations as corresponding to SLSA v1.0 Build Level 2, which
requires the build to run "on dedicated infrastructure, not an individual's workstation", with
provenance tied to that infrastructure by a digital signature. dotnet-fast release builds run on
infrastructure the maintainer controls rather than on an isolated, ephemeral third-party builder, so
Build L2 is not honestly claimable today. Build L3 — which additionally requires runs to be
isolated from each other and signing material to be unreachable from build steps — is further out
still. Build L1 only requires that provenance exist; we could emit a provenance document tomorrow,
but self-asserted, unsigned provenance from a closed build adds a file, not a security property. So
we claim no SLSA level rather than claim one we can't support.
The repository signature, documented as such — what you're reading. It's the option that describes reality, and auditing it for this page surfaced something we'd been undercounting: the nuget.org repository signature is meaningfully stronger than a checksum, is already on every release, and most consumers weren't being told it was there or how to enforce it. Documenting and enforcing what we actually have beats advertising a property we don't.
If author signing becomes worthwhile after 1.0, NuGet author signing is the natural next step: it would add the one property missing today — that the package was signed by a key the publisher controls — and, unlike attestations, it needs neither a public repository nor a hosted build service. It requires a CA-issued code-signing certificate and somewhere safe to keep the private key, so it's a deliberate decision rather than a switch to flip. It is not part of 1.0.
- No build provenance. Nothing published today ties a released artifact back to a specific source
commit or build. The
<repository>metadata inside the.nupkgpoints at this documentation repository and is not a verifiable build record — don't treat it as one. - No SLSA level. See above.
- No reproducible builds. Building the tool twice is not guaranteed to produce byte-identical output, and there is no independent rebuild to compare against.
- No author signature or Authenticode signature on the package or the binary.
- No third-party audit of the tool's source.
What you can rely on: a package on nuget.org whose content is signed and timestamped by Microsoft under a named owner, published through a keyless flow with no standing credential.
If you find a security problem in dotnet-fast — a crash on hostile input, a path-traversal in file
writing, credential handling in the build cache — please
open an issue and say up front that it's
security-related, so it gets triaged first. Include the version (dotnet-fast --version) and a
minimal reproduction.
☕ Find dotnet-fast useful? Buy me a coffee — thanks for the support!