Skip to content

fix: use 0.0.0-scrubbed sentinel version in snapshot scrubber to avoid false Dependabot alerts#5374

Merged
thomhurst merged 3 commits intomainfrom
fix/scrub-snapshot-versions-high
Apr 4, 2026
Merged

fix: use 0.0.0-scrubbed sentinel version in snapshot scrubber to avoid false Dependabot alerts#5374
thomhurst merged 3 commits intomainfrom
fix/scrub-snapshot-versions-high

Conversation

@thomhurst
Copy link
Copy Markdown
Owner

@thomhurst thomhurst commented Apr 4, 2026

Summary

  • The template snapshot test scrubber was replacing package versions with 1.0.0, which triggered Dependabot security alerts (CVE-2024-32028) for OpenTelemetry.Instrumentation.Http and OpenTelemetry.Instrumentation.AspNetCore — even though the actual template uses patched 1.15.x versions
  • Changed the scrubbed version to 0.0.0-scrubbed — a pre-release label that is structurally below all real releases, so Dependabot will never match it against any CVE
  • Updated all 13 verified snapshot files to match

Test plan

  • All 8 template instantiation tests pass

…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.
Copy link
Copy Markdown
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@codacy-production
Copy link
Copy Markdown

codacy-production bot commented Apr 4, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

TIP This summary will be updated as you push new changes. Give us feedback

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.
@thomhurst thomhurst changed the title fix: scrub snapshot versions to 99.99.99 to avoid false Dependabot alerts fix: use 0.0.0-scrubbed sentinel version in snapshot scrubber to avoid false Dependabot alerts Apr 4, 2026
Copy link
Copy Markdown
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 -scrubbed pre-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
Copy link
Copy Markdown
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.Matches only ever returns successful Match objects. Removing it (and the intermediate variable) is a small but correct simplification.

  • match.Groups[0].Valuematch.Value
    These are equivalent (Groups[0] is always the full match), but match.Value is 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.

This was referenced Apr 6, 2026
github-actions bot pushed a commit to IntelliTect/CodingGuidelines that referenced this pull request Apr 6, 2026
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>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=TUnit.Core&package-manager=nuget&previous-version=1.23.7&new-version=1.28.7)](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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant