Conversation
…erts The template snapshot test scrubber was replacing package versions with 1.0.0, which triggered Dependabot security alerts for packages with vulnerabilities fixed above 1.0.0 (e.g. OpenTelemetry.Instrumentation). Using 99.99.99 instead ensures scrubbed versions are always above any patched version threshold while still stabilizing snapshots.
There was a problem hiding this comment.
Review: fix: scrub snapshot versions to 99.99.99 to avoid false Dependabot alerts
The change is pragmatic and solves the immediate problem cleanly. Here are my observations:
What this PR does well
The root cause is correctly identified: the snapshot scrubber was emitting 1.0.0, which happens to be a real (vulnerable) version of some OpenTelemetry packages, causing Dependabot to raise false CVE alerts against snapshot files that are never actually restored or executed. The fix is minimal and surgical — one line changed in the scrubbing logic, and all 13 affected verified snapshots updated consistently.
Design considerations worth discussing
1. Why 99.99.99 rather than a clearly-invalid sentinel?
99.99.99 is a valid SemVer string. While it is currently above any published vulnerable version, that is an accidental property — not an invariant the code enforces. If any package were ever published at 99.99.99 (or if Dependabot lowers its threshold logic), the same false-alert problem could resurface.
A more robust sentinel would be one that is structurally outside the NuGet version space Dependabot actually scans, or that is obviously non-real. Some options:
0.0.0-scrubbed— a pre-release label makes clear this is intentionally synthetic, is still valid SemVer, and is below every published release, so Dependabot would have nothing to match against.SCRUBBED— NuGet tolerates non-standard version strings in<PackageReference>for snapshot/template files; this makes the intent unmistakable in the file itself.
The advantage of 0.0.0-scrubbed specifically is that it also doubles as documentation: anyone reading the snapshot file immediately understands the version field is not meaningful.
2. Constant extraction
The magic string "99.99.99" appears only once in TemplateTestBase.cs, but extracting it to a private const string ScrubbedVersion = "99.99.99" (or similar) would make the intent explicit and make future changes (e.g., if the sentinel ever needs updating again) a one-line edit with no snapshot churn.
private const string ScrubbedVersion = "99.99.99"; // Sentinel: avoids Dependabot false alerts
private static void ScrubVersions(StringBuilder sb)
{
var original = sb.ToString();
var matches = VersionRegex().Matches(original);
foreach (var match in matches.Where(m => m.Success))
{
var line = match.Groups[0].Value.Replace(match.Groups[1].Value, ScrubbedVersion);
sb.Replace(match.Value, line);
}
}3. Scrubber applies to <Sdk Name="..." Version="..."> too
Looking at the diff, Aspire.AppHost.Sdk (an <Sdk> element, not a <PackageReference>) is also scrubbed. The regex Version="([^"]*)" is intentionally broad enough to catch both cases, which is fine — but worth making explicit in a comment, since SDK version attributes are a less obvious target.
Summary
The fix is correct and the PR is good to merge as-is. The suggestions above are minor quality improvements rather than blockers:
| Suggestion | Severity |
|---|---|
Prefer 0.0.0-scrubbed or similar structurally-invalid sentinel over 99.99.99 |
Low / Nice-to-have |
| Extract magic string to a named constant | Low / Nice-to-have |
Add a comment noting the scrubber also targets <Sdk> attributes |
Informational |
None of these are required before merging, but the constant extraction in particular would make the code more maintainable if the sentinel ever needs updating again.
Up to standards ✅🟢 Issues
|
Pre-release label makes the version structurally outside Dependabot's scan range and self-documenting, rather than relying on 99.99.99 being above all patched versions.
There was a problem hiding this comment.
Follow-up review
The PR has been updated since the previous review — the sentinel has been changed from 99.99.99 to 0.0.0-scrubbed, directly addressing the earlier recommendation.
Previous feedback addressed
| Suggestion | Status |
|---|---|
Prefer a structurally-invalid / self-documenting sentinel over 99.99.99 |
✅ Addressed — 0.0.0-scrubbed is now used |
| Constant extraction | Not done (still a single inline string) — acceptable given it only appears once |
Assessment of current state
The choice of 0.0.0-scrubbed is well-reasoned:
- It is below every published package release, so Dependabot has nothing real to match against.
- The
-scrubbedpre-release label makes the intent self-documenting in the snapshot files themselves. - All 13 snapshot files are consistently updated to match.
The scrubber logic in TemplateTestBase.cs:44 is clean and there are no other concerns. This is ready to merge.
- Extract magic string to ScrubbedVersion constant - Remove redundant .Where(m => m.Success) — Matches() only returns successful matches
There was a problem hiding this comment.
Follow-up review (3rd pass)
All previously raised feedback has now been fully addressed. This is a clean, well-executed fix.
All previous feedback addressed
| Suggestion | Status |
|---|---|
Prefer 0.0.0-scrubbed over 99.99.99 as sentinel |
✅ Done |
| Extract sentinel to a named constant | ✅ Done — private const string ScrubbedVersion = "0.0.0-scrubbed" |
Additional improvement in this revision
The scrubber loop was also tidied up:
-
matches.Where(m => m.Success)→VersionRegex().Matches(original).Cast<Match>()
The.Where(m => m.Success)guard was redundant:Regex.Matchesonly ever returns successfulMatchobjects. Removing it (and the intermediate variable) is a small but correct simplification. -
match.Groups[0].Value→match.Value
These are equivalent (Groups[0]is always the full match), butmatch.Valueis the idiomatic spelling and reads more clearly.
Overall assessment
The fix is correct and the implementation is clean. The sentinel 0.0.0-scrubbed is structurally below all published releases (so Dependabot has nothing real to match against), self-documenting in the snapshot files, and now backed by a named constant that makes future changes trivial. No concerns — ready to merge.
Updated [TUnit.Core](https://github.com/thomhurst/TUnit) from 1.23.7 to 1.28.7. <details> <summary>Release notes</summary> _Sourced from [TUnit.Core's releases](https://github.com/thomhurst/TUnit/releases)._ ## 1.28.7 <!-- Release notes generated using configuration in .github/release.yml at v1.28.7 --> ## What's Changed ### Other Changes * fix: prevent StringBuilder race in console interceptor during parallel tests by @thomhurst in thomhurst/TUnit#5414 ### Dependencies * chore(deps): update tunit to 1.28.5 by @thomhurst in thomhurst/TUnit#5415 **Full Changelog**: thomhurst/TUnit@v1.28.5...v1.28.7 ## 1.28.5 <!-- Release notes generated using configuration in .github/release.yml at v1.28.5 --> ## What's Changed ### Other Changes * perf: eliminate redundant builds in CI pipeline by @thomhurst in thomhurst/TUnit#5405 * perf: eliminate store.ToArray() allocation on mock behavior execution hot path by @thomhurst in thomhurst/TUnit#5409 * fix: omit non-class/struct constraints on explicit interface mock implementations by @thomhurst in thomhurst/TUnit#5413 ### Dependencies * chore(deps): update tunit to 1.28.0 by @thomhurst in thomhurst/TUnit#5406 **Full Changelog**: thomhurst/TUnit@v1.28.0...v1.28.5 ## 1.28.0 <!-- Release notes generated using configuration in .github/release.yml at v1.28.0 --> ## What's Changed ### Other Changes * fix: resolve build warnings in solution by @thomhurst in thomhurst/TUnit#5386 * Perf: Optimize MockEngine hot paths (~30-42% faster) by @thomhurst in thomhurst/TUnit#5391 * Move Playwright install into pipeline module by @thomhurst in thomhurst/TUnit#5390 * perf: optimize solution build performance by @thomhurst in thomhurst/TUnit#5393 * perf: defer per-class JIT via lazy test registration + parallel resolution by @thomhurst in thomhurst/TUnit#5395 * Perf: Generate typed HandleCall<T1,...> overloads to eliminate argument boxing by @thomhurst in thomhurst/TUnit#5399 * perf: filter generated attributes to TUnit-related types only by @thomhurst in thomhurst/TUnit#5402 * fix: generate valid mock class names for generic interfaces with non-built-in type args by @thomhurst in thomhurst/TUnit#5404 ### Dependencies * chore(deps): update tunit to 1.27.0 by @thomhurst in thomhurst/TUnit#5392 * chore(deps): update dependency path-to-regexp to v8 by @thomhurst in thomhurst/TUnit#5378 **Full Changelog**: thomhurst/TUnit@v1.27.0...v1.28.0 ## 1.27.0 <!-- Release notes generated using configuration in .github/release.yml at v1.27.0 --> ## What's Changed ### Other Changes * Fix Dependabot security vulnerabilities in docs site by @thomhurst in thomhurst/TUnit#5372 * fix: use 0.0.0-scrubbed sentinel version in snapshot scrubber to avoid false Dependabot alerts by @thomhurst in thomhurst/TUnit#5374 * Speed up Engine.Tests by removing ProcessorCount parallelism cap by @thomhurst in thomhurst/TUnit#5379 * ci: add concurrency groups to cancel redundant workflow runs by @thomhurst in thomhurst/TUnit#5373 * Add scope-aware initialization and disposal OpenTelemetry spans to trace timeline and HTML report by @Copilot in thomhurst/TUnit#5339 * Add WithInnerExceptions() for fluent AggregateException assertion chaining by @thomhurst in thomhurst/TUnit#5380 * Drop net6.0 and net7.0 TFMs, keep net8.0+ and netstandard2.x by @thomhurst in thomhurst/TUnit#5387 * Remove all [Obsolete] members and migrate callers by @thomhurst in thomhurst/TUnit#5384 * Add AssertionResult.Failed overload that accepts an Exception by @thomhurst in thomhurst/TUnit#5388 ### Dependencies * chore(deps): update dependency mockolate to 2.3.0 by @thomhurst in thomhurst/TUnit#5370 * chore(deps): update tunit to 1.25.0 by @thomhurst in thomhurst/TUnit#5371 * chore(deps): update dependency minimatch to v9.0.9 by @thomhurst in thomhurst/TUnit#5375 * chore(deps): update dependency path-to-regexp to v0.2.5 by @thomhurst in thomhurst/TUnit#5376 * chore(deps): update dependency minimatch to v10 by @thomhurst in thomhurst/TUnit#5377 * chore(deps): update dependency picomatch to v4 by @thomhurst in thomhurst/TUnit#5382 * chore(deps): update dependency svgo to v4 by @thomhurst in thomhurst/TUnit#5383 * chore(deps): update dependency path-to-regexp to v1 [security] by @thomhurst in thomhurst/TUnit#5385 **Full Changelog**: thomhurst/TUnit@v1.25.0...v1.27.0 ## 1.25.0 <!-- Release notes generated using configuration in .github/release.yml at v1.25.0 --> ## What's Changed ### Other Changes * Fix missing `default` constraint on explicit interface implementations with unconstrained generics by @thomhurst in thomhurst/TUnit#5363 * feat(mocks): add ReturnsAsync typed factory overload with method parameters by @thomhurst in thomhurst/TUnit#5367 * Fix Arg.IsNull<T> and Arg.IsNotNull<T> to support nullable value types by @thomhurst in thomhurst/TUnit#5366 * refactor(mocks): use file-scoped types for generated implementation details by @thomhurst in thomhurst/TUnit#5369 * Compress HTML report JSON data and minify CSS by @thomhurst in thomhurst/TUnit#5368 ### Dependencies * chore(deps): update tunit to 1.24.31 by @thomhurst in thomhurst/TUnit#5356 * chore(deps): update dependency mockolate to 2.2.0 by @thomhurst in thomhurst/TUnit#5357 * chore(deps): update dependency polyfill to 9.24.1 by @thomhurst in thomhurst/TUnit#5365 * chore(deps): update dependency polyfill to 9.24.1 by @thomhurst in thomhurst/TUnit#5364 **Full Changelog**: thomhurst/TUnit@v1.24.31...v1.25.0 ## 1.24.31 <!-- Release notes generated using configuration in .github/release.yml at v1.24.31 --> ## What's Changed ### Other Changes * Fix Aspire 13.2.0+ timeout caused by ProjectRebuilderResource being awaited by @Copilot in thomhurst/TUnit#5335 * chore(deps): update dependency polyfill to 9.24.0 by @thomhurst in thomhurst/TUnit#5349 * Fix nullable IParsable type recognition in source generator and analyzer by @Copilot in thomhurst/TUnit#5354 * fix: resolve race condition in HookExecutionOrderTests by @thomhurst in thomhurst/TUnit#5355 * Fix MaxExternalSpansPerTest cap bypass when Activity.Parent chain is broken by @Copilot in thomhurst/TUnit#5352 ### Dependencies * chore(deps): update tunit to 1.24.18 by @thomhurst in thomhurst/TUnit#5340 * chore(deps): update dependency stackexchange.redis to 2.12.14 by @thomhurst in thomhurst/TUnit#5343 * chore(deps): update verify to 31.15.0 by @thomhurst in thomhurst/TUnit#5346 * chore(deps): update dependency polyfill to 9.24.0 by @thomhurst in thomhurst/TUnit#5348 **Full Changelog**: thomhurst/TUnit@v1.24.18...v1.24.31 ## 1.24.18 <!-- Release notes generated using configuration in .github/release.yml at v1.24.18 --> ## What's Changed ### Other Changes * feat(mocks): shorter, more readable generated mock type names by @thomhurst in thomhurst/TUnit#5334 * Fix DisposeAsync() ordering for nested property injection by @Copilot in thomhurst/TUnit#5337 ### Dependencies * chore(deps): update tunit to 1.24.13 by @thomhurst in thomhurst/TUnit#5331 **Full Changelog**: thomhurst/TUnit@v1.24.13...v1.24.18 ## 1.24.13 <!-- Release notes generated using configuration in .github/release.yml at v1.24.13 --> ## What's Changed ### Other Changes * perf(mocks): optimize MockEngine for lower allocation and faster verification by @thomhurst in thomhurst/TUnit#5319 * Remove defunct `UseTestingPlatformProtocol` reference for vscode by @erwinkramer in thomhurst/TUnit#5328 * perf(aspnetcore): prevent thread pool starvation during parallel WebApplicationTest server init by @thomhurst in thomhurst/TUnit#5329 * fix TUnit0073 for when type from from another assembly by @SimonCropp in thomhurst/TUnit#5322 * Fix implicit conversion operators bypassed in property injection casts by @Copilot in thomhurst/TUnit#5317 * fix(mocks): skip non-virtual 'new' methods when discovering mockable members by @thomhurst in thomhurst/TUnit#5330 * feat(mocks): IFoo.Mock() discovery with generic fallback and ORP resolution by @thomhurst in thomhurst/TUnit#5327 ### Dependencies * chore(deps): update tunit to 1.24.0 by @thomhurst in thomhurst/TUnit#5315 * chore(deps): update aspire to 13.2.1 by @thomhurst in thomhurst/TUnit#5323 * chore(deps): update verify to 31.14.0 by @thomhurst in thomhurst/TUnit#5325 ## New Contributors * @erwinkramer made their first contribution in thomhurst/TUnit#5328 **Full Changelog**: thomhurst/TUnit@v1.24.0...v1.24.13 ## 1.24.0 <!-- Release notes generated using configuration in .github/release.yml at v1.24.0 --> ## What's Changed ### Other Changes * perf: optimize TUnit.Mocks hot paths by @thomhurst in thomhurst/TUnit#5304 * fix: resolve System.Memory version conflict on .NET Framework (net462) by @thomhurst in thomhurst/TUnit#5303 * fix: resolve CS0460/CS0122/CS0115 when mocking concrete classes from external assemblies by @thomhurst in thomhurst/TUnit#5310 * feat(mocks): parameterless Returns() and ReturnsAsync() for async methods by @thomhurst in thomhurst/TUnit#5309 * Fix typo in NUnit manual migration guide by @aa-ko in thomhurst/TUnit#5312 * refactor(mocks): unify Mock.Of<T>() and Mock.OfPartial<T>() into single API by @thomhurst in thomhurst/TUnit#5311 * refactor(mocks): clean up Mock API surface by @thomhurst in thomhurst/TUnit#5314 * refactor(mocks): remove generic/untyped overloads from public API by @thomhurst in thomhurst/TUnit#5313 ### Dependencies * chore(deps): update tunit to 1.23.7 by @thomhurst in thomhurst/TUnit#5305 * chore(deps): update dependency mockolate to 2.1.1 by @thomhurst in thomhurst/TUnit#5307 ## New Contributors * @aa-ko made their first contribution in thomhurst/TUnit#5312 **Full Changelog**: thomhurst/TUnit@v1.23.7...v1.24.0 Commits viewable in [compare view](thomhurst/TUnit@v1.23.7...v1.28.7). </details> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Summary
1.0.0, which triggered Dependabot security alerts (CVE-2024-32028) forOpenTelemetry.Instrumentation.HttpandOpenTelemetry.Instrumentation.AspNetCore— even though the actual template uses patched1.15.xversions0.0.0-scrubbed— a pre-release label that is structurally below all real releases, so Dependabot will never match it against any CVETest plan