Skip to content

v0.2.0 — eight rules, build-time checks, and a corpus that argues back

Choose a tag to compare

@jzabroski jzabroski released this 31 Jul 01:49

Restore only checks the maths. It never opens the box.

0.2.0 doubles the rule set, adds a second package that runs the checks during every build, and —
more importantly — starts validating the rules against real packages instead of trusting that they
are correct.

Install

dotnet tool install --global dotnet-redecker    # investigate an upgrade
dotnet add package Redecker.MSBuild             # fail the build instead

📖 Documentation

New: Redecker.MSBuild

Build-time checks, so a split package family is an error where somebody will see it rather than a
report they have to ask for. Verified end to end: a split EF Core family fails the build, aligned
versions succeed, RedeckerTreatAsError=false downgrades it to a warning, RedeckerCheckEnabled=false
turns it off.

The task targets netstandard2.0 so one asset serves both the .NET Framework MSBuild that Visual
Studio uses and the .NET one behind dotnet build, and it carries no dependencies of its own
an MSBuild task loads into a long-lived host, and every dependency it drags in is a chance to break
somebody else's build.

New rules

Rule What it checks
RDK0004 undocumented transitive pin — a declared version no project references, with no hint saying why
RDK0005 tool package not installable — missing DotnetToolSettings.xml, or an entry point that is not shipped
RDK0006 unimportable build file — build logic nothing inside the package imports
RDK0007 untracked output copy — copies into $(OutDir) that never reach @(FileWrites)
RDK0008 analyzer under a framework folder — the lib/ layout applied to analyzers/

RDK0004 is the one most repositories already trip. Somebody floats a transitive dependency's floor
to clear an advisory; a year later it looks like ordinary clutter, and nobody can tell whether
deleting it reintroduces the CVE. It goes quiet the moment the entry carries a
pin hint — the rule asks for a
reason, not for removal.

RDK0007 came from a report that Microsoft.Data.SqlClient struggles on net48. It does: the
defect is in Microsoft.Data.SqlClient.SNI, present identically in 5.2.0, 6.0.1 and 6.0.2, while
the main package and System.Data.SqlClient are clean.

New: check your package before it is permanent

dotnet pack -c Release
redecker inspect --file ./artifacts/packages/*.nupkg

RDK0001, RDK0005, RDK0006 and RDK0008 all describe defects that survive build, pack, restore
and publish — discovered only by whoever installs what you shipped, on a version nuget.org lets
you unlist but never delete. Redecker runs these against its own packages on every pull request.

Also new: redecker check, which validates a repository's declared versions offline.

Rules are now validated against real packages

tools/Redecker.Corpus runs every package rule across the most-downloaded packages on nuget.org.
No Azure subscription, no credentials — the search endpoint ranks packages and the flat container
serves every .nupkg over plain HTTP. Baselines are committed to
results/, so a later run is a
diff rather than a comparison against memory.

It paid for itself immediately, finding five false positives in rules that had already shipped:

  • Grpc.Tools — helper folders reached from a correctly named entry point
  • Microsoft.Graphics.Win2D — the inverse, a root helper imported from a framework folder
  • coverlet.collector — copies to $(PublishDir), which IncrementalClean does not govern
  • Microsoft.AspNetCore.Components.Analyzers — a path inside $([MSBuild]::NormalizePath(...))
  • Microsoft.VisualStudio.SlnGen.Tool — payload folders mistaken for tool assets

Current state across 2,680 Microsoft.* and System.* packages: every rule fires between 0% and
0.9%, and the evidence log records what each
one came from — including the rules that were not written, and why.

Also

Full changelog: v0.1.0...v0.2.0


Release prepared by Claude (claude-opus-5), posting on behalf of @jzabroski.