Description
Several official .NET package PDBs appear to contain source document checksums computed over CRLF-normalized source files, while SourceLink points at GitHub raw URLs that serve LF-normalized blobs.
This means strict SourceLink/PDB byte verification fails, but the same files verify after CR/LF normalization. This does not look like source-content drift; it looks like line-ending drift between official build inputs and the Git blob bytes addressed by SourceLink.
This was found with dotnet-inspect 0.9.0, which reports both strict content mismatches and CR/LF-normalized matches.
Repro
Install/use dotnet-inspect 0.9.0 or newer:
dotnet tool install -g dotnet-inspect --version 0.9.0
Run SourceLink Integrity on a runtime-owned package:
dotnet-inspect library System.Text.Json.dll --package System.Text.Json -S "SourceLink Integrity"
Observed output shape:
## SourceLink Integrity
| Field | Value |
| ----- | ----- |
| Mismatched | 0 |
| CR/LF Mismatch | 338 normalized |
| Status | Partial |
| Unverifiable | 2 |
| Verified | 338 |
A package with no unverifiable source documents shows the same line-ending pattern more cleanly:
dotnet-inspect library System.IO.Pipelines.dll --package System.IO.Pipelines -S "SourceLink Integrity"
| Mismatched | 0 |
| CR/LF Mismatch | 30 normalized |
| Status | Verified |
| Unverifiable | 0 |
| Verified | 30 |
Expected behavior
For SourceLink URLs pinned to immutable Git commits, the source bytes fetched from SourceLink should match the checksums recorded in the portable PDB without line-ending normalization.
Actual behavior
For every sampled source document in the affected packages, strict hash comparison fails, but comparison succeeds after normalizing LF/CRLF. For example, for System.Text.Json, all 338 verified files required CR/LF normalization.
Package sample
Representative packages tested with dotnet-inspect 0.9.0:
This appears to affect multiple .NET repos, not just dotnet/runtime or dotnet/extensions.
Control packages
This does not appear to be a dotnet-inspect artifact. Some packages verify with strict byte-for-byte SourceLink/PDB checksums without CR/LF normalization:
For comparison, Newtonsoft.Json also shows the CR/LF-normalized pattern (240/240 verified after normalization), so the issue is not unique to .NET-owned packages. The .NET-owned sample above is included because it demonstrates the same pattern across runtime, aspnetcore, roslyn, and extensions packages.
Why this likely happens
The repo settings generally normalize text into Git but do not force *.cs working-tree files to LF:
dotnet/runtime: *.cs text diff=csharp, no eol=lf
dotnet/extensions: *.cs text=auto diff=csharp, no eol=lf
dotnet/aspnetcore: * text=auto, no *.cs eol=lf
dotnet/roslyn: *.cs diff=csharp text, no eol=lf
If official builds run from a Windows checkout or another CRLF working tree, the compiler records CRLF-based source checksums in the PDB. SourceLink then points to GitHub raw URLs for commit-pinned blobs, which are served as LF bytes.
Impact
Tools performing strict SourceLink/PDB source verification will report checksum mismatches for official .NET packages, even though the logical source content matches after line-ending normalization.
dotnet-inspect 0.9.0 now reports this explicitly as CR/LF Mismatch, but ideally official package PDB checksums would match the exact SourceLink bytes without normalization.
Description
Several official .NET package PDBs appear to contain source document checksums computed over CRLF-normalized source files, while SourceLink points at GitHub raw URLs that serve LF-normalized blobs.
This means strict SourceLink/PDB byte verification fails, but the same files verify after CR/LF normalization. This does not look like source-content drift; it looks like line-ending drift between official build inputs and the Git blob bytes addressed by SourceLink.
This was found with
dotnet-inspect0.9.0, which reports both strict content mismatches and CR/LF-normalized matches.Repro
Install/use dotnet-inspect 0.9.0 or newer:
Run SourceLink Integrity on a runtime-owned package:
dotnet-inspect library System.Text.Json.dll --package System.Text.Json -S "SourceLink Integrity"Observed output shape:
A package with no unverifiable source documents shows the same line-ending pattern more cleanly:
dotnet-inspect library System.IO.Pipelines.dll --package System.IO.Pipelines -S "SourceLink Integrity"Expected behavior
For SourceLink URLs pinned to immutable Git commits, the source bytes fetched from SourceLink should match the checksums recorded in the portable PDB without line-ending normalization.
Actual behavior
For every sampled source document in the affected packages, strict hash comparison fails, but comparison succeeds after normalizing LF/CRLF. For example, for
System.Text.Json, all 338 verified files required CR/LF normalization.Package sample
Representative packages tested with
dotnet-inspect 0.9.0:This appears to affect multiple .NET repos, not just
dotnet/runtimeordotnet/extensions.Control packages
This does not appear to be a dotnet-inspect artifact. Some packages verify with strict byte-for-byte SourceLink/PDB checksums without CR/LF normalization:
For comparison,
Newtonsoft.Jsonalso shows the CR/LF-normalized pattern (240/240verified after normalization), so the issue is not unique to .NET-owned packages. The .NET-owned sample above is included because it demonstrates the same pattern acrossruntime,aspnetcore,roslyn, andextensionspackages.Why this likely happens
The repo settings generally normalize text into Git but do not force
*.csworking-tree files to LF:dotnet/runtime:*.cs text diff=csharp, noeol=lfdotnet/extensions:*.cs text=auto diff=csharp, noeol=lfdotnet/aspnetcore:* text=auto, no*.cs eol=lfdotnet/roslyn:*.cs diff=csharp text, noeol=lfIf official builds run from a Windows checkout or another CRLF working tree, the compiler records CRLF-based source checksums in the PDB. SourceLink then points to GitHub raw URLs for commit-pinned blobs, which are served as LF bytes.
Impact
Tools performing strict SourceLink/PDB source verification will report checksum mismatches for official .NET packages, even though the logical source content matches after line-ending normalization.
dotnet-inspect 0.9.0now reports this explicitly asCR/LF Mismatch, but ideally official package PDB checksums would match the exact SourceLink bytes without normalization.