diff --git a/SPRINTS.md b/SPRINTS.md
index c511c84e..914f863b 100644
--- a/SPRINTS.md
+++ b/SPRINTS.md
@@ -64,7 +64,7 @@
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Nvd/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-NVD-02-005 | NVD merge/export parity regression |
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Osv/TASKS.md | DONE (2025-10-11) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-OSV-02-003 | OSV normalized versions & freshness |
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Osv/TASKS.md | DONE (2025-10-11) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-OSV-02-004 | OSV references & credits alignment |
-| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Osv/TASKS.md | TODO | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-OSV-02-005 | Fixture updater workflow
Instructions to work:
Read ./AGENTS.md and respective module AGENTS. Implement builder integration, provenance, and supporting docs using ./src/FASTER_MODELING_AND_NORMALIZATION.md and ensure outputs satisfy the precedence matrix in ./src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md. |
+| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Osv/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-OSV-02-005 | Fixture updater workflow
Resolved 2025-10-12: OSV mapper now derives canonical PURLs for Go + scoped npm packages when raw payloads omit `purl`; conflict fixtures unchanged for invalid npm names. Verified via `dotnet test src/StellaOps.Feedser.Source.Osv.Tests`, `src/StellaOps.Feedser.Source.Ghsa.Tests`, `src/StellaOps.Feedser.Source.Nvd.Tests`, and backbone normalization/storage suites. |
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Acsc/TASKS.md | Implementation DOING | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-ACSC-02-001 … 02-008 | Fetch pipeline, DTO parser, canonical mapper, fixtures, and README shipped 2025-10-12; downstream export integration still pending future tasks. |
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.Cccs/TASKS.md | Research DOING | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-CCCS-02-001 … 02-007 | Atom feed verified 2025-10-11, history/caching review and FR locale enumeration pending. |
| Sprint 2 | Connector & Data Implementation Wave | src/StellaOps.Feedser.Source.CertBund/TASKS.md | Research DOING | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-CERTBUND-02-001 … 02-007 | BSI RSS directory confirmed CERT-Bund feed 2025-10-11, history assessment pending. |
diff --git a/docs/dev/fixtures.md b/docs/dev/fixtures.md
index 06c29828..f5e18a0e 100644
--- a/docs/dev/fixtures.md
+++ b/docs/dev/fixtures.md
@@ -13,6 +13,9 @@ fixture sets, where they live, and how to regenerate them safely.
- **Regeneration:** Either run the test harness with online regeneration (`UPDATE_PARITY_FIXTURES=1 dotnet test src/StellaOps.Feedser.Source.Osv.Tests/StellaOps.Feedser.Source.Osv.Tests.csproj`)
or execute the fixture updater (`dotnet run --project tools/FixtureUpdater/FixtureUpdater.csproj`). Both paths
normalise timestamps and canonical ordering.
+- **SemVer provenance:** The regenerated fixtures should show `normalizedVersions[].notes` in the
+ `osv:{ecosystem}:{advisoryId}:{identifier}` shape emitted by `SemVerRangeRuleBuilder`. Confirm the
+ constraints and notes line up with GHSA/NVD composites before committing.
- **Verification:** Inspect the diff, then re-run `dotnet test src/StellaOps.Feedser.Source.Osv.Tests/StellaOps.Feedser.Source.Osv.Tests.csproj` to confirm parity.
## GHSA credit parity fixtures
diff --git a/docs/dev/normalized_versions_rollout.md b/docs/dev/normalized_versions_rollout.md
index 6373a162..f0c3fd6e 100644
--- a/docs/dev/normalized_versions_rollout.md
+++ b/docs/dev/normalized_versions_rollout.md
@@ -10,7 +10,7 @@ This dashboard tracks connector readiness for emitting `AffectedPackage.Normaliz
## Key milestones
-- **2025-10-13** – Normalization to finalize `SemVerRangeRuleBuilder` API contract for review.
+- **2025-10-12** – Normalization finalized `SemVerRangeRuleBuilder` API contract (multi-segment comparators + notes), connector review opens.
- **2025-10-17** – Connector owners to post fixture PRs showing `NormalizedVersions` arrays (even if feature-flagged).
- **2025-10-18** – Merge cross-connector review to validate consistent field usage before enabling union logic.
diff --git a/docs/ops/feedser-ghsa-operations.md b/docs/ops/feedser-ghsa-operations.md
index a1767ba9..04441ec8 100644
--- a/docs/ops/feedser-ghsa-operations.md
+++ b/docs/ops/feedser-ghsa-operations.md
@@ -13,20 +13,25 @@ The connector now surfaces rate-limit headers on every fetch and exposes the fol
| `ghsa.ratelimit.limit` (histogram) | Samples the reported request quota at fetch time. | `phase` = `list` or `detail`, `resource` (e.g., `core`). |
| `ghsa.ratelimit.remaining` (histogram) | Remaining requests returned by `X-RateLimit-Remaining`. | `phase`, `resource`. |
| `ghsa.ratelimit.reset_seconds` (histogram) | Seconds until `X-RateLimit-Reset`. | `phase`, `resource`. |
+| `ghsa.ratelimit.headroom_pct` (histogram) | Percentage of the quota still available (`remaining / limit * 100`). | `phase`, `resource`. |
+| `ghsa.ratelimit.headroom_pct_current` (observable gauge) | Latest headroom percentage reported per resource. | `phase`, `resource`. |
| `ghsa.ratelimit.exhausted` (counter) | Incremented whenever GitHub returns a zero remaining quota and the connector delays before retrying. | `phase`. |
### Dashboards & alerts
- Plot `ghsa.ratelimit.remaining` as the latest value to watch the runway. Alert when the value stays below **`RateLimitWarningThreshold`** (default `500`) for more than 5 minutes.
+- Use `ghsa.ratelimit.headroom_pct_current` to visualise remaining quota % — paging once it sits below **10 %** for longer than a single reset window helps avoid secondary limits.
- Raise a separate alert on `increase(ghsa.ratelimit.exhausted[15m]) > 0` to catch hard throttles.
- Overlay `ghsa.fetch.attempts` vs `ghsa.fetch.failures` to confirm retries are effective.
## 3. Logging signals
When `X-RateLimit-Remaining` falls below `RateLimitWarningThreshold`, the connector emits:
```
-GHSA rate limit warning: remaining {Remaining}/{Limit} for {Phase} {Resource}
+GHSA rate limit warning: remaining {Remaining}/{Limit} for {Phase} {Resource} (headroom {Headroom}%)
```
When GitHub reports zero remaining calls, the connector logs and sleeps for the reported `Retry-After`/`X-RateLimit-Reset` interval (falling back to `SecondaryRateLimitBackoff`).
+After the quota recovers above the warning threshold the connector writes an informational log with the refreshed remaining/headroom, letting operators clear alerts quickly.
+
## 4. Configuration knobs (`feedser.yaml`)
```yaml
feedser:
diff --git a/src/StellaOps.Feedser.Models/SemVerPrimitiveExtensions.cs b/src/StellaOps.Feedser.Models/SemVerPrimitiveExtensions.cs
index 9f03a472..e99f6fab 100644
--- a/src/StellaOps.Feedser.Models/SemVerPrimitiveExtensions.cs
+++ b/src/StellaOps.Feedser.Models/SemVerPrimitiveExtensions.cs
@@ -44,6 +44,18 @@ public static class SemVerPrimitiveExtensions
notes: resolvedNotes);
}
+ if (!string.IsNullOrEmpty(introduced) && string.IsNullOrEmpty(fixedVersion) && !string.IsNullOrEmpty(lastAffected))
+ {
+ return new NormalizedVersionRule(
+ scheme,
+ NormalizedVersionRuleTypes.Range,
+ min: introduced,
+ minInclusive: primitive.IntroducedInclusive,
+ max: lastAffected,
+ maxInclusive: primitive.LastAffectedInclusive,
+ notes: resolvedNotes);
+ }
+
if (!string.IsNullOrEmpty(introduced) && string.IsNullOrEmpty(fixedVersion) && string.IsNullOrEmpty(lastAffected))
{
var type = primitive.IntroducedInclusive ? NormalizedVersionRuleTypes.GreaterThanOrEqual : NormalizedVersionRuleTypes.GreaterThan;
diff --git a/src/StellaOps.Feedser.Normalization.Tests/SemVerRangeRuleBuilderTests.cs b/src/StellaOps.Feedser.Normalization.Tests/SemVerRangeRuleBuilderTests.cs
index 4c79b97f..43f0fdb5 100644
--- a/src/StellaOps.Feedser.Normalization.Tests/SemVerRangeRuleBuilderTests.cs
+++ b/src/StellaOps.Feedser.Normalization.Tests/SemVerRangeRuleBuilderTests.cs
@@ -110,4 +110,52 @@ public sealed class SemVerRangeRuleBuilderTests
Assert.Equal("2.5.1-alpha.1+build.7", normalized.Value);
Assert.Equal(Note, normalized.Notes);
}
+
+ [Fact]
+ public void Build_ParsesComparatorWithoutCommaSeparators()
+ {
+ var results = SemVerRangeRuleBuilder.Build(">=1.0.0 <1.2.0", null, Note);
+ var result = Assert.Single(results);
+
+ var primitive = result.Primitive;
+ Assert.Equal("1.0.0", primitive.Introduced);
+ Assert.True(primitive.IntroducedInclusive);
+ Assert.Equal("1.2.0", primitive.Fixed);
+ Assert.False(primitive.FixedInclusive);
+ Assert.Equal(">= 1.0.0, < 1.2.0", primitive.ConstraintExpression);
+
+ var normalized = result.NormalizedRule;
+ Assert.Equal(NormalizedVersionRuleTypes.Range, normalized.Type);
+ Assert.Equal("1.0.0", normalized.Min);
+ Assert.True(normalized.MinInclusive);
+ Assert.Equal("1.2.0", normalized.Max);
+ Assert.False(normalized.MaxInclusive);
+ Assert.Equal(Note, normalized.Notes);
+ }
+
+ [Fact]
+ public void Build_HandlesMultipleSegmentsSeparatedByOr()
+ {
+ var results = SemVerRangeRuleBuilder.Build(">=1.0.0 <1.2.0 || >=2.0.0 <2.2.0", null, Note);
+ Assert.Equal(2, results.Count);
+
+ var first = results[0];
+ Assert.Equal("1.0.0", first.Primitive.Introduced);
+ Assert.Equal("1.2.0", first.Primitive.Fixed);
+ Assert.Equal(NormalizedVersionRuleTypes.Range, first.NormalizedRule.Type);
+ Assert.Equal("1.0.0", first.NormalizedRule.Min);
+ Assert.Equal("1.2.0", first.NormalizedRule.Max);
+
+ var second = results[1];
+ Assert.Equal("2.0.0", second.Primitive.Introduced);
+ Assert.Equal("2.2.0", second.Primitive.Fixed);
+ Assert.Equal(NormalizedVersionRuleTypes.Range, second.NormalizedRule.Type);
+ Assert.Equal("2.0.0", second.NormalizedRule.Min);
+ Assert.Equal("2.2.0", second.NormalizedRule.Max);
+
+ foreach (var result in results)
+ {
+ Assert.Equal(Note, result.NormalizedRule.Notes);
+ }
+ }
}
diff --git a/src/StellaOps.Feedser.Normalization/SemVer/SemVerRangeRuleBuilder.cs b/src/StellaOps.Feedser.Normalization/SemVer/SemVerRangeRuleBuilder.cs
index d0a8b4b5..58f8862f 100644
--- a/src/StellaOps.Feedser.Normalization/SemVer/SemVerRangeRuleBuilder.cs
+++ b/src/StellaOps.Feedser.Normalization/SemVer/SemVerRangeRuleBuilder.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Text;
@@ -15,6 +16,7 @@ namespace StellaOps.Feedser.Normalization.SemVer;
public static class SemVerRangeRuleBuilder
{
private static readonly Regex ComparatorRegex = new(@"^(?>=|<=|>|<|==|=)\s*(?.+)$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
+ private static readonly Regex ComparatorTokenRegex = new(@"(?(?>=|<=|>|<|==|=)\s*(?[^,\s\|]+))", RegexOptions.Compiled | RegexOptions.CultureInvariant);
private static readonly Regex HyphenRegex = new(@"^\s*(?.+?)\s+-\s+(?.+)\s*$", RegexOptions.Compiled | RegexOptions.CultureInvariant);
private static readonly char[] SegmentTrimCharacters = { '(', ')', '[', ']', '{', '}', ';' };
private static readonly char[] FragmentSplitCharacters = { ',', ' ' };
@@ -303,21 +305,29 @@ public static class SemVerRangeRuleBuilder
foreach (var fragment in fragments)
{
- if (TryParseComparatorFragment(fragment, constraintTokens, ref introduced, ref introducedInclusive, ref hasIntroduced, ref fixedVersion, ref fixedInclusive, ref hasFixed, ref lastAffected, ref lastInclusive, ref hasLast, ref exactValue))
- {
- continue;
- }
-
- var parts = fragment.Split(FragmentSplitCharacters, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
var handled = false;
- foreach (var part in parts)
+
+ foreach (Match match in ComparatorTokenRegex.Matches(fragment))
{
- if (TryParseComparatorFragment(part, constraintTokens, ref introduced, ref introducedInclusive, ref hasIntroduced, ref fixedVersion, ref fixedInclusive, ref hasFixed, ref lastAffected, ref lastInclusive, ref hasLast, ref exactValue))
+ if (match.Groups["token"].Success
+ && TryParseComparatorFragment(match.Groups["token"].Value, constraintTokens, ref introduced, ref introducedInclusive, ref hasIntroduced, ref fixedVersion, ref fixedInclusive, ref hasFixed, ref lastAffected, ref lastInclusive, ref hasLast, ref exactValue))
{
handled = true;
}
}
+ if (!handled)
+ {
+ var parts = fragment.Split(FragmentSplitCharacters, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
+ foreach (var part in parts)
+ {
+ if (TryParseComparatorFragment(part, constraintTokens, ref introduced, ref introducedInclusive, ref hasIntroduced, ref fixedVersion, ref fixedInclusive, ref hasFixed, ref lastAffected, ref lastInclusive, ref hasLast, ref exactValue))
+ {
+ handled = true;
+ }
+ }
+ }
+
if (handled)
{
continue;
@@ -339,7 +349,8 @@ public static class SemVerRangeRuleBuilder
FixedInclusive: true,
LastAffected: null,
LastAffectedInclusive: false,
- ConstraintExpression: constraintTokens.Count > 0 ? string.Join(", ", constraintTokens) : expression.Trim());
+ ConstraintExpression: constraintTokens.Count > 0 ? string.Join(", ", constraintTokens) : expression.Trim(),
+ ExactValue: exactValue);
return true;
}
@@ -426,32 +437,32 @@ public static class SemVerRangeRuleBuilder
switch (op)
{
case ">=":
- introduced = value;
+ introduced = value!;
introducedInclusive = true;
hasIntroduced = true;
constraintTokens.Add($">= {value}");
break;
case ">":
- introduced = value;
+ introduced = value!;
introducedInclusive = false;
hasIntroduced = true;
constraintTokens.Add($"> {value}");
break;
case "<=":
- lastAffected = value;
+ lastAffected = value!;
lastInclusive = true;
hasLast = true;
constraintTokens.Add($"<= {value}");
break;
case "<":
- fixedVersion = value;
+ fixedVersion = value!;
fixedInclusive = false;
hasFixed = true;
constraintTokens.Add($"< {value}");
break;
case "=":
case "==":
- exactValue = value;
+ exactValue = value!;
constraintTokens.Add($"= {value}");
break;
}
@@ -459,7 +470,7 @@ public static class SemVerRangeRuleBuilder
return true;
}
- private static bool TryNormalizeVersion(string? value, out string normalized)
+ private static bool TryNormalizeVersion(string? value, [NotNullWhen(true)] out string normalized)
{
normalized = string.Empty;
if (string.IsNullOrWhiteSpace(value))
@@ -492,22 +503,23 @@ public static class SemVerRangeRuleBuilder
return true;
}
- private static bool TryParseSemanticVersion(string value, out SemanticVersion version, out string normalized)
+ private static bool TryParseSemanticVersion(string value, [NotNullWhen(true)] out SemanticVersion version, out string normalized)
{
- version = null!;
normalized = string.Empty;
var candidate = RemoveLeadingV(value);
- if (!SemanticVersion.TryParse(candidate, out version))
+ if (!SemanticVersion.TryParse(candidate, out var parsed))
{
candidate = ExpandSemanticVersion(candidate);
- if (!SemanticVersion.TryParse(candidate, out version))
+ if (!SemanticVersion.TryParse(candidate, out parsed))
{
+ version = null!;
return false;
}
}
- normalized = FormatVersion(version);
+ version = parsed!;
+ normalized = FormatVersion(parsed);
return true;
}
diff --git a/src/StellaOps.Feedser.Normalization/TASKS.md b/src/StellaOps.Feedser.Normalization/TASKS.md
index 8d547682..ed72034b 100644
--- a/src/StellaOps.Feedser.Normalization/TASKS.md
+++ b/src/StellaOps.Feedser.Normalization/TASKS.md
@@ -4,5 +4,6 @@
|Canonical NEVRA/EVR parsing helpers|BE-Norm (Distro WG)|Models|DONE – `Normalization.Distro` exposes parsers + canonical formatters consumed by Merge comparers/tests.|
|PURL/CPE identifier normalization|BE-Norm (OSS WG)|Models|DONE – canonical PURL/CPE helpers feed connectors and exporter tooling.|
|CPE normalization escape handling|BE-Norm (OSS WG)|Normalization identifiers|DONE – percent-decoding, edition sub-field expansion, and deterministic escaping landed in `Cpe23` with new tests covering boundary cases.|
-|CVSS metric normalization & severity bands|BE-Norm (Risk WG)|Models|DONE – `CvssMetricNormalizer` unifies vectors, recomputes scores/severities, and is wired through NVD/RedHat/JVN mappers with unit coverage.|
-|Description and locale normalization pipeline|BE-Norm (I18N)|Source connectors|DONE – `DescriptionNormalizer` strips markup, collapses whitespace, and provides locale fallback used by core mappers.|
+|CVSS metric normalization & severity bands|BE-Norm (Risk WG)|Models|DONE – `CvssMetricNormalizer` unifies vectors, recomputes scores/severities, and is wired through NVD/RedHat/JVN mappers with unit coverage.|
+|Description and locale normalization pipeline|BE-Norm (I18N)|Source connectors|DONE – `DescriptionNormalizer` strips markup, collapses whitespace, and provides locale fallback used by core mappers.|
+|SemVer normalized rule emitter (FEEDNORM-NORM-02-001)|BE-Norm (SemVer WG)|Models, `FASTER_MODELING_AND_NORMALIZATION.md`|**DONE (2025-10-12)** – `SemVerRangeRuleBuilder` now parses comparator chains without comma delimiters, supports multi-segment `||` ranges, pushes exact-value metadata, and new tests document the contract for connector teams.|
diff --git a/src/StellaOps.Feedser.Source.Ghsa/GhsaConnector.cs b/src/StellaOps.Feedser.Source.Ghsa/GhsaConnector.cs
index c375c4ba..03bc591c 100644
--- a/src/StellaOps.Feedser.Source.Ghsa/GhsaConnector.cs
+++ b/src/StellaOps.Feedser.Source.Ghsa/GhsaConnector.cs
@@ -37,6 +37,8 @@ public sealed class GhsaConnector : IFeedConnector
private readonly GhsaDiagnostics _diagnostics;
private readonly TimeProvider _timeProvider;
private readonly ILogger _logger;
+ private readonly object _rateLimitWarningLock = new();
+ private readonly Dictionary<(string Phase, string Resource), bool> _rateLimitWarnings = new();
public GhsaConnector(
SourceFetchService fetchService,
@@ -412,6 +414,62 @@ public sealed class GhsaConnector : IFeedConnector
await _stateRepository.UpdateCursorAsync(SourceName, cursor.ToBsonDocument(), _timeProvider.GetUtcNow(), cancellationToken).ConfigureAwait(false);
}
+ private bool ShouldLogRateLimitWarning(in GhsaRateLimitSnapshot snapshot, out bool recovered)
+ {
+ recovered = false;
+
+ if (!snapshot.Remaining.HasValue)
+ {
+ return false;
+ }
+
+ var key = (snapshot.Phase, snapshot.Resource ?? "global");
+ var warn = snapshot.Remaining.Value <= _options.RateLimitWarningThreshold;
+
+ lock (_rateLimitWarningLock)
+ {
+ var previouslyWarned = _rateLimitWarnings.TryGetValue(key, out var flagged) && flagged;
+
+ if (warn)
+ {
+ if (previouslyWarned)
+ {
+ return false;
+ }
+
+ _rateLimitWarnings[key] = true;
+ return true;
+ }
+
+ if (previouslyWarned)
+ {
+ _rateLimitWarnings.Remove(key);
+ recovered = true;
+ }
+
+ return false;
+ }
+ }
+
+ private static double? CalculateHeadroomPercentage(in GhsaRateLimitSnapshot snapshot)
+ {
+ if (!snapshot.Limit.HasValue || !snapshot.Remaining.HasValue)
+ {
+ return null;
+ }
+
+ var limit = snapshot.Limit.Value;
+ if (limit <= 0)
+ {
+ return null;
+ }
+
+ return (double)snapshot.Remaining.Value / limit * 100d;
+ }
+
+ private static string FormatHeadroom(double? headroomPct)
+ => headroomPct.HasValue ? $" (headroom {headroomPct.Value:F1}%)" : string.Empty;
+
private async Task ApplyRateLimitAsync(IReadOnlyDictionary? headers, string phase, CancellationToken cancellationToken)
{
var snapshot = GhsaRateLimitParser.TryParse(headers, _timeProvider.GetUtcNow(), phase);
@@ -422,19 +480,31 @@ public sealed class GhsaConnector : IFeedConnector
_diagnostics.RecordRateLimit(snapshot.Value);
- if (snapshot.Value.Remaining.HasValue && snapshot.Value.Remaining.Value <= _options.RateLimitWarningThreshold)
+ var headroomPct = CalculateHeadroomPercentage(snapshot.Value);
+ if (ShouldLogRateLimitWarning(snapshot.Value, out var recovered))
{
var resetMessage = snapshot.Value.ResetAfter.HasValue
? $" (resets in {snapshot.Value.ResetAfter.Value:c})"
: snapshot.Value.ResetAt.HasValue ? $" (resets at {snapshot.Value.ResetAt.Value:O})" : string.Empty;
_logger.LogWarning(
- "GHSA rate limit warning: remaining {Remaining} of {Limit} for {Phase} {Resource}{ResetMessage}",
+ "GHSA rate limit warning: remaining {Remaining} of {Limit} for {Phase} {Resource}{ResetMessage}{Headroom}",
snapshot.Value.Remaining,
snapshot.Value.Limit,
phase,
snapshot.Value.Resource ?? "global",
- resetMessage);
+ resetMessage,
+ FormatHeadroom(headroomPct));
+ }
+ else if (recovered)
+ {
+ _logger.LogInformation(
+ "GHSA rate limit recovered for {Phase} {Resource}: remaining {Remaining} of {Limit}{Headroom}",
+ phase,
+ snapshot.Value.Resource ?? "global",
+ snapshot.Value.Remaining,
+ snapshot.Value.Limit,
+ FormatHeadroom(headroomPct));
}
if (snapshot.Value.Remaining.HasValue && snapshot.Value.Remaining.Value <= 0)
@@ -445,10 +515,11 @@ public sealed class GhsaConnector : IFeedConnector
if (delay > TimeSpan.Zero)
{
_logger.LogWarning(
- "GHSA rate limit exhausted for {Phase} {Resource}; delaying {Delay}",
+ "GHSA rate limit exhausted for {Phase} {Resource}; delaying {Delay}{Headroom}",
phase,
snapshot.Value.Resource ?? "global",
- delay);
+ delay,
+ FormatHeadroom(headroomPct));
await Task.Delay(delay, cancellationToken).ConfigureAwait(false);
}
diff --git a/src/StellaOps.Feedser.Source.Ghsa/Internal/GhsaDiagnostics.cs b/src/StellaOps.Feedser.Source.Ghsa/Internal/GhsaDiagnostics.cs
index a5bbaa80..d1bb313d 100644
--- a/src/StellaOps.Feedser.Source.Ghsa/Internal/GhsaDiagnostics.cs
+++ b/src/StellaOps.Feedser.Source.Ghsa/Internal/GhsaDiagnostics.cs
@@ -1,3 +1,4 @@
+using System.Collections.Generic;
using System.Diagnostics.Metrics;
namespace StellaOps.Feedser.Source.Ghsa.Internal;
@@ -19,9 +20,12 @@ public sealed class GhsaDiagnostics : IDisposable
private readonly Histogram _rateLimitRemaining;
private readonly Histogram _rateLimitLimit;
private readonly Histogram _rateLimitResetSeconds;
+ private readonly Histogram _rateLimitHeadroomPct;
+ private readonly ObservableGauge _rateLimitHeadroomGauge;
private readonly Counter _rateLimitExhausted;
private readonly object _rateLimitLock = new();
private GhsaRateLimitSnapshot? _lastRateLimitSnapshot;
+ private readonly Dictionary<(string Phase, string? Resource), GhsaRateLimitSnapshot> _rateLimitSnapshots = new();
public GhsaDiagnostics()
{
@@ -37,6 +41,8 @@ public sealed class GhsaDiagnostics : IDisposable
_rateLimitRemaining = _meter.CreateHistogram("ghsa.ratelimit.remaining", unit: "requests");
_rateLimitLimit = _meter.CreateHistogram("ghsa.ratelimit.limit", unit: "requests");
_rateLimitResetSeconds = _meter.CreateHistogram("ghsa.ratelimit.reset_seconds", unit: "s");
+ _rateLimitHeadroomPct = _meter.CreateHistogram("ghsa.ratelimit.headroom_pct", unit: "percent");
+ _rateLimitHeadroomGauge = _meter.CreateObservableGauge("ghsa.ratelimit.headroom_pct_current", ObserveHeadroom, unit: "percent");
_rateLimitExhausted = _meter.CreateCounter("ghsa.ratelimit.exhausted", unit: "events");
}
@@ -79,9 +85,15 @@ public sealed class GhsaDiagnostics : IDisposable
_rateLimitResetSeconds.Record(snapshot.ResetAfter.Value.TotalSeconds, tags);
}
+ if (TryCalculateHeadroom(snapshot, out var headroom))
+ {
+ _rateLimitHeadroomPct.Record(headroom, tags);
+ }
+
lock (_rateLimitLock)
{
_lastRateLimitSnapshot = snapshot;
+ _rateLimitSnapshots[(snapshot.Phase, snapshot.Resource)] = snapshot;
}
}
@@ -96,5 +108,48 @@ public sealed class GhsaDiagnostics : IDisposable
}
}
- public void Dispose() => _meter.Dispose();
+ private IEnumerable> ObserveHeadroom()
+ {
+ lock (_rateLimitLock)
+ {
+ if (_rateLimitSnapshots.Count == 0)
+ {
+ yield break;
+ }
+
+ foreach (var snapshot in _rateLimitSnapshots.Values)
+ {
+ if (TryCalculateHeadroom(snapshot, out var headroom))
+ {
+ yield return new Measurement(
+ headroom,
+ new KeyValuePair("phase", snapshot.Phase),
+ new KeyValuePair("resource", snapshot.Resource ?? "unknown"));
+ }
+ }
+ }
+ }
+
+ private static bool TryCalculateHeadroom(in GhsaRateLimitSnapshot snapshot, out double headroomPct)
+ {
+ headroomPct = 0;
+ if (!snapshot.Limit.HasValue || !snapshot.Remaining.HasValue)
+ {
+ return false;
+ }
+
+ var limit = snapshot.Limit.Value;
+ if (limit <= 0)
+ {
+ return false;
+ }
+
+ headroomPct = (double)snapshot.Remaining.Value / limit * 100d;
+ return true;
+ }
+
+ public void Dispose()
+ {
+ _meter.Dispose();
+ }
}
diff --git a/src/StellaOps.Feedser.Source.Ghsa/TASKS.md b/src/StellaOps.Feedser.Source.Ghsa/TASKS.md
index 0affb8a6..0c551d1c 100644
--- a/src/StellaOps.Feedser.Source.Ghsa/TASKS.md
+++ b/src/StellaOps.Feedser.Source.Ghsa/TASKS.md
@@ -11,5 +11,7 @@
|Production credential & scheduler rollout|Ops, BE-Conn-GHSA|Docs, WebService|**DONE (2025-10-12)** – Scheduler defaults registered via `JobSchedulerBuilder`, credential provisioning documented (Compose/Helm samples), and staged backfill guidance captured in `docs/ops/feedser-ghsa-operations.md`.|
|FEEDCONN-GHSA-04-002 Conflict regression fixtures|BE-Conn-GHSA, QA|Merge `FEEDMERGE-ENGINE-04-001`|**DONE (2025-10-12)** – Added `conflict-ghsa.canonical.json` + `GhsaConflictFixtureTests`; SemVer ranges and credits align with merge precedence triple and shareable with QA. Validation: `dotnet test src/StellaOps.Feedser.Source.Ghsa.Tests/StellaOps.Feedser.Source.Ghsa.Tests.csproj --filter GhsaConflictFixtureTests`.|
|FEEDCONN-GHSA-02-004 GHSA credits & ecosystem severity mapping|BE-Conn-GHSA|Models `FEEDMODELS-SCHEMA-01-002`|**DONE (2025-10-11)** – Mapper emits advisory credits with provenance masks, fixtures assert role/contact ordering, and severity normalization remains unchanged.|
-|FEEDCONN-GHSA-02-007 Credit parity regression fixtures|BE-Conn-GHSA, QA|Source.Nvd, Source.Osv|**DONE (2025-10-12)** – Credit parity fixtures recorded, regression tests cover GHSA/OSV/NVD alignment, and regeneration workflow documented in `docs/dev/fixtures.md`.|
+|FEEDCONN-GHSA-02-007 Credit parity regression fixtures|BE-Conn-GHSA, QA|Source.Nvd, Source.Osv|**DONE (2025-10-12)** – Parity fixtures regenerated via `tools/FixtureUpdater`, normalized SemVer notes verified against GHSA/NVD/OSV snapshots, and the fixtures guide now documents the headroom checks.|
|FEEDCONN-GHSA-02-001 Normalized versions rollout|BE-Conn-GHSA|Models `FEEDMODELS-SCHEMA-01-003`, Normalization playbook|**DONE (2025-10-11)** – GHSA mapper now emits SemVer primitives + normalized ranges, fixtures refreshed, connector tests passing; report logged via FEEDMERGE-COORD-02-900.|
+|FEEDCONN-GHSA-02-005 Quota monitoring hardening|BE-Conn-GHSA, Observability|Source.Common metrics|**DONE (2025-10-12)** – Diagnostics expose headroom histograms/gauges, warning logs dedupe below the configured threshold, and the ops runbook gained alerting and mitigation guidance.|
+|FEEDCONN-GHSA-02-006 Scheduler rollout integration|BE-Conn-GHSA, Ops|Job scheduler|**DONE (2025-10-12)** – Dependency routine tests assert cron/timeouts, and the runbook highlights cron overrides plus backoff toggles for staged rollouts.|
diff --git a/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-invalid-schema.json b/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-invalid-schema.json
index 02b611d5..cefb4b2f 100644
--- a/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-invalid-schema.json
+++ b/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-invalid-schema.json
@@ -1,6 +1,6 @@
-{
- "resultsPerPage": 1,
- "startIndex": 0,
- "totalResults": 1,
- "vulnerabilities": "this-should-be-an-array"
-}
+{
+ "resultsPerPage": 1,
+ "startIndex": 0,
+ "totalResults": 1,
+ "vulnerabilities": "this-should-be-an-array"
+}
diff --git a/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-multipage-1.json b/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-multipage-1.json
index e6a45070..ed90665d 100644
--- a/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-multipage-1.json
+++ b/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-multipage-1.json
@@ -1,69 +1,69 @@
-{
- "resultsPerPage": 2,
- "startIndex": 0,
- "totalResults": 5,
- "vulnerabilities": [
- {
- "cve": {
- "id": "CVE-2024-1000",
- "sourceIdentifier": "nvd@nist.gov",
- "published": "2024-02-01T10:00:00Z",
- "lastModified": "2024-02-02T10:00:00Z",
- "descriptions": [
- { "lang": "en", "value": "Multipage vulnerability one." }
- ],
- "metrics": {
- "cvssMetricV31": [
- {
- "cvssData": {
- "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
- "baseScore": 9.8,
- "baseSeverity": "CRITICAL"
- }
- }
- ]
- },
- "configurations": {
- "nodes": [
- {
- "cpeMatch": [
- { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_a:1.0:*:*:*:*:*:*:*" }
- ]
- }
- ]
- }
- }
- },
- {
- "cve": {
- "id": "CVE-2024-1001",
- "sourceIdentifier": "nvd@nist.gov",
- "published": "2024-02-01T11:00:00Z",
- "lastModified": "2024-02-02T11:00:00Z",
- "descriptions": [
- { "lang": "en", "value": "Multipage vulnerability two." }
- ],
- "metrics": {
- "cvssMetricV31": [
- {
- "cvssData": {
- "vectorString": "CVSS:3.1/AV:P/AC:L/PR:L/UI:R/S:U/C:L/I:L/A:L",
- "baseScore": 5.1,
- "baseSeverity": "MEDIUM"
- }
- }
- ]
- },
- "configurations": {
- "nodes": [
- {
- "cpeMatch": [
- { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_b:2.0:*:*:*:*:*:*:*" }
- ]
- }
- ]
- }
- }
- }
- ]
-}
+{
+ "resultsPerPage": 2,
+ "startIndex": 0,
+ "totalResults": 5,
+ "vulnerabilities": [
+ {
+ "cve": {
+ "id": "CVE-2024-1000",
+ "sourceIdentifier": "nvd@nist.gov",
+ "published": "2024-02-01T10:00:00Z",
+ "lastModified": "2024-02-02T10:00:00Z",
+ "descriptions": [
+ { "lang": "en", "value": "Multipage vulnerability one." }
+ ],
+ "metrics": {
+ "cvssMetricV31": [
+ {
+ "cvssData": {
+ "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
+ "baseScore": 9.8,
+ "baseSeverity": "CRITICAL"
+ }
+ }
+ ]
+ },
+ "configurations": {
+ "nodes": [
+ {
+ "cpeMatch": [
+ { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_a:1.0:*:*:*:*:*:*:*" }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "cve": {
+ "id": "CVE-2024-1001",
+ "sourceIdentifier": "nvd@nist.gov",
+ "published": "2024-02-01T11:00:00Z",
+ "lastModified": "2024-02-02T11:00:00Z",
+ "descriptions": [
+ { "lang": "en", "value": "Multipage vulnerability two." }
+ ],
+ "metrics": {
+ "cvssMetricV31": [
+ {
+ "cvssData": {
+ "vectorString": "CVSS:3.1/AV:P/AC:L/PR:L/UI:R/S:U/C:L/I:L/A:L",
+ "baseScore": 5.1,
+ "baseSeverity": "MEDIUM"
+ }
+ }
+ ]
+ },
+ "configurations": {
+ "nodes": [
+ {
+ "cpeMatch": [
+ { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_b:2.0:*:*:*:*:*:*:*" }
+ ]
+ }
+ ]
+ }
+ }
+ }
+ ]
+}
diff --git a/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-multipage-2.json b/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-multipage-2.json
index 0270b45d..530ecdf3 100644
--- a/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-multipage-2.json
+++ b/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-multipage-2.json
@@ -1,69 +1,69 @@
-{
- "resultsPerPage": 2,
- "startIndex": 2,
- "totalResults": 5,
- "vulnerabilities": [
- {
- "cve": {
- "id": "CVE-2024-1002",
- "sourceIdentifier": "nvd@nist.gov",
- "published": "2024-02-01T12:00:00Z",
- "lastModified": "2024-02-02T12:00:00Z",
- "descriptions": [
- { "lang": "en", "value": "Multipage vulnerability three." }
- ],
- "metrics": {
- "cvssMetricV31": [
- {
- "cvssData": {
- "vectorString": "CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N",
- "baseScore": 3.1,
- "baseSeverity": "LOW"
- }
- }
- ]
- },
- "configurations": {
- "nodes": [
- {
- "cpeMatch": [
- { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_c:3.0:*:*:*:*:*:*:*" }
- ]
- }
- ]
- }
- }
- },
- {
- "cve": {
- "id": "CVE-2024-1003",
- "sourceIdentifier": "nvd@nist.gov",
- "published": "2024-02-01T13:00:00Z",
- "lastModified": "2024-02-02T13:00:00Z",
- "descriptions": [
- { "lang": "en", "value": "Multipage vulnerability four." }
- ],
- "metrics": {
- "cvssMetricV31": [
- {
- "cvssData": {
- "vectorString": "CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:M/I:L/A:L",
- "baseScore": 7.4,
- "baseSeverity": "HIGH"
- }
- }
- ]
- },
- "configurations": {
- "nodes": [
- {
- "cpeMatch": [
- { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_d:4.0:*:*:*:*:*:*:*" }
- ]
- }
- ]
- }
- }
- }
- ]
-}
+{
+ "resultsPerPage": 2,
+ "startIndex": 2,
+ "totalResults": 5,
+ "vulnerabilities": [
+ {
+ "cve": {
+ "id": "CVE-2024-1002",
+ "sourceIdentifier": "nvd@nist.gov",
+ "published": "2024-02-01T12:00:00Z",
+ "lastModified": "2024-02-02T12:00:00Z",
+ "descriptions": [
+ { "lang": "en", "value": "Multipage vulnerability three." }
+ ],
+ "metrics": {
+ "cvssMetricV31": [
+ {
+ "cvssData": {
+ "vectorString": "CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N",
+ "baseScore": 3.1,
+ "baseSeverity": "LOW"
+ }
+ }
+ ]
+ },
+ "configurations": {
+ "nodes": [
+ {
+ "cpeMatch": [
+ { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_c:3.0:*:*:*:*:*:*:*" }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "cve": {
+ "id": "CVE-2024-1003",
+ "sourceIdentifier": "nvd@nist.gov",
+ "published": "2024-02-01T13:00:00Z",
+ "lastModified": "2024-02-02T13:00:00Z",
+ "descriptions": [
+ { "lang": "en", "value": "Multipage vulnerability four." }
+ ],
+ "metrics": {
+ "cvssMetricV31": [
+ {
+ "cvssData": {
+ "vectorString": "CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:M/I:L/A:L",
+ "baseScore": 7.4,
+ "baseSeverity": "HIGH"
+ }
+ }
+ ]
+ },
+ "configurations": {
+ "nodes": [
+ {
+ "cpeMatch": [
+ { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_d:4.0:*:*:*:*:*:*:*" }
+ ]
+ }
+ ]
+ }
+ }
+ }
+ ]
+}
diff --git a/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-multipage-3.json b/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-multipage-3.json
index 9b0df922..42cf57dc 100644
--- a/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-multipage-3.json
+++ b/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-multipage-3.json
@@ -1,38 +1,38 @@
-{
- "resultsPerPage": 2,
- "startIndex": 4,
- "totalResults": 5,
- "vulnerabilities": [
- {
- "cve": {
- "id": "CVE-2024-1004",
- "sourceIdentifier": "nvd@nist.gov",
- "published": "2024-02-01T14:00:00Z",
- "lastModified": "2024-02-02T14:00:00Z",
- "descriptions": [
- { "lang": "en", "value": "Multipage vulnerability five." }
- ],
- "metrics": {
- "cvssMetricV31": [
- {
- "cvssData": {
- "vectorString": "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:H/A:L",
- "baseScore": 7.9,
- "baseSeverity": "HIGH"
- }
- }
- ]
- },
- "configurations": {
- "nodes": [
- {
- "cpeMatch": [
- { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_e:5.0:*:*:*:*:*:*:*" }
- ]
- }
- ]
- }
- }
- }
- ]
-}
+{
+ "resultsPerPage": 2,
+ "startIndex": 4,
+ "totalResults": 5,
+ "vulnerabilities": [
+ {
+ "cve": {
+ "id": "CVE-2024-1004",
+ "sourceIdentifier": "nvd@nist.gov",
+ "published": "2024-02-01T14:00:00Z",
+ "lastModified": "2024-02-02T14:00:00Z",
+ "descriptions": [
+ { "lang": "en", "value": "Multipage vulnerability five." }
+ ],
+ "metrics": {
+ "cvssMetricV31": [
+ {
+ "cvssData": {
+ "vectorString": "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:H/A:L",
+ "baseScore": 7.9,
+ "baseSeverity": "HIGH"
+ }
+ }
+ ]
+ },
+ "configurations": {
+ "nodes": [
+ {
+ "cpeMatch": [
+ { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_e:5.0:*:*:*:*:*:*:*" }
+ ]
+ }
+ ]
+ }
+ }
+ }
+ ]
+}
diff --git a/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-window-1.json b/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-window-1.json
index 1d1dd348..0890cb62 100644
--- a/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-window-1.json
+++ b/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-window-1.json
@@ -1,23 +1,23 @@
-{
- "resultsPerPage": 2000,
- "startIndex": 0,
- "totalResults": 2,
- "vulnerabilities": [
- {
- "cve": {
- "id": "CVE-2024-0001",
- "sourceIdentifier": "nvd@nist.gov",
- "published": "2024-01-01T10:00:00Z",
- "lastModified": "2024-01-02T10:00:00Z",
- "descriptions": [
- { "lang": "en", "value": "Example vulnerability one." }
- ],
- "references": [
- {
- "url": "https://vendor.example.com/advisories/0001",
- "source": "Vendor",
- "tags": ["Vendor Advisory"]
- }
+{
+ "resultsPerPage": 2000,
+ "startIndex": 0,
+ "totalResults": 2,
+ "vulnerabilities": [
+ {
+ "cve": {
+ "id": "CVE-2024-0001",
+ "sourceIdentifier": "nvd@nist.gov",
+ "published": "2024-01-01T10:00:00Z",
+ "lastModified": "2024-01-02T10:00:00Z",
+ "descriptions": [
+ { "lang": "en", "value": "Example vulnerability one." }
+ ],
+ "references": [
+ {
+ "url": "https://vendor.example.com/advisories/0001",
+ "source": "Vendor",
+ "tags": ["Vendor Advisory"]
+ }
],
"weaknesses": [
{
@@ -28,43 +28,43 @@
}
],
"metrics": {
- "cvssMetricV31": [
- {
- "cvssData": {
- "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
- "baseScore": 9.8,
- "baseSeverity": "CRITICAL"
- }
- }
- ]
- },
- "configurations": {
- "nodes": [
- {
- "cpeMatch": [
- { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_one:1.0:*:*:*:*:*:*:*" }
- ]
- }
- ]
- }
- }
- },
- {
- "cve": {
- "id": "CVE-2024-0002",
- "sourceIdentifier": "nvd@nist.gov",
- "published": "2024-01-01T11:00:00Z",
- "lastModified": "2024-01-02T11:00:00Z",
- "descriptions": [
- { "lang": "fr", "value": "Description française" },
- { "lang": "en", "value": "Example vulnerability two." }
- ],
- "references": [
- {
- "url": "https://cisa.example.gov/alerts/0002",
- "source": "CISA",
- "tags": ["US Government Resource"]
- }
+ "cvssMetricV31": [
+ {
+ "cvssData": {
+ "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
+ "baseScore": 9.8,
+ "baseSeverity": "CRITICAL"
+ }
+ }
+ ]
+ },
+ "configurations": {
+ "nodes": [
+ {
+ "cpeMatch": [
+ { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_one:1.0:*:*:*:*:*:*:*" }
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "cve": {
+ "id": "CVE-2024-0002",
+ "sourceIdentifier": "nvd@nist.gov",
+ "published": "2024-01-01T11:00:00Z",
+ "lastModified": "2024-01-02T11:00:00Z",
+ "descriptions": [
+ { "lang": "fr", "value": "Description française" },
+ { "lang": "en", "value": "Example vulnerability two." }
+ ],
+ "references": [
+ {
+ "url": "https://cisa.example.gov/alerts/0002",
+ "source": "CISA",
+ "tags": ["US Government Resource"]
+ }
],
"weaknesses": [
{
@@ -75,27 +75,27 @@
}
],
"metrics": {
- "cvssMetricV30": [
- {
- "cvssData": {
- "vectorString": "CVSS:3.0/AV:L/AC:H/PR:L/UI:R/S:U/C:L/I:L/A:L",
- "baseScore": 4.6,
- "baseSeverity": "MEDIUM"
- }
- }
- ]
- },
- "configurations": {
- "nodes": [
- {
- "cpeMatch": [
- { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_two:2.0:*:*:*:*:*:*:*" },
- { "vulnerable": false, "criteria": "cpe:2.3:a:example:product_two:2.1:*:*:*:*:*:*:*" }
- ]
- }
- ]
- }
- }
- }
- ]
-}
+ "cvssMetricV30": [
+ {
+ "cvssData": {
+ "vectorString": "CVSS:3.0/AV:L/AC:H/PR:L/UI:R/S:U/C:L/I:L/A:L",
+ "baseScore": 4.6,
+ "baseSeverity": "MEDIUM"
+ }
+ }
+ ]
+ },
+ "configurations": {
+ "nodes": [
+ {
+ "cpeMatch": [
+ { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_two:2.0:*:*:*:*:*:*:*" },
+ { "vulnerable": false, "criteria": "cpe:2.3:a:example:product_two:2.1:*:*:*:*:*:*:*" }
+ ]
+ }
+ ]
+ }
+ }
+ }
+ ]
+}
diff --git a/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-window-2.json b/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-window-2.json
index 6220fe5a..bf68d9b9 100644
--- a/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-window-2.json
+++ b/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-window-2.json
@@ -1,45 +1,45 @@
-{
- "resultsPerPage": 2000,
- "startIndex": 0,
- "totalResults": 1,
- "vulnerabilities": [
- {
- "cve": {
- "id": "CVE-2024-0003",
- "sourceIdentifier": "nvd@nist.gov",
- "published": "2024-01-01T12:00:00Z",
- "lastModified": "2024-01-02T12:00:00Z",
- "descriptions": [
- { "lang": "en", "value": "Example vulnerability three." }
- ],
- "references": [
- {
- "url": "https://example.org/patches/0003",
- "source": "Vendor",
- "tags": ["Patch"]
- }
- ],
- "metrics": {
- "cvssMetricV2": [
- {
- "cvssData": {
- "vectorString": "AV:N/AC:M/Au:N/C:P/I:P/A:P",
- "baseScore": 6.8,
- "baseSeverity": "MEDIUM"
- }
- }
- ]
- },
- "configurations": {
- "nodes": [
- {
- "cpeMatch": [
- { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_three:3.5:*:*:*:*:*:*:*" }
- ]
- }
- ]
- }
- }
- }
- ]
-}
+{
+ "resultsPerPage": 2000,
+ "startIndex": 0,
+ "totalResults": 1,
+ "vulnerabilities": [
+ {
+ "cve": {
+ "id": "CVE-2024-0003",
+ "sourceIdentifier": "nvd@nist.gov",
+ "published": "2024-01-01T12:00:00Z",
+ "lastModified": "2024-01-02T12:00:00Z",
+ "descriptions": [
+ { "lang": "en", "value": "Example vulnerability three." }
+ ],
+ "references": [
+ {
+ "url": "https://example.org/patches/0003",
+ "source": "Vendor",
+ "tags": ["Patch"]
+ }
+ ],
+ "metrics": {
+ "cvssMetricV2": [
+ {
+ "cvssData": {
+ "vectorString": "AV:N/AC:M/Au:N/C:P/I:P/A:P",
+ "baseScore": 6.8,
+ "baseSeverity": "MEDIUM"
+ }
+ }
+ ]
+ },
+ "configurations": {
+ "nodes": [
+ {
+ "cpeMatch": [
+ { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_three:3.5:*:*:*:*:*:*:*" }
+ ]
+ }
+ ]
+ }
+ }
+ }
+ ]
+}
diff --git a/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-window-update.json b/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-window-update.json
index 65ad963f..f7be7b3a 100644
--- a/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-window-update.json
+++ b/src/StellaOps.Feedser.Source.Nvd.Tests/Nvd/Fixtures/nvd-window-update.json
@@ -1,51 +1,51 @@
-{
- "resultsPerPage": 2000,
- "startIndex": 0,
- "totalResults": 1,
- "vulnerabilities": [
- {
- "cve": {
- "id": "CVE-2024-0001",
- "sourceIdentifier": "nvd@nist.gov",
- "published": "2024-01-01T10:00:00Z",
- "lastModified": "2024-01-03T12:00:00Z",
- "descriptions": [
- { "lang": "en", "value": "Example vulnerability one updated." }
- ],
- "references": [
- {
- "url": "https://vendor.example.com/advisories/0001",
- "source": "Vendor",
- "tags": ["Vendor Advisory"]
- },
- {
- "url": "https://kb.example.com/articles/0001",
- "source": "KnowledgeBase",
- "tags": ["Third Party Advisory"]
- }
- ],
- "metrics": {
- "cvssMetricV31": [
- {
- "cvssData": {
- "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
- "baseScore": 8.8,
- "baseSeverity": "HIGH"
- }
- }
- ]
- },
- "configurations": {
- "nodes": [
- {
- "cpeMatch": [
- { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_one:1.0:*:*:*:*:*:*:*" },
- { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_one:1.1:*:*:*:*:*:*:*" }
- ]
- }
- ]
- }
- }
- }
- ]
-}
+{
+ "resultsPerPage": 2000,
+ "startIndex": 0,
+ "totalResults": 1,
+ "vulnerabilities": [
+ {
+ "cve": {
+ "id": "CVE-2024-0001",
+ "sourceIdentifier": "nvd@nist.gov",
+ "published": "2024-01-01T10:00:00Z",
+ "lastModified": "2024-01-03T12:00:00Z",
+ "descriptions": [
+ { "lang": "en", "value": "Example vulnerability one updated." }
+ ],
+ "references": [
+ {
+ "url": "https://vendor.example.com/advisories/0001",
+ "source": "Vendor",
+ "tags": ["Vendor Advisory"]
+ },
+ {
+ "url": "https://kb.example.com/articles/0001",
+ "source": "KnowledgeBase",
+ "tags": ["Third Party Advisory"]
+ }
+ ],
+ "metrics": {
+ "cvssMetricV31": [
+ {
+ "cvssData": {
+ "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H",
+ "baseScore": 8.8,
+ "baseSeverity": "HIGH"
+ }
+ }
+ ]
+ },
+ "configurations": {
+ "nodes": [
+ {
+ "cpeMatch": [
+ { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_one:1.0:*:*:*:*:*:*:*" },
+ { "vulnerable": true, "criteria": "cpe:2.3:a:example:product_one:1.1:*:*:*:*:*:*:*" }
+ ]
+ }
+ ]
+ }
+ }
+ }
+ ]
+}
diff --git a/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.ghsa.json b/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.ghsa.json
index 172a2e45..3cdd0919 100644
--- a/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.ghsa.json
+++ b/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.ghsa.json
@@ -4,20 +4,39 @@
"affectedPackages": [
{
"type": "semver",
- "identifier": "pkg:golang/github.com/opencontainers/image-spec",
- "platform": "go",
+ "identifier": "go:github.com/opencontainers/image-spec",
+ "platform": null,
"versionRanges": [
{
"fixedVersion": "1.0.2",
"introducedVersion": null,
"lastAffectedVersion": null,
- "primitives": null,
+ "primitives": {
+ "evr": null,
+ "hasVendorExtensions": true,
+ "nevra": null,
+ "semVer": {
+ "constraintExpression": "< 1.0.2",
+ "exactValue": null,
+ "fixed": "1.0.2",
+ "fixedInclusive": false,
+ "introduced": null,
+ "introducedInclusive": true,
+ "lastAffected": null,
+ "lastAffectedInclusive": false,
+ "style": "lessThan"
+ },
+ "vendorExtensions": {
+ "ecosystem": "go",
+ "package": "github.com/opencontainers/image-spec"
+ }
+ },
"provenance": {
"source": "ghsa",
- "kind": "range",
- "value": "pkg:golang/github.com/opencontainers/image-spec",
+ "kind": "affected-range",
+ "value": "go:github.com/opencontainers/image-spec",
"decisionReason": null,
- "recordedAt": "2023-01-09T05:05:32+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4315301+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -26,15 +45,40 @@
"rangeKind": "semver"
}
],
- "normalizedVersions": [],
- "statuses": [],
+ "normalizedVersions": [
+ {
+ "scheme": "semver",
+ "type": "lt",
+ "min": null,
+ "minInclusive": null,
+ "max": "1.0.2",
+ "maxInclusive": false,
+ "value": null,
+ "notes": "ghsa:go:github.com/opencontainers/image-spec"
+ }
+ ],
+ "statuses": [
+ {
+ "provenance": {
+ "source": "ghsa",
+ "kind": "affected-status",
+ "value": "go:github.com/opencontainers/image-spec",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.4315301+00:00",
+ "fieldMask": [
+ "affectedpackages[].statuses[]"
+ ]
+ },
+ "status": "affected"
+ }
+ ],
"provenance": [
{
"source": "ghsa",
- "kind": "package",
- "value": "pkg:golang/github.com/opencontainers/image-spec",
+ "kind": "affected",
+ "value": "go:github.com/opencontainers/image-spec",
"decisionReason": null,
- "recordedAt": "2023-01-09T05:05:32+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4315301+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -46,124 +90,36 @@
"GHSA-77vh-xpmg-72qh"
],
"credits": [],
- "cvssMetrics": [
- {
- "baseScore": 3,
- "baseSeverity": "low",
- "provenance": {
- "source": "ghsa",
- "kind": "cvss",
- "value": "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:N/I:L/A:N",
- "decisionReason": null,
- "recordedAt": "2023-01-09T05:05:32+00:00",
- "fieldMask": [
- "cvssmetrics[]"
- ]
- },
- "vector": "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:N/I:L/A:N",
- "version": "3.1"
- }
- ],
+ "cvssMetrics": [],
"exploitKnown": false,
"language": "en",
"modified": "2023-01-09T05:05:32+00:00",
"provenance": [
{
"source": "ghsa",
- "kind": "map",
+ "kind": "document",
+ "value": "https://github.com/advisories/GHSA-77vh-xpmg-72qh",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.4315294+00:00",
+ "fieldMask": [
+ "advisory"
+ ]
+ },
+ {
+ "source": "ghsa",
+ "kind": "mapping",
"value": "GHSA-77vh-xpmg-72qh",
"decisionReason": null,
- "recordedAt": "2023-01-09T05:05:32+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4315301+00:00",
"fieldMask": [
"advisory"
]
}
],
"published": "2021-11-18T16:02:41+00:00",
- "references": [
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/advisories/GHSA-77vh-xpmg-72qh",
- "decisionReason": null,
- "recordedAt": "2023-01-09T05:05:32+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/advisories/GHSA-77vh-xpmg-72qh"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/opencontainers/distribution-spec/security/advisories/GHSA-mc8v-mgrf-8f4m",
- "decisionReason": null,
- "recordedAt": "2023-01-09T05:05:32+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/opencontainers/distribution-spec/security/advisories/GHSA-mc8v-mgrf-8f4m"
- },
- {
- "kind": "patch",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/opencontainers/image-spec/commit/693428a734f5bab1a84bd2f990d92ef1111cd60c",
- "decisionReason": null,
- "recordedAt": "2023-01-09T05:05:32+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/opencontainers/image-spec/commit/693428a734f5bab1a84bd2f990d92ef1111cd60c"
- },
- {
- "kind": "patch",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/opencontainers/image-spec/releases/tag/v1.0.2",
- "decisionReason": null,
- "recordedAt": "2023-01-09T05:05:32+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/opencontainers/image-spec/releases/tag/v1.0.2"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/opencontainers/image-spec/security/advisories/GHSA-77vh-xpmg-72qh",
- "decisionReason": null,
- "recordedAt": "2023-01-09T05:05:32+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/opencontainers/image-spec/security/advisories/GHSA-77vh-xpmg-72qh"
- }
- ],
+ "references": [],
"severity": "low",
- "summary": "### Impact\nIn the OCI Image Specification version 1.0.1 and prior, manifest and index documents are not self-describing and documents with a single digest could be interpreted as either a manifest or an index.\n\n### Patches\nThe Image Specification will be updated to recommend that both manifest and index documents contain a `mediaType` field to identify the type of document.\nRelease [v1.0.2](https://github.com/opencontainers/image-spec/releases/tag/v1.0.2) includes these updates.\n\n### Workarounds\nSoftware attempting to deserialize an ambiguous document may reject the document if it contains both “manifests” and “layers” fields or “manifests” and “config” fields.\n\n### References\nhttps://github.com/opencontainers/distribution-spec/security/advisories/GHSA-mc8v-mgrf-8f4m\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue in https://github.com/opencontainers/image-spec\n* Email us at [security@opencontainers.org](mailto:security@opencontainers.org)\n* https://github.com/opencontainers/image-spec/commits/v1.0.2",
+ "summary": "Clarify `mediaType` handling",
"title": "Clarify `mediaType` handling"
},
{
@@ -171,20 +127,39 @@
"affectedPackages": [
{
"type": "semver",
- "identifier": "pkg:maven/org.apache.logging.log4j/log4j-core",
- "platform": "maven",
+ "identifier": "maven:org.apache.logging.log4j:log4j-core",
+ "platform": null,
"versionRanges": [
{
"fixedVersion": "2.16.0",
"introducedVersion": "2.13.0",
"lastAffectedVersion": null,
- "primitives": null,
+ "primitives": {
+ "evr": null,
+ "hasVendorExtensions": true,
+ "nevra": null,
+ "semVer": {
+ "constraintExpression": ">= 2.13.0, < 2.16.0",
+ "exactValue": null,
+ "fixed": "2.16.0",
+ "fixedInclusive": false,
+ "introduced": "2.13.0",
+ "introducedInclusive": true,
+ "lastAffected": null,
+ "lastAffectedInclusive": false,
+ "style": "range"
+ },
+ "vendorExtensions": {
+ "ecosystem": "maven",
+ "package": "org.apache.logging.log4j:log4j-core"
+ }
+ },
"provenance": {
"source": "ghsa",
- "kind": "range",
- "value": "pkg:maven/org.apache.logging.log4j/log4j-core",
+ "kind": "affected-range",
+ "value": "maven:org.apache.logging.log4j:log4j-core",
"decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -193,15 +168,40 @@
"rangeKind": "semver"
}
],
- "normalizedVersions": [],
- "statuses": [],
+ "normalizedVersions": [
+ {
+ "scheme": "semver",
+ "type": "range",
+ "min": "2.13.0",
+ "minInclusive": true,
+ "max": "2.16.0",
+ "maxInclusive": false,
+ "value": null,
+ "notes": "ghsa:maven:org.apache.logging.log4j:log4j-core"
+ }
+ ],
+ "statuses": [
+ {
+ "provenance": {
+ "source": "ghsa",
+ "kind": "affected-status",
+ "value": "maven:org.apache.logging.log4j:log4j-core",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
+ "fieldMask": [
+ "affectedpackages[].statuses[]"
+ ]
+ },
+ "status": "affected"
+ }
+ ],
"provenance": [
{
"source": "ghsa",
- "kind": "package",
- "value": "pkg:maven/org.apache.logging.log4j/log4j-core",
+ "kind": "affected",
+ "value": "maven:org.apache.logging.log4j:log4j-core",
"decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -210,20 +210,39 @@
},
{
"type": "semver",
- "identifier": "pkg:maven/org.apache.logging.log4j/log4j-core",
- "platform": "maven",
+ "identifier": "maven:org.apache.logging.log4j:log4j-core",
+ "platform": null,
"versionRanges": [
{
"fixedVersion": "2.12.2",
"introducedVersion": null,
"lastAffectedVersion": null,
- "primitives": null,
+ "primitives": {
+ "evr": null,
+ "hasVendorExtensions": true,
+ "nevra": null,
+ "semVer": {
+ "constraintExpression": "< 2.12.2",
+ "exactValue": null,
+ "fixed": "2.12.2",
+ "fixedInclusive": false,
+ "introduced": null,
+ "introducedInclusive": true,
+ "lastAffected": null,
+ "lastAffectedInclusive": false,
+ "style": "lessThan"
+ },
+ "vendorExtensions": {
+ "ecosystem": "maven",
+ "package": "org.apache.logging.log4j:log4j-core"
+ }
+ },
"provenance": {
"source": "ghsa",
- "kind": "range",
- "value": "pkg:maven/org.apache.logging.log4j/log4j-core",
+ "kind": "affected-range",
+ "value": "maven:org.apache.logging.log4j:log4j-core",
"decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -232,15 +251,40 @@
"rangeKind": "semver"
}
],
- "normalizedVersions": [],
- "statuses": [],
+ "normalizedVersions": [
+ {
+ "scheme": "semver",
+ "type": "lt",
+ "min": null,
+ "minInclusive": null,
+ "max": "2.12.2",
+ "maxInclusive": false,
+ "value": null,
+ "notes": "ghsa:maven:org.apache.logging.log4j:log4j-core"
+ }
+ ],
+ "statuses": [
+ {
+ "provenance": {
+ "source": "ghsa",
+ "kind": "affected-status",
+ "value": "maven:org.apache.logging.log4j:log4j-core",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
+ "fieldMask": [
+ "affectedpackages[].statuses[]"
+ ]
+ },
+ "status": "affected"
+ }
+ ],
"provenance": [
{
"source": "ghsa",
- "kind": "package",
- "value": "pkg:maven/org.apache.logging.log4j/log4j-core",
+ "kind": "affected",
+ "value": "maven:org.apache.logging.log4j:log4j-core",
"decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -249,20 +293,39 @@
},
{
"type": "semver",
- "identifier": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
- "platform": "maven",
+ "identifier": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
+ "platform": null,
"versionRanges": [
{
"fixedVersion": "1.9.2",
"introducedVersion": "1.8.0",
"lastAffectedVersion": null,
- "primitives": null,
+ "primitives": {
+ "evr": null,
+ "hasVendorExtensions": true,
+ "nevra": null,
+ "semVer": {
+ "constraintExpression": ">= 1.8.0, < 1.9.2",
+ "exactValue": null,
+ "fixed": "1.9.2",
+ "fixedInclusive": false,
+ "introduced": "1.8.0",
+ "introducedInclusive": true,
+ "lastAffected": null,
+ "lastAffectedInclusive": false,
+ "style": "range"
+ },
+ "vendorExtensions": {
+ "ecosystem": "maven",
+ "package": "org.ops4j.pax.logging:pax-logging-log4j2"
+ }
+ },
"provenance": {
"source": "ghsa",
- "kind": "range",
- "value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
+ "kind": "affected-range",
+ "value": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -271,15 +334,40 @@
"rangeKind": "semver"
}
],
- "normalizedVersions": [],
- "statuses": [],
+ "normalizedVersions": [
+ {
+ "scheme": "semver",
+ "type": "range",
+ "min": "1.8.0",
+ "minInclusive": true,
+ "max": "1.9.2",
+ "maxInclusive": false,
+ "value": null,
+ "notes": "ghsa:maven:org.ops4j.pax.logging:pax-logging-log4j2"
+ }
+ ],
+ "statuses": [
+ {
+ "provenance": {
+ "source": "ghsa",
+ "kind": "affected-status",
+ "value": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
+ "fieldMask": [
+ "affectedpackages[].statuses[]"
+ ]
+ },
+ "status": "affected"
+ }
+ ],
"provenance": [
{
"source": "ghsa",
- "kind": "package",
- "value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
+ "kind": "affected",
+ "value": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -288,20 +376,39 @@
},
{
"type": "semver",
- "identifier": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
- "platform": "maven",
+ "identifier": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
+ "platform": null,
"versionRanges": [
{
"fixedVersion": "1.10.8",
"introducedVersion": "1.10.0",
"lastAffectedVersion": null,
- "primitives": null,
+ "primitives": {
+ "evr": null,
+ "hasVendorExtensions": true,
+ "nevra": null,
+ "semVer": {
+ "constraintExpression": ">= 1.10.0, < 1.10.8",
+ "exactValue": null,
+ "fixed": "1.10.8",
+ "fixedInclusive": false,
+ "introduced": "1.10.0",
+ "introducedInclusive": true,
+ "lastAffected": null,
+ "lastAffectedInclusive": false,
+ "style": "range"
+ },
+ "vendorExtensions": {
+ "ecosystem": "maven",
+ "package": "org.ops4j.pax.logging:pax-logging-log4j2"
+ }
+ },
"provenance": {
"source": "ghsa",
- "kind": "range",
- "value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
+ "kind": "affected-range",
+ "value": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -310,15 +417,40 @@
"rangeKind": "semver"
}
],
- "normalizedVersions": [],
- "statuses": [],
+ "normalizedVersions": [
+ {
+ "scheme": "semver",
+ "type": "range",
+ "min": "1.10.0",
+ "minInclusive": true,
+ "max": "1.10.8",
+ "maxInclusive": false,
+ "value": null,
+ "notes": "ghsa:maven:org.ops4j.pax.logging:pax-logging-log4j2"
+ }
+ ],
+ "statuses": [
+ {
+ "provenance": {
+ "source": "ghsa",
+ "kind": "affected-status",
+ "value": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
+ "fieldMask": [
+ "affectedpackages[].statuses[]"
+ ]
+ },
+ "status": "affected"
+ }
+ ],
"provenance": [
{
"source": "ghsa",
- "kind": "package",
- "value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
+ "kind": "affected",
+ "value": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -327,20 +459,39 @@
},
{
"type": "semver",
- "identifier": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
- "platform": "maven",
+ "identifier": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
+ "platform": null,
"versionRanges": [
{
"fixedVersion": "1.11.11",
"introducedVersion": "1.11.0",
"lastAffectedVersion": null,
- "primitives": null,
+ "primitives": {
+ "evr": null,
+ "hasVendorExtensions": true,
+ "nevra": null,
+ "semVer": {
+ "constraintExpression": ">= 1.11.0, < 1.11.11",
+ "exactValue": null,
+ "fixed": "1.11.11",
+ "fixedInclusive": false,
+ "introduced": "1.11.0",
+ "introducedInclusive": true,
+ "lastAffected": null,
+ "lastAffectedInclusive": false,
+ "style": "range"
+ },
+ "vendorExtensions": {
+ "ecosystem": "maven",
+ "package": "org.ops4j.pax.logging:pax-logging-log4j2"
+ }
+ },
"provenance": {
"source": "ghsa",
- "kind": "range",
- "value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
+ "kind": "affected-range",
+ "value": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -349,15 +500,40 @@
"rangeKind": "semver"
}
],
- "normalizedVersions": [],
- "statuses": [],
+ "normalizedVersions": [
+ {
+ "scheme": "semver",
+ "type": "range",
+ "min": "1.11.0",
+ "minInclusive": true,
+ "max": "1.11.11",
+ "maxInclusive": false,
+ "value": null,
+ "notes": "ghsa:maven:org.ops4j.pax.logging:pax-logging-log4j2"
+ }
+ ],
+ "statuses": [
+ {
+ "provenance": {
+ "source": "ghsa",
+ "kind": "affected-status",
+ "value": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
+ "fieldMask": [
+ "affectedpackages[].statuses[]"
+ ]
+ },
+ "status": "affected"
+ }
+ ],
"provenance": [
{
"source": "ghsa",
- "kind": "package",
- "value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
+ "kind": "affected",
+ "value": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -366,20 +542,39 @@
},
{
"type": "semver",
- "identifier": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
- "platform": "maven",
+ "identifier": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
+ "platform": null,
"versionRanges": [
{
"fixedVersion": "2.0.12",
"introducedVersion": "2.0.0",
"lastAffectedVersion": null,
- "primitives": null,
+ "primitives": {
+ "evr": null,
+ "hasVendorExtensions": true,
+ "nevra": null,
+ "semVer": {
+ "constraintExpression": ">= 2.0.0, < 2.0.12",
+ "exactValue": null,
+ "fixed": "2.0.12",
+ "fixedInclusive": false,
+ "introduced": "2.0.0",
+ "introducedInclusive": true,
+ "lastAffected": null,
+ "lastAffectedInclusive": false,
+ "style": "range"
+ },
+ "vendorExtensions": {
+ "ecosystem": "maven",
+ "package": "org.ops4j.pax.logging:pax-logging-log4j2"
+ }
+ },
"provenance": {
"source": "ghsa",
- "kind": "range",
- "value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
+ "kind": "affected-range",
+ "value": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -388,15 +583,40 @@
"rangeKind": "semver"
}
],
- "normalizedVersions": [],
- "statuses": [],
+ "normalizedVersions": [
+ {
+ "scheme": "semver",
+ "type": "range",
+ "min": "2.0.0",
+ "minInclusive": true,
+ "max": "2.0.12",
+ "maxInclusive": false,
+ "value": null,
+ "notes": "ghsa:maven:org.ops4j.pax.logging:pax-logging-log4j2"
+ }
+ ],
+ "statuses": [
+ {
+ "provenance": {
+ "source": "ghsa",
+ "kind": "affected-status",
+ "value": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
+ "fieldMask": [
+ "affectedpackages[].statuses[]"
+ ]
+ },
+ "status": "affected"
+ }
+ ],
"provenance": [
{
"source": "ghsa",
- "kind": "package",
- "value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
+ "kind": "affected",
+ "value": "maven:org.ops4j.pax.logging:pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -405,448 +625,91 @@
}
],
"aliases": [
- "CVE-2021-45046",
"GHSA-7rjr-3q55-vv33"
],
- "credits": [],
- "cvssMetrics": [
+ "credits": [
{
- "baseScore": 9.1,
- "baseSeverity": "critical",
+ "displayName": "afdesk",
+ "role": "analyst",
+ "contacts": [
+ "https://github.com/afdesk"
+ ],
"provenance": {
"source": "ghsa",
- "kind": "cvss",
- "value": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H",
+ "kind": "credit",
+ "value": "afdesk",
"decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
"fieldMask": [
- "cvssmetrics[]"
+ "credits[]"
]
- },
- "vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H",
- "version": "3.1"
+ }
+ },
+ {
+ "displayName": "mrjonstrong",
+ "role": "analyst",
+ "contacts": [
+ "https://github.com/mrjonstrong"
+ ],
+ "provenance": {
+ "source": "ghsa",
+ "kind": "credit",
+ "value": "mrjonstrong",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
+ "fieldMask": [
+ "credits[]"
+ ]
+ }
+ },
+ {
+ "displayName": "ppkarwasz",
+ "role": "analyst",
+ "contacts": [
+ "https://github.com/ppkarwasz"
+ ],
+ "provenance": {
+ "source": "ghsa",
+ "kind": "credit",
+ "value": "ppkarwasz",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
+ "fieldMask": [
+ "credits[]"
+ ]
+ }
}
],
+ "cvssMetrics": [],
"exploitKnown": false,
"language": "en",
"modified": "2025-05-09T12:28:41+00:00",
"provenance": [
{
"source": "ghsa",
- "kind": "map",
+ "kind": "document",
+ "value": "https://github.com/advisories/GHSA-7rjr-3q55-vv33",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.4318432+00:00",
+ "fieldMask": [
+ "advisory"
+ ]
+ },
+ {
+ "source": "ghsa",
+ "kind": "mapping",
"value": "GHSA-7rjr-3q55-vv33",
"decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4318439+00:00",
"fieldMask": [
"advisory"
]
}
],
"published": "2021-12-14T18:01:28+00:00",
- "references": [
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "http://www.openwall.com/lists/oss-security/2021/12/14/4",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "www.openwall.com",
- "summary": null,
- "url": "http://www.openwall.com/lists/oss-security/2021/12/14/4"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "http://www.openwall.com/lists/oss-security/2021/12/15/3",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "www.openwall.com",
- "summary": null,
- "url": "http://www.openwall.com/lists/oss-security/2021/12/15/3"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "http://www.openwall.com/lists/oss-security/2021/12/18/1",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "www.openwall.com",
- "summary": null,
- "url": "http://www.openwall.com/lists/oss-security/2021/12/18/1"
- },
- {
- "kind": null,
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://cert-portal.siemens.com/productcert/pdf/ssa-397453.pdf",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "cert-portal.siemens.com",
- "summary": null,
- "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-397453.pdf"
- },
- {
- "kind": null,
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://cert-portal.siemens.com/productcert/pdf/ssa-479842.pdf",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "cert-portal.siemens.com",
- "summary": null,
- "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-479842.pdf"
- },
- {
- "kind": null,
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://cert-portal.siemens.com/productcert/pdf/ssa-661247.pdf",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "cert-portal.siemens.com",
- "summary": null,
- "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-661247.pdf"
- },
- {
- "kind": null,
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://cert-portal.siemens.com/productcert/pdf/ssa-714170.pdf",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "cert-portal.siemens.com",
- "summary": null,
- "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-714170.pdf"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/advisories/GHSA-7rjr-3q55-vv33",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/advisories/GHSA-7rjr-3q55-vv33"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/advisories/GHSA-jfh8-c2jp-5v3q",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/advisories/GHSA-jfh8-c2jp-5v3q"
- },
- {
- "kind": null,
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/EOKPQGV24RRBBI4TBZUDQMM4MEH7MXCY",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "lists.fedoraproject.org",
- "summary": null,
- "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/EOKPQGV24RRBBI4TBZUDQMM4MEH7MXCY"
- },
- {
- "kind": null,
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/SIG7FZULMNK2XF6FZRU4VWYDQXNMUGAJ",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "lists.fedoraproject.org",
- "summary": null,
- "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/SIG7FZULMNK2XF6FZRU4VWYDQXNMUGAJ"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://logging.apache.org/log4j/2.x/security.html",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "logging.apache.org",
- "summary": null,
- "url": "https://logging.apache.org/log4j/2.x/security.html"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://nvd.nist.gov/vuln/detail/CVE-2021-45046",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "nvd.nist.gov",
- "summary": null,
- "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-45046"
- },
- {
- "kind": null,
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://psirt.global.sonicwall.com/vuln-detail/SNWLID-2021-0032",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "psirt.global.sonicwall.com",
- "summary": null,
- "url": "https://psirt.global.sonicwall.com/vuln-detail/SNWLID-2021-0032"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-apache-log4j-qRuKNEbd",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "sec.cloudapps.cisco.com",
- "summary": null,
- "url": "https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-apache-log4j-qRuKNEbd"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://security.gentoo.org/glsa/202310-16",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "security.gentoo.org",
- "summary": null,
- "url": "https://security.gentoo.org/glsa/202310-16"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://www.cve.org/CVERecord?id=CVE-2021-44228",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "www.cve.org",
- "summary": null,
- "url": "https://www.cve.org/CVERecord?id=CVE-2021-44228"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://www.debian.org/security/2021/dsa-5022",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "www.debian.org",
- "summary": null,
- "url": "https://www.debian.org/security/2021/dsa-5022"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00646.html",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "www.intel.com",
- "summary": null,
- "url": "https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00646.html"
- },
- {
- "kind": null,
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://www.kb.cert.org/vuls/id/930724",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "www.kb.cert.org",
- "summary": null,
- "url": "https://www.kb.cert.org/vuls/id/930724"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://www.openwall.com/lists/oss-security/2021/12/14/4",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "www.openwall.com",
- "summary": null,
- "url": "https://www.openwall.com/lists/oss-security/2021/12/14/4"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://www.oracle.com/security-alerts/alert-cve-2021-44228.html",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "www.oracle.com",
- "summary": null,
- "url": "https://www.oracle.com/security-alerts/alert-cve-2021-44228.html"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://www.oracle.com/security-alerts/cpuapr2022.html",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "www.oracle.com",
- "summary": null,
- "url": "https://www.oracle.com/security-alerts/cpuapr2022.html"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://www.oracle.com/security-alerts/cpujan2022.html",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "www.oracle.com",
- "summary": null,
- "url": "https://www.oracle.com/security-alerts/cpujan2022.html"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://www.oracle.com/security-alerts/cpujul2022.html",
- "decisionReason": null,
- "recordedAt": "2025-05-09T12:28:41+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "www.oracle.com",
- "summary": null,
- "url": "https://www.oracle.com/security-alerts/cpujul2022.html"
- }
- ],
+ "references": [],
"severity": "critical",
- "summary": "# Impact\n\nThe fix to address [CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228) in Apache Log4j 2.15.0 was incomplete in certain non-default configurations. This could allow attackers with control over Thread Context Map (MDC) input data when the logging configuration uses a non-default Pattern Layout with either a Context Lookup (for example, $${ctx:loginId}) or a Thread Context Map pattern (%X, %mdc, or %MDC) to craft malicious input data using a JNDI Lookup pattern resulting in a remote code execution (RCE) attack. \n\n## Affected packages\nOnly the `org.apache.logging.log4j:log4j-core` package is directly affected by this vulnerability. The `org.apache.logging.log4j:log4j-api` should be kept at the same version as the `org.apache.logging.log4j:log4j-core` package to ensure compatability if in use.\n\n# Mitigation\n\nLog4j 2.16.0 fixes this issue by removing support for message lookup patterns and disabling JNDI functionality by default. This issue can be mitigated in prior releases (< 2.16.0) by removing the JndiLookup class from the classpath (example: zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class).\n\nLog4j 2.15.0 restricts JNDI LDAP lookups to localhost by default. Note that previous mitigations involving configuration such as to set the system property `log4j2.formatMsgNoLookups` to `true` do NOT mitigate this specific vulnerability.",
+ "summary": "Incomplete fix for Apache Log4j vulnerability",
"title": "Incomplete fix for Apache Log4j vulnerability"
},
{
@@ -854,20 +717,39 @@
"affectedPackages": [
{
"type": "semver",
- "identifier": "pyload-ng",
- "platform": "pip",
+ "identifier": "pip:pyload-ng",
+ "platform": null,
"versionRanges": [
{
"fixedVersion": "0.5.0b3.dev91",
"introducedVersion": null,
"lastAffectedVersion": null,
- "primitives": null,
+ "primitives": {
+ "evr": null,
+ "hasVendorExtensions": true,
+ "nevra": null,
+ "semVer": {
+ "constraintExpression": "< 0.5.0b3.dev91",
+ "exactValue": null,
+ "fixed": "0.5.0b3.dev91",
+ "fixedInclusive": false,
+ "introduced": null,
+ "introducedInclusive": true,
+ "lastAffected": null,
+ "lastAffectedInclusive": false,
+ "style": "lessThan"
+ },
+ "vendorExtensions": {
+ "ecosystem": "pip",
+ "package": "pyload-ng"
+ }
+ },
"provenance": {
"source": "ghsa",
- "kind": "range",
- "value": "pyload-ng",
+ "kind": "affected-range",
+ "value": "pip:pyload-ng",
"decisionReason": null,
- "recordedAt": "2025-10-09T15:19:48+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4306422+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -876,15 +758,40 @@
"rangeKind": "semver"
}
],
- "normalizedVersions": [],
- "statuses": [],
+ "normalizedVersions": [
+ {
+ "scheme": "semver",
+ "type": "lt",
+ "min": null,
+ "minInclusive": null,
+ "max": "0.5.0b3.dev91",
+ "maxInclusive": false,
+ "value": null,
+ "notes": "ghsa:pip:pyload-ng"
+ }
+ ],
+ "statuses": [
+ {
+ "provenance": {
+ "source": "ghsa",
+ "kind": "affected-status",
+ "value": "pip:pyload-ng",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.4306422+00:00",
+ "fieldMask": [
+ "affectedpackages[].statuses[]"
+ ]
+ },
+ "status": "affected"
+ }
+ ],
"provenance": [
{
"source": "ghsa",
- "kind": "package",
- "value": "pyload-ng",
+ "kind": "affected",
+ "value": "pip:pyload-ng",
"decisionReason": null,
- "recordedAt": "2025-10-09T15:19:48+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4306422+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -893,112 +800,57 @@
}
],
"aliases": [
- "CVE-2025-61773",
"GHSA-cjjf-27cc-pvmv"
],
- "credits": [],
- "cvssMetrics": [
+ "credits": [
{
- "baseScore": 8.1,
- "baseSeverity": "high",
+ "displayName": "odaysec",
+ "role": "reporter",
+ "contacts": [
+ "https://github.com/odaysec"
+ ],
"provenance": {
"source": "ghsa",
- "kind": "cvss",
- "value": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N",
+ "kind": "credit",
+ "value": "odaysec",
"decisionReason": null,
- "recordedAt": "2025-10-09T15:19:48+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4306422+00:00",
"fieldMask": [
- "cvssmetrics[]"
+ "credits[]"
]
- },
- "vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N",
- "version": "3.1"
+ }
}
],
+ "cvssMetrics": [],
"exploitKnown": false,
"language": "en",
"modified": "2025-10-09T15:19:48+00:00",
"provenance": [
{
"source": "ghsa",
- "kind": "map",
+ "kind": "document",
+ "value": "https://github.com/advisories/GHSA-cjjf-27cc-pvmv",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.430641+00:00",
+ "fieldMask": [
+ "advisory"
+ ]
+ },
+ {
+ "source": "ghsa",
+ "kind": "mapping",
"value": "GHSA-cjjf-27cc-pvmv",
"decisionReason": null,
- "recordedAt": "2025-10-09T15:19:48+00:00",
+ "recordedAt": "2025-10-12T19:48:04.4306422+00:00",
"fieldMask": [
"advisory"
]
}
],
"published": "2025-10-09T15:19:48+00:00",
- "references": [
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/advisories/GHSA-cjjf-27cc-pvmv",
- "decisionReason": null,
- "recordedAt": "2025-10-09T15:19:48+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/advisories/GHSA-cjjf-27cc-pvmv"
- },
- {
- "kind": "patch",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/pyload/pyload/commit/5823327d0b797161c7195a1f660266d30a69f0ca",
- "decisionReason": null,
- "recordedAt": "2025-10-09T15:19:48+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/pyload/pyload/commit/5823327d0b797161c7195a1f660266d30a69f0ca"
- },
- {
- "kind": "patch",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/pyload/pyload/pull/4624",
- "decisionReason": null,
- "recordedAt": "2025-10-09T15:19:48+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/pyload/pyload/pull/4624"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/pyload/pyload/security/advisories/GHSA-cjjf-27cc-pvmv",
- "decisionReason": null,
- "recordedAt": "2025-10-09T15:19:48+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/pyload/pyload/security/advisories/GHSA-cjjf-27cc-pvmv"
- }
- ],
+ "references": [],
"severity": "high",
- "summary": "### Summary\npyLoad web interface contained insufficient input validation in both the Captcha script endpoint and the Click'N'Load (CNL) Blueprint. This flaw allowed untrusted user input to be processed unsafely, which could be exploited by an attacker to inject arbitrary content into the web UI or manipulate request handling. The vulnerability could lead to client-side code execution (XSS) or other unintended behaviors when a malicious payload is submitted.\n\nuser-supplied parameters from HTTP requests were not adequately validated or sanitized before being passed into the application logic and response generation. This allowed crafted input to alter the expected execution flow.\n CNL (Click'N'Load) blueprint exposed unsafe handling of untrusted parameters in HTTP requests. The application did not consistently enforce input validation or encoding, making it possible for an attacker to craft malicious requests.\n\n### PoC\n\n1. Run a vulnerable version of pyLoad prior to commit [`f9d27f2`](https://github.com/pyload/pyload/pull/4624).\n2. Start the web UI and access the Captcha or CNL endpoints.\n3. Submit a crafted request containing malicious JavaScript payloads in unvalidated parameters (`/flash/addcrypted2?jk=function(){alert(1)}&crypted=12345`).\n4. Observe that the payload is reflected and executed in the client’s browser, demonstrating cross-site scripting (XSS).\n\nExample request:\n\n```http\nGET /flash/addcrypted2?jk=function(){alert(1)}&crypted=12345 HTTP/1.1\nHost: 127.0.0.1:8000\nContent-Type: application/x-www-form-urlencoded\nContent-Length: 107\n```\n\n### Impact\n\nExploiting this vulnerability allows an attacker to inject and execute arbitrary JavaScript within the browser session of a user accessing the pyLoad Web UI. In practice, this means an attacker could impersonate an administrator, steal authentication cookies or tokens, and perform unauthorized actions on behalf of the victim. Because the affected endpoints are part of the core interface, a successful attack undermines the trust and security of the entire application, potentially leading to a full compromise of the management interface and the data it controls. The impact is particularly severe in cases where the Web UI is exposed over a network without additional access restrictions, as it enables remote attackers to directly target users with crafted links or requests that trigger the vulnerability.",
+ "summary": "pyLoad CNL and captcha handlers allow Code Injection via unsanitized parameters",
"title": "pyLoad CNL and captcha handlers allow Code Injection via unsanitized parameters"
},
{
@@ -1006,20 +858,39 @@
"affectedPackages": [
{
"type": "semver",
- "identifier": "social-auth-app-django",
- "platform": "pip",
+ "identifier": "pip:social-auth-app-django",
+ "platform": null,
"versionRanges": [
{
"fixedVersion": "5.6.0",
"introducedVersion": null,
"lastAffectedVersion": null,
- "primitives": null,
+ "primitives": {
+ "evr": null,
+ "hasVendorExtensions": true,
+ "nevra": null,
+ "semVer": {
+ "constraintExpression": "< 5.6.0",
+ "exactValue": null,
+ "fixed": "5.6.0",
+ "fixedInclusive": false,
+ "introduced": null,
+ "introducedInclusive": true,
+ "lastAffected": null,
+ "lastAffectedInclusive": false,
+ "style": "lessThan"
+ },
+ "vendorExtensions": {
+ "ecosystem": "pip",
+ "package": "social-auth-app-django"
+ }
+ },
"provenance": {
"source": "ghsa",
- "kind": "range",
- "value": "social-auth-app-django",
+ "kind": "affected-range",
+ "value": "pip:social-auth-app-django",
"decisionReason": null,
- "recordedAt": "2025-10-09T17:08:06+00:00",
+ "recordedAt": "2025-10-12T19:48:04.3823222+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -1028,15 +899,40 @@
"rangeKind": "semver"
}
],
- "normalizedVersions": [],
- "statuses": [],
+ "normalizedVersions": [
+ {
+ "scheme": "semver",
+ "type": "lt",
+ "min": null,
+ "minInclusive": null,
+ "max": "5.6.0",
+ "maxInclusive": false,
+ "value": null,
+ "notes": "ghsa:pip:social-auth-app-django"
+ }
+ ],
+ "statuses": [
+ {
+ "provenance": {
+ "source": "ghsa",
+ "kind": "affected-status",
+ "value": "pip:social-auth-app-django",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.3823222+00:00",
+ "fieldMask": [
+ "affectedpackages[].statuses[]"
+ ]
+ },
+ "status": "affected"
+ }
+ ],
"provenance": [
{
"source": "ghsa",
- "kind": "package",
- "value": "social-auth-app-django",
+ "kind": "affected",
+ "value": "pip:social-auth-app-django",
"decisionReason": null,
- "recordedAt": "2025-10-09T17:08:06+00:00",
+ "recordedAt": "2025-10-12T19:48:04.3823222+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -1045,10 +941,61 @@
}
],
"aliases": [
- "CVE-2025-61783",
"GHSA-wv4w-6qv2-qqfg"
],
- "credits": [],
+ "credits": [
+ {
+ "displayName": "nijel",
+ "role": "remediation_developer",
+ "contacts": [
+ "https://github.com/nijel"
+ ],
+ "provenance": {
+ "source": "ghsa",
+ "kind": "credit",
+ "value": "nijel",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.3823222+00:00",
+ "fieldMask": [
+ "credits[]"
+ ]
+ }
+ },
+ {
+ "displayName": "mel-mason",
+ "role": "reporter",
+ "contacts": [
+ "https://github.com/mel-mason"
+ ],
+ "provenance": {
+ "source": "ghsa",
+ "kind": "credit",
+ "value": "mel-mason",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.3823222+00:00",
+ "fieldMask": [
+ "credits[]"
+ ]
+ }
+ },
+ {
+ "displayName": "vanya909",
+ "role": "reporter",
+ "contacts": [
+ "https://github.com/vanya909"
+ ],
+ "provenance": {
+ "source": "ghsa",
+ "kind": "credit",
+ "value": "vanya909",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.3823222+00:00",
+ "fieldMask": [
+ "credits[]"
+ ]
+ }
+ }
+ ],
"cvssMetrics": [],
"exploitKnown": false,
"language": "en",
@@ -1056,132 +1003,29 @@
"provenance": [
{
"source": "ghsa",
- "kind": "map",
+ "kind": "document",
+ "value": "https://github.com/advisories/GHSA-wv4w-6qv2-qqfg",
+ "decisionReason": null,
+ "recordedAt": "2025-10-12T19:48:04.3823199+00:00",
+ "fieldMask": [
+ "advisory"
+ ]
+ },
+ {
+ "source": "ghsa",
+ "kind": "mapping",
"value": "GHSA-wv4w-6qv2-qqfg",
"decisionReason": null,
- "recordedAt": "2025-10-09T17:08:06+00:00",
+ "recordedAt": "2025-10-12T19:48:04.3823222+00:00",
"fieldMask": [
"advisory"
]
}
],
"published": "2025-10-09T17:08:05+00:00",
- "references": [
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/advisories/GHSA-wv4w-6qv2-qqfg",
- "decisionReason": null,
- "recordedAt": "2025-10-09T17:08:06+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/advisories/GHSA-wv4w-6qv2-qqfg"
- },
- {
- "kind": "patch",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/python-social-auth/social-app-django/commit/10c80e2ebabeccd4e9c84ad0e16e1db74148ed4c",
- "decisionReason": null,
- "recordedAt": "2025-10-09T17:08:06+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/python-social-auth/social-app-django/commit/10c80e2ebabeccd4e9c84ad0e16e1db74148ed4c"
- },
- {
- "kind": null,
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/python-social-auth/social-app-django/issues/220",
- "decisionReason": null,
- "recordedAt": "2025-10-09T17:08:06+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/python-social-auth/social-app-django/issues/220"
- },
- {
- "kind": null,
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/python-social-auth/social-app-django/issues/231",
- "decisionReason": null,
- "recordedAt": "2025-10-09T17:08:06+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/python-social-auth/social-app-django/issues/231"
- },
- {
- "kind": null,
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/python-social-auth/social-app-django/issues/634",
- "decisionReason": null,
- "recordedAt": "2025-10-09T17:08:06+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/python-social-auth/social-app-django/issues/634"
- },
- {
- "kind": "patch",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/python-social-auth/social-app-django/pull/803",
- "decisionReason": null,
- "recordedAt": "2025-10-09T17:08:06+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/python-social-auth/social-app-django/pull/803"
- },
- {
- "kind": "advisory",
- "provenance": {
- "source": "ghsa",
- "kind": "reference",
- "value": "https://github.com/python-social-auth/social-app-django/security/advisories/GHSA-wv4w-6qv2-qqfg",
- "decisionReason": null,
- "recordedAt": "2025-10-09T17:08:06+00:00",
- "fieldMask": [
- "references[]"
- ]
- },
- "sourceTag": "github.com",
- "summary": null,
- "url": "https://github.com/python-social-auth/social-app-django/security/advisories/GHSA-wv4w-6qv2-qqfg"
- }
- ],
+ "references": [],
"severity": "medium",
- "summary": "### Impact\n\nUpon authentication, the user could be associated by e-mail even if the `associate_by_email` pipeline was not included. This could lead to account compromise when a third-party authentication service does not validate provided e-mail addresses or doesn't require unique e-mail addresses.\n\n### Patches\n\n* https://github.com/python-social-auth/social-app-django/pull/803\n\n### Workarounds\n\nReview the authentication service policy on e-mail addresses; many will not allow exploiting this vulnerability.",
+ "summary": "Python Social Auth - Django has unsafe account association",
"title": "Python Social Auth - Django has unsafe account association"
}
]
\ No newline at end of file
diff --git a/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.osv.json b/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.osv.json
index 4123a65b..3c240a74 100644
--- a/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.osv.json
+++ b/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.osv.json
@@ -33,7 +33,7 @@
"kind": "range",
"value": "pkg:golang/github.com/opencontainers/image-spec",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8509671+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2184266+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -61,7 +61,7 @@
"kind": "affected",
"value": "pkg:golang/github.com/opencontainers/image-spec",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8509671+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2184266+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -83,7 +83,7 @@
"kind": "cvss",
"value": "CVSS_V3",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8509671+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2184266+00:00",
"fieldMask": []
},
"vector": "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:N/I:L/A:N",
@@ -99,7 +99,7 @@
"kind": "document",
"value": "https://osv.dev/vulnerability/GHSA-77vh-xpmg-72qh",
"decisionReason": null,
- "recordedAt": "2021-11-18T16:02:41+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2181708+00:00",
"fieldMask": [
"advisory"
]
@@ -109,7 +109,7 @@
"kind": "mapping",
"value": "GHSA-77vh-xpmg-72qh",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8509671+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2184266+00:00",
"fieldMask": [
"advisory"
]
@@ -124,7 +124,7 @@
"kind": "reference",
"value": "https://github.com/opencontainers/distribution-spec/security/advisories/GHSA-mc8v-mgrf-8f4m",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8509671+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2184266+00:00",
"fieldMask": [
"references[]"
]
@@ -140,7 +140,7 @@
"kind": "reference",
"value": "https://github.com/opencontainers/image-spec",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8509671+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2184266+00:00",
"fieldMask": [
"references[]"
]
@@ -156,7 +156,7 @@
"kind": "reference",
"value": "https://github.com/opencontainers/image-spec/commit/693428a734f5bab1a84bd2f990d92ef1111cd60c",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8509671+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2184266+00:00",
"fieldMask": [
"references[]"
]
@@ -172,7 +172,7 @@
"kind": "reference",
"value": "https://github.com/opencontainers/image-spec/releases/tag/v1.0.2",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8509671+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2184266+00:00",
"fieldMask": [
"references[]"
]
@@ -188,7 +188,7 @@
"kind": "reference",
"value": "https://github.com/opencontainers/image-spec/security/advisories/GHSA-77vh-xpmg-72qh",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8509671+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2184266+00:00",
"fieldMask": [
"references[]"
]
@@ -236,7 +236,7 @@
"kind": "range",
"value": "pkg:maven/org.apache.logging.log4j/log4j-core",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -264,7 +264,7 @@
"kind": "affected",
"value": "pkg:maven/org.apache.logging.log4j/log4j-core",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -302,7 +302,7 @@
"kind": "range",
"value": "pkg:maven/org.apache.logging.log4j/log4j-core",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -330,7 +330,7 @@
"kind": "affected",
"value": "pkg:maven/org.apache.logging.log4j/log4j-core",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -368,7 +368,7 @@
"kind": "range",
"value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -396,7 +396,7 @@
"kind": "affected",
"value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -434,7 +434,7 @@
"kind": "range",
"value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -462,7 +462,7 @@
"kind": "affected",
"value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -500,7 +500,7 @@
"kind": "range",
"value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -528,7 +528,7 @@
"kind": "affected",
"value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -566,7 +566,7 @@
"kind": "range",
"value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -594,7 +594,7 @@
"kind": "affected",
"value": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -616,7 +616,7 @@
"kind": "cvss",
"value": "CVSS_V3",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": []
},
"vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H",
@@ -632,7 +632,7 @@
"kind": "document",
"value": "https://osv.dev/vulnerability/GHSA-7rjr-3q55-vv33",
"decisionReason": null,
- "recordedAt": "2021-12-14T18:01:28+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2355464+00:00",
"fieldMask": [
"advisory"
]
@@ -642,7 +642,7 @@
"kind": "mapping",
"value": "GHSA-7rjr-3q55-vv33",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"advisory"
]
@@ -657,7 +657,7 @@
"kind": "reference",
"value": "http://www.openwall.com/lists/oss-security/2021/12/14/4",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -673,7 +673,7 @@
"kind": "reference",
"value": "http://www.openwall.com/lists/oss-security/2021/12/15/3",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -689,7 +689,7 @@
"kind": "reference",
"value": "http://www.openwall.com/lists/oss-security/2021/12/18/1",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -705,7 +705,7 @@
"kind": "reference",
"value": "https://cert-portal.siemens.com/productcert/pdf/ssa-397453.pdf",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -721,7 +721,7 @@
"kind": "reference",
"value": "https://cert-portal.siemens.com/productcert/pdf/ssa-479842.pdf",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -737,7 +737,7 @@
"kind": "reference",
"value": "https://cert-portal.siemens.com/productcert/pdf/ssa-661247.pdf",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -753,7 +753,7 @@
"kind": "reference",
"value": "https://cert-portal.siemens.com/productcert/pdf/ssa-714170.pdf",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -769,7 +769,7 @@
"kind": "reference",
"value": "https://github.com/advisories/GHSA-jfh8-c2jp-5v3q",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -785,7 +785,7 @@
"kind": "reference",
"value": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/EOKPQGV24RRBBI4TBZUDQMM4MEH7MXCY",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -801,7 +801,7 @@
"kind": "reference",
"value": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/SIG7FZULMNK2XF6FZRU4VWYDQXNMUGAJ",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -817,7 +817,7 @@
"kind": "reference",
"value": "https://logging.apache.org/log4j/2.x/security.html",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -833,7 +833,7 @@
"kind": "reference",
"value": "https://nvd.nist.gov/vuln/detail/CVE-2021-45046",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -849,7 +849,7 @@
"kind": "reference",
"value": "https://psirt.global.sonicwall.com/vuln-detail/SNWLID-2021-0032",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -865,7 +865,7 @@
"kind": "reference",
"value": "https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-apache-log4j-qRuKNEbd",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -881,7 +881,7 @@
"kind": "reference",
"value": "https://security.gentoo.org/glsa/202310-16",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -897,7 +897,7 @@
"kind": "reference",
"value": "https://www.cve.org/CVERecord?id=CVE-2021-44228",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -913,7 +913,7 @@
"kind": "reference",
"value": "https://www.debian.org/security/2021/dsa-5022",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -929,7 +929,7 @@
"kind": "reference",
"value": "https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00646.html",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -945,7 +945,7 @@
"kind": "reference",
"value": "https://www.kb.cert.org/vuls/id/930724",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -961,7 +961,7 @@
"kind": "reference",
"value": "https://www.openwall.com/lists/oss-security/2021/12/14/4",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -977,7 +977,7 @@
"kind": "reference",
"value": "https://www.oracle.com/security-alerts/alert-cve-2021-44228.html",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -993,7 +993,7 @@
"kind": "reference",
"value": "https://www.oracle.com/security-alerts/cpuapr2022.html",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -1009,7 +1009,7 @@
"kind": "reference",
"value": "https://www.oracle.com/security-alerts/cpujan2022.html",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -1025,7 +1025,7 @@
"kind": "reference",
"value": "https://www.oracle.com/security-alerts/cpujul2022.html",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.862103+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2365076+00:00",
"fieldMask": [
"references[]"
]
@@ -1073,7 +1073,7 @@
"kind": "range",
"value": "pkg:pypi/pyload-ng",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8437105+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2065811+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -1101,7 +1101,7 @@
"kind": "affected",
"value": "pkg:pypi/pyload-ng",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8437105+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2065811+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -1123,7 +1123,7 @@
"kind": "cvss",
"value": "CVSS_V3",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8437105+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2065811+00:00",
"fieldMask": []
},
"vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N",
@@ -1139,7 +1139,7 @@
"kind": "document",
"value": "https://osv.dev/vulnerability/GHSA-cjjf-27cc-pvmv",
"decisionReason": null,
- "recordedAt": "2025-10-09T15:19:48+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2061911+00:00",
"fieldMask": [
"advisory"
]
@@ -1149,7 +1149,7 @@
"kind": "mapping",
"value": "GHSA-cjjf-27cc-pvmv",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8437105+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2065811+00:00",
"fieldMask": [
"advisory"
]
@@ -1164,7 +1164,7 @@
"kind": "reference",
"value": "https://github.com/pyload/pyload",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8437105+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2065811+00:00",
"fieldMask": [
"references[]"
]
@@ -1180,7 +1180,7 @@
"kind": "reference",
"value": "https://github.com/pyload/pyload/commit/5823327d0b797161c7195a1f660266d30a69f0ca",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8437105+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2065811+00:00",
"fieldMask": [
"references[]"
]
@@ -1196,7 +1196,7 @@
"kind": "reference",
"value": "https://github.com/pyload/pyload/pull/4624",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8437105+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2065811+00:00",
"fieldMask": [
"references[]"
]
@@ -1212,7 +1212,7 @@
"kind": "reference",
"value": "https://github.com/pyload/pyload/security/advisories/GHSA-cjjf-27cc-pvmv",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8437105+00:00",
+ "recordedAt": "2025-10-12T19:48:04.2065811+00:00",
"fieldMask": [
"references[]"
]
@@ -1260,7 +1260,7 @@
"kind": "range",
"value": "pkg:pypi/social-auth-app-django",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8047195+00:00",
+ "recordedAt": "2025-10-12T19:48:04.1231115+00:00",
"fieldMask": [
"affectedpackages[].versionranges[]"
]
@@ -1288,7 +1288,7 @@
"kind": "affected",
"value": "pkg:pypi/social-auth-app-django",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8047195+00:00",
+ "recordedAt": "2025-10-12T19:48:04.1231115+00:00",
"fieldMask": [
"affectedpackages[]"
]
@@ -1311,7 +1311,7 @@
"kind": "document",
"value": "https://osv.dev/vulnerability/GHSA-wv4w-6qv2-qqfg",
"decisionReason": null,
- "recordedAt": "2025-10-09T17:08:05+00:00",
+ "recordedAt": "2025-10-12T19:48:04.0743113+00:00",
"fieldMask": [
"advisory"
]
@@ -1321,7 +1321,7 @@
"kind": "mapping",
"value": "GHSA-wv4w-6qv2-qqfg",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8047195+00:00",
+ "recordedAt": "2025-10-12T19:48:04.1231115+00:00",
"fieldMask": [
"advisory"
]
@@ -1336,7 +1336,7 @@
"kind": "reference",
"value": "https://github.com/python-social-auth/social-app-django",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8047195+00:00",
+ "recordedAt": "2025-10-12T19:48:04.1231115+00:00",
"fieldMask": [
"references[]"
]
@@ -1352,7 +1352,7 @@
"kind": "reference",
"value": "https://github.com/python-social-auth/social-app-django/commit/10c80e2ebabeccd4e9c84ad0e16e1db74148ed4c",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8047195+00:00",
+ "recordedAt": "2025-10-12T19:48:04.1231115+00:00",
"fieldMask": [
"references[]"
]
@@ -1368,7 +1368,7 @@
"kind": "reference",
"value": "https://github.com/python-social-auth/social-app-django/issues/220",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8047195+00:00",
+ "recordedAt": "2025-10-12T19:48:04.1231115+00:00",
"fieldMask": [
"references[]"
]
@@ -1384,7 +1384,7 @@
"kind": "reference",
"value": "https://github.com/python-social-auth/social-app-django/issues/231",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8047195+00:00",
+ "recordedAt": "2025-10-12T19:48:04.1231115+00:00",
"fieldMask": [
"references[]"
]
@@ -1400,7 +1400,7 @@
"kind": "reference",
"value": "https://github.com/python-social-auth/social-app-django/issues/634",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8047195+00:00",
+ "recordedAt": "2025-10-12T19:48:04.1231115+00:00",
"fieldMask": [
"references[]"
]
@@ -1416,7 +1416,7 @@
"kind": "reference",
"value": "https://github.com/python-social-auth/social-app-django/pull/803",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8047195+00:00",
+ "recordedAt": "2025-10-12T19:48:04.1231115+00:00",
"fieldMask": [
"references[]"
]
@@ -1432,7 +1432,7 @@
"kind": "reference",
"value": "https://github.com/python-social-auth/social-app-django/security/advisories/GHSA-wv4w-6qv2-qqfg",
"decisionReason": null,
- "recordedAt": "2025-10-12T12:01:51.8047195+00:00",
+ "recordedAt": "2025-10-12T19:48:04.1231115+00:00",
"fieldMask": [
"references[]"
]
diff --git a/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.raw-ghsa.json b/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.raw-ghsa.json
index 4d2d84b1..34893ac5 100644
--- a/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.raw-ghsa.json
+++ b/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.raw-ghsa.json
@@ -1,519 +1,519 @@
-[
- {
- "ghsa_id": "GHSA-wv4w-6qv2-qqfg",
- "cve_id": "CVE-2025-61783",
- "url": "https://api.github.com/advisories/GHSA-wv4w-6qv2-qqfg",
- "html_url": "https://github.com/advisories/GHSA-wv4w-6qv2-qqfg",
- "summary": "Python Social Auth - Django has unsafe account association ",
- "description": "### Impact\n\nUpon authentication, the user could be associated by e-mail even if the \u0060associate_by_email\u0060 pipeline was not included. This could lead to account compromise when a third-party authentication service does not validate provided e-mail addresses or doesn\u0027t require unique e-mail addresses.\n\n### Patches\n\n* https://github.com/python-social-auth/social-app-django/pull/803\n\n### Workarounds\n\nReview the authentication service policy on e-mail addresses; many will not allow exploiting this vulnerability.",
- "type": "reviewed",
- "severity": "medium",
- "repository_advisory_url": "https://api.github.com/repos/python-social-auth/social-app-django/security-advisories/GHSA-wv4w-6qv2-qqfg",
- "source_code_location": "https://github.com/python-social-auth/social-app-django",
- "identifiers": [
- {
- "value": "GHSA-wv4w-6qv2-qqfg",
- "type": "GHSA"
- },
- {
- "value": "CVE-2025-61783",
- "type": "CVE"
- }
- ],
- "references": [
- "https://github.com/python-social-auth/social-app-django/security/advisories/GHSA-wv4w-6qv2-qqfg",
- "https://github.com/python-social-auth/social-app-django/issues/220",
- "https://github.com/python-social-auth/social-app-django/issues/231",
- "https://github.com/python-social-auth/social-app-django/issues/634",
- "https://github.com/python-social-auth/social-app-django/pull/803",
- "https://github.com/python-social-auth/social-app-django/commit/10c80e2ebabeccd4e9c84ad0e16e1db74148ed4c",
- "https://github.com/advisories/GHSA-wv4w-6qv2-qqfg"
- ],
- "published_at": "2025-10-09T17:08:05Z",
- "updated_at": "2025-10-09T17:08:06Z",
- "github_reviewed_at": "2025-10-09T17:08:05Z",
- "nvd_published_at": null,
- "withdrawn_at": null,
- "vulnerabilities": [
- {
- "package": {
- "ecosystem": "pip",
- "name": "social-auth-app-django"
- },
- "vulnerable_version_range": "\u003C 5.6.0",
- "first_patched_version": "5.6.0",
- "vulnerable_functions": []
- }
- ],
- "cvss_severities": {
- "cvss_v3": {
- "vector_string": null,
- "score": 0.0
- },
- "cvss_v4": {
- "vector_string": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N",
- "score": 6.3
- }
- },
- "cwes": [
- {
- "cwe_id": "CWE-290",
- "name": "Authentication Bypass by Spoofing"
- }
- ],
- "credits": [
- {
- "user": {
- "login": "mel-mason",
- "id": 19391457,
- "node_id": "MDQ6VXNlcjE5MzkxNDU3",
- "avatar_url": "https://avatars.githubusercontent.com/u/19391457?v=4",
- "gravatar_id": "",
- "url": "https://api.github.com/users/mel-mason",
- "html_url": "https://github.com/mel-mason",
- "followers_url": "https://api.github.com/users/mel-mason/followers",
- "following_url": "https://api.github.com/users/mel-mason/following{/other_user}",
- "gists_url": "https://api.github.com/users/mel-mason/gists{/gist_id}",
- "starred_url": "https://api.github.com/users/mel-mason/starred{/owner}{/repo}",
- "subscriptions_url": "https://api.github.com/users/mel-mason/subscriptions",
- "organizations_url": "https://api.github.com/users/mel-mason/orgs",
- "repos_url": "https://api.github.com/users/mel-mason/repos",
- "events_url": "https://api.github.com/users/mel-mason/events{/privacy}",
- "received_events_url": "https://api.github.com/users/mel-mason/received_events",
- "type": "User",
- "user_view_type": "public",
- "site_admin": false
- },
- "type": "reporter"
- },
- {
- "user": {
- "login": "vanya909",
- "id": 53380238,
- "node_id": "MDQ6VXNlcjUzMzgwMjM4",
- "avatar_url": "https://avatars.githubusercontent.com/u/53380238?v=4",
- "gravatar_id": "",
- "url": "https://api.github.com/users/vanya909",
- "html_url": "https://github.com/vanya909",
- "followers_url": "https://api.github.com/users/vanya909/followers",
- "following_url": "https://api.github.com/users/vanya909/following{/other_user}",
- "gists_url": "https://api.github.com/users/vanya909/gists{/gist_id}",
- "starred_url": "https://api.github.com/users/vanya909/starred{/owner}{/repo}",
- "subscriptions_url": "https://api.github.com/users/vanya909/subscriptions",
- "organizations_url": "https://api.github.com/users/vanya909/orgs",
- "repos_url": "https://api.github.com/users/vanya909/repos",
- "events_url": "https://api.github.com/users/vanya909/events{/privacy}",
- "received_events_url": "https://api.github.com/users/vanya909/received_events",
- "type": "User",
- "user_view_type": "public",
- "site_admin": false
- },
- "type": "reporter"
- },
- {
- "user": {
- "login": "nijel",
- "id": 212189,
- "node_id": "MDQ6VXNlcjIxMjE4OQ==",
- "avatar_url": "https://avatars.githubusercontent.com/u/212189?v=4",
- "gravatar_id": "",
- "url": "https://api.github.com/users/nijel",
- "html_url": "https://github.com/nijel",
- "followers_url": "https://api.github.com/users/nijel/followers",
- "following_url": "https://api.github.com/users/nijel/following{/other_user}",
- "gists_url": "https://api.github.com/users/nijel/gists{/gist_id}",
- "starred_url": "https://api.github.com/users/nijel/starred{/owner}{/repo}",
- "subscriptions_url": "https://api.github.com/users/nijel/subscriptions",
- "organizations_url": "https://api.github.com/users/nijel/orgs",
- "repos_url": "https://api.github.com/users/nijel/repos",
- "events_url": "https://api.github.com/users/nijel/events{/privacy}",
- "received_events_url": "https://api.github.com/users/nijel/received_events",
- "type": "User",
- "user_view_type": "public",
- "site_admin": false
- },
- "type": "remediation_developer"
- }
- ],
- "cvss": {
- "vector_string": null,
- "score": null
- }
- },
- {
- "ghsa_id": "GHSA-cjjf-27cc-pvmv",
- "cve_id": "CVE-2025-61773",
- "url": "https://api.github.com/advisories/GHSA-cjjf-27cc-pvmv",
- "html_url": "https://github.com/advisories/GHSA-cjjf-27cc-pvmv",
- "summary": "pyLoad CNL and captcha handlers allow Code Injection via unsanitized parameters",
- "description": "### Summary\npyLoad web interface contained insufficient input validation in both the Captcha script endpoint and the Click\u0027N\u0027Load (CNL) Blueprint. This flaw allowed untrusted user input to be processed unsafely, which could be exploited by an attacker to inject arbitrary content into the web UI or manipulate request handling. The vulnerability could lead to client-side code execution (XSS) or other unintended behaviors when a malicious payload is submitted.\n\nuser-supplied parameters from HTTP requests were not adequately validated or sanitized before being passed into the application logic and response generation. This allowed crafted input to alter the expected execution flow.\n CNL (Click\u0027N\u0027Load) blueprint exposed unsafe handling of untrusted parameters in HTTP requests. The application did not consistently enforce input validation or encoding, making it possible for an attacker to craft malicious requests.\n\n### PoC\n\n1. Run a vulnerable version of pyLoad prior to commit [\u0060f9d27f2\u0060](https://github.com/pyload/pyload/pull/4624).\n2. Start the web UI and access the Captcha or CNL endpoints.\n3. Submit a crafted request containing malicious JavaScript payloads in unvalidated parameters (\u0060/flash/addcrypted2?jk=function(){alert(1)}\u0026crypted=12345\u0060).\n4. Observe that the payload is reflected and executed in the client\u2019s browser, demonstrating cross-site scripting (XSS).\n\nExample request:\n\n\u0060\u0060\u0060http\nGET /flash/addcrypted2?jk=function(){alert(1)}\u0026crypted=12345 HTTP/1.1\nHost: 127.0.0.1:8000\nContent-Type: application/x-www-form-urlencoded\nContent-Length: 107\n\u0060\u0060\u0060\n\n### Impact\n\nExploiting this vulnerability allows an attacker to inject and execute arbitrary JavaScript within the browser session of a user accessing the pyLoad Web UI. In practice, this means an attacker could impersonate an administrator, steal authentication cookies or tokens, and perform unauthorized actions on behalf of the victim. Because the affected endpoints are part of the core interface, a successful attack undermines the trust and security of the entire application, potentially leading to a full compromise of the management interface and the data it controls. The impact is particularly severe in cases where the Web UI is exposed over a network without additional access restrictions, as it enables remote attackers to directly target users with crafted links or requests that trigger the vulnerability.",
- "type": "reviewed",
- "severity": "high",
- "repository_advisory_url": "https://api.github.com/repos/pyload/pyload/security-advisories/GHSA-cjjf-27cc-pvmv",
- "source_code_location": "https://github.com/pyload/pyload",
- "identifiers": [
- {
- "value": "GHSA-cjjf-27cc-pvmv",
- "type": "GHSA"
- },
- {
- "value": "CVE-2025-61773",
- "type": "CVE"
- }
- ],
- "references": [
- "https://github.com/pyload/pyload/security/advisories/GHSA-cjjf-27cc-pvmv",
- "https://github.com/pyload/pyload/pull/4624",
- "https://github.com/pyload/pyload/commit/5823327d0b797161c7195a1f660266d30a69f0ca",
- "https://github.com/advisories/GHSA-cjjf-27cc-pvmv"
- ],
- "published_at": "2025-10-09T15:19:48Z",
- "updated_at": "2025-10-09T15:19:48Z",
- "github_reviewed_at": "2025-10-09T15:19:48Z",
- "nvd_published_at": null,
- "withdrawn_at": null,
- "vulnerabilities": [
- {
- "package": {
- "ecosystem": "pip",
- "name": "pyload-ng"
- },
- "vulnerable_version_range": "\u003C 0.5.0b3.dev91",
- "first_patched_version": "0.5.0b3.dev91",
- "vulnerable_functions": []
- }
- ],
- "cvss_severities": {
- "cvss_v3": {
- "vector_string": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N",
- "score": 8.1
- },
- "cvss_v4": {
- "vector_string": null,
- "score": 0.0
- }
- },
- "cwes": [
- {
- "cwe_id": "CWE-74",
- "name": "Improper Neutralization of Special Elements in Output Used by a Downstream Component (\u0027Injection\u0027)"
- },
- {
- "cwe_id": "CWE-79",
- "name": "Improper Neutralization of Input During Web Page Generation (\u0027Cross-site Scripting\u0027)"
- },
- {
- "cwe_id": "CWE-94",
- "name": "Improper Control of Generation of Code (\u0027Code Injection\u0027)"
- },
- {
- "cwe_id": "CWE-116",
- "name": "Improper Encoding or Escaping of Output"
- }
- ],
- "credits": [
- {
- "user": {
- "login": "odaysec",
- "id": 47859767,
- "node_id": "MDQ6VXNlcjQ3ODU5NzY3",
- "avatar_url": "https://avatars.githubusercontent.com/u/47859767?v=4",
- "gravatar_id": "",
- "url": "https://api.github.com/users/odaysec",
- "html_url": "https://github.com/odaysec",
- "followers_url": "https://api.github.com/users/odaysec/followers",
- "following_url": "https://api.github.com/users/odaysec/following{/other_user}",
- "gists_url": "https://api.github.com/users/odaysec/gists{/gist_id}",
- "starred_url": "https://api.github.com/users/odaysec/starred{/owner}{/repo}",
- "subscriptions_url": "https://api.github.com/users/odaysec/subscriptions",
- "organizations_url": "https://api.github.com/users/odaysec/orgs",
- "repos_url": "https://api.github.com/users/odaysec/repos",
- "events_url": "https://api.github.com/users/odaysec/events{/privacy}",
- "received_events_url": "https://api.github.com/users/odaysec/received_events",
- "type": "User",
- "user_view_type": "public",
- "site_admin": false
- },
- "type": "reporter"
- }
- ],
- "cvss": {
- "vector_string": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N",
- "score": 8.1
- }
- },
- {
- "ghsa_id": "GHSA-77vh-xpmg-72qh",
- "cve_id": null,
- "url": "https://api.github.com/advisories/GHSA-77vh-xpmg-72qh",
- "html_url": "https://github.com/advisories/GHSA-77vh-xpmg-72qh",
- "summary": "Clarify \u0060mediaType\u0060 handling",
- "description": "### Impact\nIn the OCI Image Specification version 1.0.1 and prior, manifest and index documents are not self-describing and documents with a single digest could be interpreted as either a manifest or an index.\n\n### Patches\nThe Image Specification will be updated to recommend that both manifest and index documents contain a \u0060mediaType\u0060 field to identify the type of document.\nRelease [v1.0.2](https://github.com/opencontainers/image-spec/releases/tag/v1.0.2) includes these updates.\n\n### Workarounds\nSoftware attempting to deserialize an ambiguous document may reject the document if it contains both \u201Cmanifests\u201D and \u201Clayers\u201D fields or \u201Cmanifests\u201D and \u201Cconfig\u201D fields.\n\n### References\nhttps://github.com/opencontainers/distribution-spec/security/advisories/GHSA-mc8v-mgrf-8f4m\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue in https://github.com/opencontainers/image-spec\n* Email us at [security@opencontainers.org](mailto:security@opencontainers.org)\n* https://github.com/opencontainers/image-spec/commits/v1.0.2\n",
- "type": "reviewed",
- "severity": "low",
- "repository_advisory_url": "https://api.github.com/repos/opencontainers/image-spec/security-advisories/GHSA-77vh-xpmg-72qh",
- "source_code_location": "https://github.com/opencontainers/image-spec",
- "identifiers": [
- {
- "value": "GHSA-77vh-xpmg-72qh",
- "type": "GHSA"
- }
- ],
- "references": [
- "https://github.com/opencontainers/distribution-spec/security/advisories/GHSA-mc8v-mgrf-8f4m",
- "https://github.com/opencontainers/image-spec/security/advisories/GHSA-77vh-xpmg-72qh",
- "https://github.com/opencontainers/image-spec/commit/693428a734f5bab1a84bd2f990d92ef1111cd60c",
- "https://github.com/opencontainers/image-spec/releases/tag/v1.0.2",
- "https://github.com/advisories/GHSA-77vh-xpmg-72qh"
- ],
- "published_at": "2021-11-18T16:02:41Z",
- "updated_at": "2023-01-09T05:05:32Z",
- "github_reviewed_at": "2021-11-17T23:13:41Z",
- "nvd_published_at": null,
- "withdrawn_at": null,
- "vulnerabilities": [
- {
- "package": {
- "ecosystem": "go",
- "name": "github.com/opencontainers/image-spec"
- },
- "vulnerable_version_range": "\u003C 1.0.2",
- "first_patched_version": "1.0.2",
- "vulnerable_functions": []
- }
- ],
- "cvss_severities": {
- "cvss_v3": {
- "vector_string": "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:N/I:L/A:N",
- "score": 3.0
- },
- "cvss_v4": {
- "vector_string": null,
- "score": 0.0
- }
- },
- "cwes": [
- {
- "cwe_id": "CWE-843",
- "name": "Access of Resource Using Incompatible Type (\u0027Type Confusion\u0027)"
- }
- ],
- "credits": [],
- "cvss": {
- "vector_string": "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:N/I:L/A:N",
- "score": 3.0
- }
- },
- {
- "ghsa_id": "GHSA-7rjr-3q55-vv33",
- "cve_id": "CVE-2021-45046",
- "url": "https://api.github.com/advisories/GHSA-7rjr-3q55-vv33",
- "html_url": "https://github.com/advisories/GHSA-7rjr-3q55-vv33",
- "summary": "Incomplete fix for Apache Log4j vulnerability",
- "description": "# Impact\n\nThe fix to address [CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228) in Apache Log4j 2.15.0 was incomplete in certain non-default configurations. This could allow attackers with control over Thread Context Map (MDC) input data when the logging configuration uses a non-default Pattern Layout with either a Context Lookup (for example, $${ctx:loginId}) or a Thread Context Map pattern (%X, %mdc, or %MDC) to craft malicious input data using a JNDI Lookup pattern resulting in a remote code execution (RCE) attack. \n\n## Affected packages\nOnly the \u0060org.apache.logging.log4j:log4j-core\u0060 package is directly affected by this vulnerability. The \u0060org.apache.logging.log4j:log4j-api\u0060 should be kept at the same version as the \u0060org.apache.logging.log4j:log4j-core\u0060 package to ensure compatability if in use.\n\n# Mitigation\n\nLog4j 2.16.0 fixes this issue by removing support for message lookup patterns and disabling JNDI functionality by default. This issue can be mitigated in prior releases (\u003C 2.16.0) by removing the JndiLookup class from the classpath (example: zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class).\n\nLog4j 2.15.0 restricts JNDI LDAP lookups to localhost by default. Note that previous mitigations involving configuration such as to set the system property \u0060log4j2.formatMsgNoLookups\u0060 to \u0060true\u0060 do NOT mitigate this specific vulnerability.",
- "type": "reviewed",
- "severity": "critical",
- "repository_advisory_url": null,
- "source_code_location": "",
- "identifiers": [
- {
- "value": "GHSA-7rjr-3q55-vv33",
- "type": "GHSA"
- },
- {
- "value": "CVE-2021-45046",
- "type": "CVE"
- }
- ],
- "references": [
- "https://nvd.nist.gov/vuln/detail/CVE-2021-45046",
- "https://github.com/advisories/GHSA-jfh8-c2jp-5v3q",
- "https://logging.apache.org/log4j/2.x/security.html",
- "https://www.openwall.com/lists/oss-security/2021/12/14/4",
- "https://www.cve.org/CVERecord?id=CVE-2021-44228",
- "http://www.openwall.com/lists/oss-security/2021/12/14/4",
- "https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00646.html",
- "http://www.openwall.com/lists/oss-security/2021/12/15/3",
- "https://cert-portal.siemens.com/productcert/pdf/ssa-661247.pdf",
- "https://cert-portal.siemens.com/productcert/pdf/ssa-714170.pdf",
- "https://www.kb.cert.org/vuls/id/930724",
- "https://www.debian.org/security/2021/dsa-5022",
- "https://psirt.global.sonicwall.com/vuln-detail/SNWLID-2021-0032",
- "https://www.oracle.com/security-alerts/alert-cve-2021-44228.html",
- "http://www.openwall.com/lists/oss-security/2021/12/18/1",
- "https://cert-portal.siemens.com/productcert/pdf/ssa-397453.pdf",
- "https://cert-portal.siemens.com/productcert/pdf/ssa-479842.pdf",
- "https://www.oracle.com/security-alerts/cpujan2022.html",
- "https://www.oracle.com/security-alerts/cpuapr2022.html",
- "https://www.oracle.com/security-alerts/cpujul2022.html",
- "https://security.gentoo.org/glsa/202310-16",
- "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/SIG7FZULMNK2XF6FZRU4VWYDQXNMUGAJ",
- "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/EOKPQGV24RRBBI4TBZUDQMM4MEH7MXCY",
- "https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-apache-log4j-qRuKNEbd",
- "https://github.com/advisories/GHSA-7rjr-3q55-vv33"
- ],
- "published_at": "2021-12-14T18:01:28Z",
- "updated_at": "2025-05-09T12:28:41Z",
- "github_reviewed_at": "2021-12-14T17:55:00Z",
- "nvd_published_at": "2021-12-14T19:15:00Z",
- "withdrawn_at": null,
- "vulnerabilities": [
- {
- "package": {
- "ecosystem": "maven",
- "name": "org.apache.logging.log4j:log4j-core"
- },
- "vulnerable_version_range": "\u003E= 2.13.0, \u003C 2.16.0",
- "first_patched_version": "2.16.0",
- "vulnerable_functions": []
- },
- {
- "package": {
- "ecosystem": "maven",
- "name": "org.apache.logging.log4j:log4j-core"
- },
- "vulnerable_version_range": "\u003C 2.12.2",
- "first_patched_version": "2.12.2",
- "vulnerable_functions": []
- },
- {
- "package": {
- "ecosystem": "maven",
- "name": "org.ops4j.pax.logging:pax-logging-log4j2"
- },
- "vulnerable_version_range": "\u003E= 1.8.0, \u003C 1.9.2",
- "first_patched_version": "1.9.2",
- "vulnerable_functions": []
- },
- {
- "package": {
- "ecosystem": "maven",
- "name": "org.ops4j.pax.logging:pax-logging-log4j2"
- },
- "vulnerable_version_range": "\u003E= 1.10.0, \u003C 1.10.8",
- "first_patched_version": "1.10.8",
- "vulnerable_functions": []
- },
- {
- "package": {
- "ecosystem": "maven",
- "name": "org.ops4j.pax.logging:pax-logging-log4j2"
- },
- "vulnerable_version_range": "\u003E= 1.11.0, \u003C 1.11.11",
- "first_patched_version": "1.11.11",
- "vulnerable_functions": []
- },
- {
- "package": {
- "ecosystem": "maven",
- "name": "org.ops4j.pax.logging:pax-logging-log4j2"
- },
- "vulnerable_version_range": "\u003E= 2.0.0, \u003C 2.0.12",
- "first_patched_version": "2.0.12",
- "vulnerable_functions": []
- }
- ],
- "cvss_severities": {
- "cvss_v3": {
- "vector_string": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H",
- "score": 9.1
- },
- "cvss_v4": {
- "vector_string": null,
- "score": 0.0
- }
- },
- "cwes": [
- {
- "cwe_id": "CWE-502",
- "name": "Deserialization of Untrusted Data"
- },
- {
- "cwe_id": "CWE-917",
- "name": "Improper Neutralization of Special Elements used in an Expression Language Statement (\u0027Expression Language Injection\u0027)"
- }
- ],
- "credits": [
- {
- "user": {
- "login": "mrjonstrong",
- "id": 42520909,
- "node_id": "MDQ6VXNlcjQyNTIwOTA5",
- "avatar_url": "https://avatars.githubusercontent.com/u/42520909?v=4",
- "gravatar_id": "",
- "url": "https://api.github.com/users/mrjonstrong",
- "html_url": "https://github.com/mrjonstrong",
- "followers_url": "https://api.github.com/users/mrjonstrong/followers",
- "following_url": "https://api.github.com/users/mrjonstrong/following{/other_user}",
- "gists_url": "https://api.github.com/users/mrjonstrong/gists{/gist_id}",
- "starred_url": "https://api.github.com/users/mrjonstrong/starred{/owner}{/repo}",
- "subscriptions_url": "https://api.github.com/users/mrjonstrong/subscriptions",
- "organizations_url": "https://api.github.com/users/mrjonstrong/orgs",
- "repos_url": "https://api.github.com/users/mrjonstrong/repos",
- "events_url": "https://api.github.com/users/mrjonstrong/events{/privacy}",
- "received_events_url": "https://api.github.com/users/mrjonstrong/received_events",
- "type": "User",
- "user_view_type": "public",
- "site_admin": false
- },
- "type": "analyst"
- },
- {
- "user": {
- "login": "afdesk",
- "id": 19297627,
- "node_id": "MDQ6VXNlcjE5Mjk3NjI3",
- "avatar_url": "https://avatars.githubusercontent.com/u/19297627?v=4",
- "gravatar_id": "",
- "url": "https://api.github.com/users/afdesk",
- "html_url": "https://github.com/afdesk",
- "followers_url": "https://api.github.com/users/afdesk/followers",
- "following_url": "https://api.github.com/users/afdesk/following{/other_user}",
- "gists_url": "https://api.github.com/users/afdesk/gists{/gist_id}",
- "starred_url": "https://api.github.com/users/afdesk/starred{/owner}{/repo}",
- "subscriptions_url": "https://api.github.com/users/afdesk/subscriptions",
- "organizations_url": "https://api.github.com/users/afdesk/orgs",
- "repos_url": "https://api.github.com/users/afdesk/repos",
- "events_url": "https://api.github.com/users/afdesk/events{/privacy}",
- "received_events_url": "https://api.github.com/users/afdesk/received_events",
- "type": "User",
- "user_view_type": "public",
- "site_admin": false
- },
- "type": "analyst"
- },
- {
- "user": {
- "login": "ppkarwasz",
- "id": 12533274,
- "node_id": "MDQ6VXNlcjEyNTMzMjc0",
- "avatar_url": "https://avatars.githubusercontent.com/u/12533274?v=4",
- "gravatar_id": "",
- "url": "https://api.github.com/users/ppkarwasz",
- "html_url": "https://github.com/ppkarwasz",
- "followers_url": "https://api.github.com/users/ppkarwasz/followers",
- "following_url": "https://api.github.com/users/ppkarwasz/following{/other_user}",
- "gists_url": "https://api.github.com/users/ppkarwasz/gists{/gist_id}",
- "starred_url": "https://api.github.com/users/ppkarwasz/starred{/owner}{/repo}",
- "subscriptions_url": "https://api.github.com/users/ppkarwasz/subscriptions",
- "organizations_url": "https://api.github.com/users/ppkarwasz/orgs",
- "repos_url": "https://api.github.com/users/ppkarwasz/repos",
- "events_url": "https://api.github.com/users/ppkarwasz/events{/privacy}",
- "received_events_url": "https://api.github.com/users/ppkarwasz/received_events",
- "type": "User",
- "user_view_type": "public",
- "site_admin": false
- },
- "type": "analyst"
- }
- ],
- "cvss": {
- "vector_string": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H",
- "score": 9.1
- },
- "epss": {
- "percentage": 0.9434,
- "percentile": 0.9995
- }
- }
+[
+ {
+ "ghsa_id": "GHSA-wv4w-6qv2-qqfg",
+ "cve_id": "CVE-2025-61783",
+ "url": "https://api.github.com/advisories/GHSA-wv4w-6qv2-qqfg",
+ "html_url": "https://github.com/advisories/GHSA-wv4w-6qv2-qqfg",
+ "summary": "Python Social Auth - Django has unsafe account association ",
+ "description": "### Impact\n\nUpon authentication, the user could be associated by e-mail even if the \u0060associate_by_email\u0060 pipeline was not included. This could lead to account compromise when a third-party authentication service does not validate provided e-mail addresses or doesn\u0027t require unique e-mail addresses.\n\n### Patches\n\n* https://github.com/python-social-auth/social-app-django/pull/803\n\n### Workarounds\n\nReview the authentication service policy on e-mail addresses; many will not allow exploiting this vulnerability.",
+ "type": "reviewed",
+ "severity": "medium",
+ "repository_advisory_url": "https://api.github.com/repos/python-social-auth/social-app-django/security-advisories/GHSA-wv4w-6qv2-qqfg",
+ "source_code_location": "https://github.com/python-social-auth/social-app-django",
+ "identifiers": [
+ {
+ "value": "GHSA-wv4w-6qv2-qqfg",
+ "type": "GHSA"
+ },
+ {
+ "value": "CVE-2025-61783",
+ "type": "CVE"
+ }
+ ],
+ "references": [
+ "https://github.com/python-social-auth/social-app-django/security/advisories/GHSA-wv4w-6qv2-qqfg",
+ "https://github.com/python-social-auth/social-app-django/issues/220",
+ "https://github.com/python-social-auth/social-app-django/issues/231",
+ "https://github.com/python-social-auth/social-app-django/issues/634",
+ "https://github.com/python-social-auth/social-app-django/pull/803",
+ "https://github.com/python-social-auth/social-app-django/commit/10c80e2ebabeccd4e9c84ad0e16e1db74148ed4c",
+ "https://github.com/advisories/GHSA-wv4w-6qv2-qqfg"
+ ],
+ "published_at": "2025-10-09T17:08:05Z",
+ "updated_at": "2025-10-09T17:08:06Z",
+ "github_reviewed_at": "2025-10-09T17:08:05Z",
+ "nvd_published_at": null,
+ "withdrawn_at": null,
+ "vulnerabilities": [
+ {
+ "package": {
+ "ecosystem": "pip",
+ "name": "social-auth-app-django"
+ },
+ "vulnerable_version_range": "\u003C 5.6.0",
+ "first_patched_version": "5.6.0",
+ "vulnerable_functions": []
+ }
+ ],
+ "cvss_severities": {
+ "cvss_v3": {
+ "vector_string": null,
+ "score": 0.0
+ },
+ "cvss_v4": {
+ "vector_string": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N",
+ "score": 6.3
+ }
+ },
+ "cwes": [
+ {
+ "cwe_id": "CWE-290",
+ "name": "Authentication Bypass by Spoofing"
+ }
+ ],
+ "credits": [
+ {
+ "user": {
+ "login": "mel-mason",
+ "id": 19391457,
+ "node_id": "MDQ6VXNlcjE5MzkxNDU3",
+ "avatar_url": "https://avatars.githubusercontent.com/u/19391457?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/mel-mason",
+ "html_url": "https://github.com/mel-mason",
+ "followers_url": "https://api.github.com/users/mel-mason/followers",
+ "following_url": "https://api.github.com/users/mel-mason/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mel-mason/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mel-mason/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mel-mason/subscriptions",
+ "organizations_url": "https://api.github.com/users/mel-mason/orgs",
+ "repos_url": "https://api.github.com/users/mel-mason/repos",
+ "events_url": "https://api.github.com/users/mel-mason/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mel-mason/received_events",
+ "type": "User",
+ "user_view_type": "public",
+ "site_admin": false
+ },
+ "type": "reporter"
+ },
+ {
+ "user": {
+ "login": "vanya909",
+ "id": 53380238,
+ "node_id": "MDQ6VXNlcjUzMzgwMjM4",
+ "avatar_url": "https://avatars.githubusercontent.com/u/53380238?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/vanya909",
+ "html_url": "https://github.com/vanya909",
+ "followers_url": "https://api.github.com/users/vanya909/followers",
+ "following_url": "https://api.github.com/users/vanya909/following{/other_user}",
+ "gists_url": "https://api.github.com/users/vanya909/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/vanya909/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/vanya909/subscriptions",
+ "organizations_url": "https://api.github.com/users/vanya909/orgs",
+ "repos_url": "https://api.github.com/users/vanya909/repos",
+ "events_url": "https://api.github.com/users/vanya909/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/vanya909/received_events",
+ "type": "User",
+ "user_view_type": "public",
+ "site_admin": false
+ },
+ "type": "reporter"
+ },
+ {
+ "user": {
+ "login": "nijel",
+ "id": 212189,
+ "node_id": "MDQ6VXNlcjIxMjE4OQ==",
+ "avatar_url": "https://avatars.githubusercontent.com/u/212189?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/nijel",
+ "html_url": "https://github.com/nijel",
+ "followers_url": "https://api.github.com/users/nijel/followers",
+ "following_url": "https://api.github.com/users/nijel/following{/other_user}",
+ "gists_url": "https://api.github.com/users/nijel/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/nijel/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/nijel/subscriptions",
+ "organizations_url": "https://api.github.com/users/nijel/orgs",
+ "repos_url": "https://api.github.com/users/nijel/repos",
+ "events_url": "https://api.github.com/users/nijel/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/nijel/received_events",
+ "type": "User",
+ "user_view_type": "public",
+ "site_admin": false
+ },
+ "type": "remediation_developer"
+ }
+ ],
+ "cvss": {
+ "vector_string": null,
+ "score": null
+ }
+ },
+ {
+ "ghsa_id": "GHSA-cjjf-27cc-pvmv",
+ "cve_id": "CVE-2025-61773",
+ "url": "https://api.github.com/advisories/GHSA-cjjf-27cc-pvmv",
+ "html_url": "https://github.com/advisories/GHSA-cjjf-27cc-pvmv",
+ "summary": "pyLoad CNL and captcha handlers allow Code Injection via unsanitized parameters",
+ "description": "### Summary\npyLoad web interface contained insufficient input validation in both the Captcha script endpoint and the Click\u0027N\u0027Load (CNL) Blueprint. This flaw allowed untrusted user input to be processed unsafely, which could be exploited by an attacker to inject arbitrary content into the web UI or manipulate request handling. The vulnerability could lead to client-side code execution (XSS) or other unintended behaviors when a malicious payload is submitted.\n\nuser-supplied parameters from HTTP requests were not adequately validated or sanitized before being passed into the application logic and response generation. This allowed crafted input to alter the expected execution flow.\n CNL (Click\u0027N\u0027Load) blueprint exposed unsafe handling of untrusted parameters in HTTP requests. The application did not consistently enforce input validation or encoding, making it possible for an attacker to craft malicious requests.\n\n### PoC\n\n1. Run a vulnerable version of pyLoad prior to commit [\u0060f9d27f2\u0060](https://github.com/pyload/pyload/pull/4624).\n2. Start the web UI and access the Captcha or CNL endpoints.\n3. Submit a crafted request containing malicious JavaScript payloads in unvalidated parameters (\u0060/flash/addcrypted2?jk=function(){alert(1)}\u0026crypted=12345\u0060).\n4. Observe that the payload is reflected and executed in the client\u2019s browser, demonstrating cross-site scripting (XSS).\n\nExample request:\n\n\u0060\u0060\u0060http\nGET /flash/addcrypted2?jk=function(){alert(1)}\u0026crypted=12345 HTTP/1.1\nHost: 127.0.0.1:8000\nContent-Type: application/x-www-form-urlencoded\nContent-Length: 107\n\u0060\u0060\u0060\n\n### Impact\n\nExploiting this vulnerability allows an attacker to inject and execute arbitrary JavaScript within the browser session of a user accessing the pyLoad Web UI. In practice, this means an attacker could impersonate an administrator, steal authentication cookies or tokens, and perform unauthorized actions on behalf of the victim. Because the affected endpoints are part of the core interface, a successful attack undermines the trust and security of the entire application, potentially leading to a full compromise of the management interface and the data it controls. The impact is particularly severe in cases where the Web UI is exposed over a network without additional access restrictions, as it enables remote attackers to directly target users with crafted links or requests that trigger the vulnerability.",
+ "type": "reviewed",
+ "severity": "high",
+ "repository_advisory_url": "https://api.github.com/repos/pyload/pyload/security-advisories/GHSA-cjjf-27cc-pvmv",
+ "source_code_location": "https://github.com/pyload/pyload",
+ "identifiers": [
+ {
+ "value": "GHSA-cjjf-27cc-pvmv",
+ "type": "GHSA"
+ },
+ {
+ "value": "CVE-2025-61773",
+ "type": "CVE"
+ }
+ ],
+ "references": [
+ "https://github.com/pyload/pyload/security/advisories/GHSA-cjjf-27cc-pvmv",
+ "https://github.com/pyload/pyload/pull/4624",
+ "https://github.com/pyload/pyload/commit/5823327d0b797161c7195a1f660266d30a69f0ca",
+ "https://github.com/advisories/GHSA-cjjf-27cc-pvmv"
+ ],
+ "published_at": "2025-10-09T15:19:48Z",
+ "updated_at": "2025-10-09T15:19:48Z",
+ "github_reviewed_at": "2025-10-09T15:19:48Z",
+ "nvd_published_at": null,
+ "withdrawn_at": null,
+ "vulnerabilities": [
+ {
+ "package": {
+ "ecosystem": "pip",
+ "name": "pyload-ng"
+ },
+ "vulnerable_version_range": "\u003C 0.5.0b3.dev91",
+ "first_patched_version": "0.5.0b3.dev91",
+ "vulnerable_functions": []
+ }
+ ],
+ "cvss_severities": {
+ "cvss_v3": {
+ "vector_string": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N",
+ "score": 8.1
+ },
+ "cvss_v4": {
+ "vector_string": null,
+ "score": 0.0
+ }
+ },
+ "cwes": [
+ {
+ "cwe_id": "CWE-74",
+ "name": "Improper Neutralization of Special Elements in Output Used by a Downstream Component (\u0027Injection\u0027)"
+ },
+ {
+ "cwe_id": "CWE-79",
+ "name": "Improper Neutralization of Input During Web Page Generation (\u0027Cross-site Scripting\u0027)"
+ },
+ {
+ "cwe_id": "CWE-94",
+ "name": "Improper Control of Generation of Code (\u0027Code Injection\u0027)"
+ },
+ {
+ "cwe_id": "CWE-116",
+ "name": "Improper Encoding or Escaping of Output"
+ }
+ ],
+ "credits": [
+ {
+ "user": {
+ "login": "odaysec",
+ "id": 47859767,
+ "node_id": "MDQ6VXNlcjQ3ODU5NzY3",
+ "avatar_url": "https://avatars.githubusercontent.com/u/47859767?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/odaysec",
+ "html_url": "https://github.com/odaysec",
+ "followers_url": "https://api.github.com/users/odaysec/followers",
+ "following_url": "https://api.github.com/users/odaysec/following{/other_user}",
+ "gists_url": "https://api.github.com/users/odaysec/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/odaysec/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/odaysec/subscriptions",
+ "organizations_url": "https://api.github.com/users/odaysec/orgs",
+ "repos_url": "https://api.github.com/users/odaysec/repos",
+ "events_url": "https://api.github.com/users/odaysec/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/odaysec/received_events",
+ "type": "User",
+ "user_view_type": "public",
+ "site_admin": false
+ },
+ "type": "reporter"
+ }
+ ],
+ "cvss": {
+ "vector_string": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N",
+ "score": 8.1
+ }
+ },
+ {
+ "ghsa_id": "GHSA-77vh-xpmg-72qh",
+ "cve_id": null,
+ "url": "https://api.github.com/advisories/GHSA-77vh-xpmg-72qh",
+ "html_url": "https://github.com/advisories/GHSA-77vh-xpmg-72qh",
+ "summary": "Clarify \u0060mediaType\u0060 handling",
+ "description": "### Impact\nIn the OCI Image Specification version 1.0.1 and prior, manifest and index documents are not self-describing and documents with a single digest could be interpreted as either a manifest or an index.\n\n### Patches\nThe Image Specification will be updated to recommend that both manifest and index documents contain a \u0060mediaType\u0060 field to identify the type of document.\nRelease [v1.0.2](https://github.com/opencontainers/image-spec/releases/tag/v1.0.2) includes these updates.\n\n### Workarounds\nSoftware attempting to deserialize an ambiguous document may reject the document if it contains both \u201Cmanifests\u201D and \u201Clayers\u201D fields or \u201Cmanifests\u201D and \u201Cconfig\u201D fields.\n\n### References\nhttps://github.com/opencontainers/distribution-spec/security/advisories/GHSA-mc8v-mgrf-8f4m\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue in https://github.com/opencontainers/image-spec\n* Email us at [security@opencontainers.org](mailto:security@opencontainers.org)\n* https://github.com/opencontainers/image-spec/commits/v1.0.2\n",
+ "type": "reviewed",
+ "severity": "low",
+ "repository_advisory_url": "https://api.github.com/repos/opencontainers/image-spec/security-advisories/GHSA-77vh-xpmg-72qh",
+ "source_code_location": "https://github.com/opencontainers/image-spec",
+ "identifiers": [
+ {
+ "value": "GHSA-77vh-xpmg-72qh",
+ "type": "GHSA"
+ }
+ ],
+ "references": [
+ "https://github.com/opencontainers/distribution-spec/security/advisories/GHSA-mc8v-mgrf-8f4m",
+ "https://github.com/opencontainers/image-spec/security/advisories/GHSA-77vh-xpmg-72qh",
+ "https://github.com/opencontainers/image-spec/commit/693428a734f5bab1a84bd2f990d92ef1111cd60c",
+ "https://github.com/opencontainers/image-spec/releases/tag/v1.0.2",
+ "https://github.com/advisories/GHSA-77vh-xpmg-72qh"
+ ],
+ "published_at": "2021-11-18T16:02:41Z",
+ "updated_at": "2023-01-09T05:05:32Z",
+ "github_reviewed_at": "2021-11-17T23:13:41Z",
+ "nvd_published_at": null,
+ "withdrawn_at": null,
+ "vulnerabilities": [
+ {
+ "package": {
+ "ecosystem": "go",
+ "name": "github.com/opencontainers/image-spec"
+ },
+ "vulnerable_version_range": "\u003C 1.0.2",
+ "first_patched_version": "1.0.2",
+ "vulnerable_functions": []
+ }
+ ],
+ "cvss_severities": {
+ "cvss_v3": {
+ "vector_string": "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:N/I:L/A:N",
+ "score": 3.0
+ },
+ "cvss_v4": {
+ "vector_string": null,
+ "score": 0.0
+ }
+ },
+ "cwes": [
+ {
+ "cwe_id": "CWE-843",
+ "name": "Access of Resource Using Incompatible Type (\u0027Type Confusion\u0027)"
+ }
+ ],
+ "credits": [],
+ "cvss": {
+ "vector_string": "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:N/I:L/A:N",
+ "score": 3.0
+ }
+ },
+ {
+ "ghsa_id": "GHSA-7rjr-3q55-vv33",
+ "cve_id": "CVE-2021-45046",
+ "url": "https://api.github.com/advisories/GHSA-7rjr-3q55-vv33",
+ "html_url": "https://github.com/advisories/GHSA-7rjr-3q55-vv33",
+ "summary": "Incomplete fix for Apache Log4j vulnerability",
+ "description": "# Impact\n\nThe fix to address [CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228) in Apache Log4j 2.15.0 was incomplete in certain non-default configurations. This could allow attackers with control over Thread Context Map (MDC) input data when the logging configuration uses a non-default Pattern Layout with either a Context Lookup (for example, $${ctx:loginId}) or a Thread Context Map pattern (%X, %mdc, or %MDC) to craft malicious input data using a JNDI Lookup pattern resulting in a remote code execution (RCE) attack. \n\n## Affected packages\nOnly the \u0060org.apache.logging.log4j:log4j-core\u0060 package is directly affected by this vulnerability. The \u0060org.apache.logging.log4j:log4j-api\u0060 should be kept at the same version as the \u0060org.apache.logging.log4j:log4j-core\u0060 package to ensure compatability if in use.\n\n# Mitigation\n\nLog4j 2.16.0 fixes this issue by removing support for message lookup patterns and disabling JNDI functionality by default. This issue can be mitigated in prior releases (\u003C 2.16.0) by removing the JndiLookup class from the classpath (example: zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class).\n\nLog4j 2.15.0 restricts JNDI LDAP lookups to localhost by default. Note that previous mitigations involving configuration such as to set the system property \u0060log4j2.formatMsgNoLookups\u0060 to \u0060true\u0060 do NOT mitigate this specific vulnerability.",
+ "type": "reviewed",
+ "severity": "critical",
+ "repository_advisory_url": null,
+ "source_code_location": "",
+ "identifiers": [
+ {
+ "value": "GHSA-7rjr-3q55-vv33",
+ "type": "GHSA"
+ },
+ {
+ "value": "CVE-2021-45046",
+ "type": "CVE"
+ }
+ ],
+ "references": [
+ "https://nvd.nist.gov/vuln/detail/CVE-2021-45046",
+ "https://github.com/advisories/GHSA-jfh8-c2jp-5v3q",
+ "https://logging.apache.org/log4j/2.x/security.html",
+ "https://www.openwall.com/lists/oss-security/2021/12/14/4",
+ "https://www.cve.org/CVERecord?id=CVE-2021-44228",
+ "http://www.openwall.com/lists/oss-security/2021/12/14/4",
+ "https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00646.html",
+ "http://www.openwall.com/lists/oss-security/2021/12/15/3",
+ "https://cert-portal.siemens.com/productcert/pdf/ssa-661247.pdf",
+ "https://cert-portal.siemens.com/productcert/pdf/ssa-714170.pdf",
+ "https://www.kb.cert.org/vuls/id/930724",
+ "https://www.debian.org/security/2021/dsa-5022",
+ "https://psirt.global.sonicwall.com/vuln-detail/SNWLID-2021-0032",
+ "https://www.oracle.com/security-alerts/alert-cve-2021-44228.html",
+ "http://www.openwall.com/lists/oss-security/2021/12/18/1",
+ "https://cert-portal.siemens.com/productcert/pdf/ssa-397453.pdf",
+ "https://cert-portal.siemens.com/productcert/pdf/ssa-479842.pdf",
+ "https://www.oracle.com/security-alerts/cpujan2022.html",
+ "https://www.oracle.com/security-alerts/cpuapr2022.html",
+ "https://www.oracle.com/security-alerts/cpujul2022.html",
+ "https://security.gentoo.org/glsa/202310-16",
+ "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/SIG7FZULMNK2XF6FZRU4VWYDQXNMUGAJ",
+ "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/EOKPQGV24RRBBI4TBZUDQMM4MEH7MXCY",
+ "https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-apache-log4j-qRuKNEbd",
+ "https://github.com/advisories/GHSA-7rjr-3q55-vv33"
+ ],
+ "published_at": "2021-12-14T18:01:28Z",
+ "updated_at": "2025-05-09T12:28:41Z",
+ "github_reviewed_at": "2021-12-14T17:55:00Z",
+ "nvd_published_at": "2021-12-14T19:15:00Z",
+ "withdrawn_at": null,
+ "vulnerabilities": [
+ {
+ "package": {
+ "ecosystem": "maven",
+ "name": "org.apache.logging.log4j:log4j-core"
+ },
+ "vulnerable_version_range": "\u003E= 2.13.0, \u003C 2.16.0",
+ "first_patched_version": "2.16.0",
+ "vulnerable_functions": []
+ },
+ {
+ "package": {
+ "ecosystem": "maven",
+ "name": "org.apache.logging.log4j:log4j-core"
+ },
+ "vulnerable_version_range": "\u003C 2.12.2",
+ "first_patched_version": "2.12.2",
+ "vulnerable_functions": []
+ },
+ {
+ "package": {
+ "ecosystem": "maven",
+ "name": "org.ops4j.pax.logging:pax-logging-log4j2"
+ },
+ "vulnerable_version_range": "\u003E= 1.8.0, \u003C 1.9.2",
+ "first_patched_version": "1.9.2",
+ "vulnerable_functions": []
+ },
+ {
+ "package": {
+ "ecosystem": "maven",
+ "name": "org.ops4j.pax.logging:pax-logging-log4j2"
+ },
+ "vulnerable_version_range": "\u003E= 1.10.0, \u003C 1.10.8",
+ "first_patched_version": "1.10.8",
+ "vulnerable_functions": []
+ },
+ {
+ "package": {
+ "ecosystem": "maven",
+ "name": "org.ops4j.pax.logging:pax-logging-log4j2"
+ },
+ "vulnerable_version_range": "\u003E= 1.11.0, \u003C 1.11.11",
+ "first_patched_version": "1.11.11",
+ "vulnerable_functions": []
+ },
+ {
+ "package": {
+ "ecosystem": "maven",
+ "name": "org.ops4j.pax.logging:pax-logging-log4j2"
+ },
+ "vulnerable_version_range": "\u003E= 2.0.0, \u003C 2.0.12",
+ "first_patched_version": "2.0.12",
+ "vulnerable_functions": []
+ }
+ ],
+ "cvss_severities": {
+ "cvss_v3": {
+ "vector_string": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H",
+ "score": 9.1
+ },
+ "cvss_v4": {
+ "vector_string": null,
+ "score": 0.0
+ }
+ },
+ "cwes": [
+ {
+ "cwe_id": "CWE-502",
+ "name": "Deserialization of Untrusted Data"
+ },
+ {
+ "cwe_id": "CWE-917",
+ "name": "Improper Neutralization of Special Elements used in an Expression Language Statement (\u0027Expression Language Injection\u0027)"
+ }
+ ],
+ "credits": [
+ {
+ "user": {
+ "login": "mrjonstrong",
+ "id": 42520909,
+ "node_id": "MDQ6VXNlcjQyNTIwOTA5",
+ "avatar_url": "https://avatars.githubusercontent.com/u/42520909?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/mrjonstrong",
+ "html_url": "https://github.com/mrjonstrong",
+ "followers_url": "https://api.github.com/users/mrjonstrong/followers",
+ "following_url": "https://api.github.com/users/mrjonstrong/following{/other_user}",
+ "gists_url": "https://api.github.com/users/mrjonstrong/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/mrjonstrong/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/mrjonstrong/subscriptions",
+ "organizations_url": "https://api.github.com/users/mrjonstrong/orgs",
+ "repos_url": "https://api.github.com/users/mrjonstrong/repos",
+ "events_url": "https://api.github.com/users/mrjonstrong/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/mrjonstrong/received_events",
+ "type": "User",
+ "user_view_type": "public",
+ "site_admin": false
+ },
+ "type": "analyst"
+ },
+ {
+ "user": {
+ "login": "afdesk",
+ "id": 19297627,
+ "node_id": "MDQ6VXNlcjE5Mjk3NjI3",
+ "avatar_url": "https://avatars.githubusercontent.com/u/19297627?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/afdesk",
+ "html_url": "https://github.com/afdesk",
+ "followers_url": "https://api.github.com/users/afdesk/followers",
+ "following_url": "https://api.github.com/users/afdesk/following{/other_user}",
+ "gists_url": "https://api.github.com/users/afdesk/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/afdesk/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/afdesk/subscriptions",
+ "organizations_url": "https://api.github.com/users/afdesk/orgs",
+ "repos_url": "https://api.github.com/users/afdesk/repos",
+ "events_url": "https://api.github.com/users/afdesk/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/afdesk/received_events",
+ "type": "User",
+ "user_view_type": "public",
+ "site_admin": false
+ },
+ "type": "analyst"
+ },
+ {
+ "user": {
+ "login": "ppkarwasz",
+ "id": 12533274,
+ "node_id": "MDQ6VXNlcjEyNTMzMjc0",
+ "avatar_url": "https://avatars.githubusercontent.com/u/12533274?v=4",
+ "gravatar_id": "",
+ "url": "https://api.github.com/users/ppkarwasz",
+ "html_url": "https://github.com/ppkarwasz",
+ "followers_url": "https://api.github.com/users/ppkarwasz/followers",
+ "following_url": "https://api.github.com/users/ppkarwasz/following{/other_user}",
+ "gists_url": "https://api.github.com/users/ppkarwasz/gists{/gist_id}",
+ "starred_url": "https://api.github.com/users/ppkarwasz/starred{/owner}{/repo}",
+ "subscriptions_url": "https://api.github.com/users/ppkarwasz/subscriptions",
+ "organizations_url": "https://api.github.com/users/ppkarwasz/orgs",
+ "repos_url": "https://api.github.com/users/ppkarwasz/repos",
+ "events_url": "https://api.github.com/users/ppkarwasz/events{/privacy}",
+ "received_events_url": "https://api.github.com/users/ppkarwasz/received_events",
+ "type": "User",
+ "user_view_type": "public",
+ "site_admin": false
+ },
+ "type": "analyst"
+ }
+ ],
+ "cvss": {
+ "vector_string": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H",
+ "score": 9.1
+ },
+ "epss": {
+ "percentage": 0.9434,
+ "percentile": 0.9995
+ }
+ }
]
\ No newline at end of file
diff --git a/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.raw-osv.json b/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.raw-osv.json
index b48295ab..bea1df2e 100644
--- a/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.raw-osv.json
+++ b/src/StellaOps.Feedser.Source.Osv.Tests/Fixtures/osv-ghsa.raw-osv.json
@@ -1,714 +1,714 @@
-[
- {
- "id": "GHSA-wv4w-6qv2-qqfg",
- "summary": "Python Social Auth - Django has unsafe account association ",
- "details": "### Impact\n\nUpon authentication, the user could be associated by e-mail even if the \u0060associate_by_email\u0060 pipeline was not included. This could lead to account compromise when a third-party authentication service does not validate provided e-mail addresses or doesn\u0027t require unique e-mail addresses.\n\n### Patches\n\n* https://github.com/python-social-auth/social-app-django/pull/803\n\n### Workarounds\n\nReview the authentication service policy on e-mail addresses; many will not allow exploiting this vulnerability.",
- "aliases": [
- "CVE-2025-61783"
- ],
- "modified": "2025-10-09T17:57:29.916841Z",
- "published": "2025-10-09T17:08:05Z",
- "database_specific": {
- "github_reviewed_at": "2025-10-09T17:08:05Z",
- "severity": "MODERATE",
- "cwe_ids": [
- "CWE-290"
- ],
- "github_reviewed": true,
- "nvd_published_at": null
- },
- "references": [
- {
- "type": "WEB",
- "url": "https://github.com/python-social-auth/social-app-django/security/advisories/GHSA-wv4w-6qv2-qqfg"
- },
- {
- "type": "WEB",
- "url": "https://github.com/python-social-auth/social-app-django/issues/220"
- },
- {
- "type": "WEB",
- "url": "https://github.com/python-social-auth/social-app-django/issues/231"
- },
- {
- "type": "WEB",
- "url": "https://github.com/python-social-auth/social-app-django/issues/634"
- },
- {
- "type": "WEB",
- "url": "https://github.com/python-social-auth/social-app-django/pull/803"
- },
- {
- "type": "WEB",
- "url": "https://github.com/python-social-auth/social-app-django/commit/10c80e2ebabeccd4e9c84ad0e16e1db74148ed4c"
- },
- {
- "type": "PACKAGE",
- "url": "https://github.com/python-social-auth/social-app-django"
- }
- ],
- "affected": [
- {
- "package": {
- "name": "social-auth-app-django",
- "ecosystem": "PyPI",
- "purl": "pkg:pypi/social-auth-app-django"
- },
- "ranges": [
- {
- "type": "ECOSYSTEM",
- "events": [
- {
- "introduced": "0"
- },
- {
- "fixed": "5.6.0"
- }
- ]
- }
- ],
- "versions": [
- "0.0.1",
- "0.1.0",
- "1.0.0",
- "1.0.1",
- "1.1.0",
- "1.2.0",
- "2.0.0",
- "2.1.0",
- "3.0.0",
- "3.1.0",
- "3.3.0",
- "3.4.0",
- "4.0.0",
- "5.0.0",
- "5.1.0",
- "5.2.0",
- "5.3.0",
- "5.4.0",
- "5.4.1",
- "5.4.2",
- "5.4.3",
- "5.5.0",
- "5.5.1"
- ],
- "database_specific": {
- "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2025/10/GHSA-wv4w-6qv2-qqfg/GHSA-wv4w-6qv2-qqfg.json"
- }
- }
- ],
- "schema_version": "1.7.3",
- "severity": [
- {
- "type": "CVSS_V4",
- "score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N"
- }
- ]
- },
- {
- "id": "GHSA-cjjf-27cc-pvmv",
- "summary": "pyLoad CNL and captcha handlers allow Code Injection via unsanitized parameters",
- "details": "### Summary\npyLoad web interface contained insufficient input validation in both the Captcha script endpoint and the Click\u0027N\u0027Load (CNL) Blueprint. This flaw allowed untrusted user input to be processed unsafely, which could be exploited by an attacker to inject arbitrary content into the web UI or manipulate request handling. The vulnerability could lead to client-side code execution (XSS) or other unintended behaviors when a malicious payload is submitted.\n\nuser-supplied parameters from HTTP requests were not adequately validated or sanitized before being passed into the application logic and response generation. This allowed crafted input to alter the expected execution flow.\n CNL (Click\u0027N\u0027Load) blueprint exposed unsafe handling of untrusted parameters in HTTP requests. The application did not consistently enforce input validation or encoding, making it possible for an attacker to craft malicious requests.\n\n### PoC\n\n1. Run a vulnerable version of pyLoad prior to commit [\u0060f9d27f2\u0060](https://github.com/pyload/pyload/pull/4624).\n2. Start the web UI and access the Captcha or CNL endpoints.\n3. Submit a crafted request containing malicious JavaScript payloads in unvalidated parameters (\u0060/flash/addcrypted2?jk=function(){alert(1)}\u0026crypted=12345\u0060).\n4. Observe that the payload is reflected and executed in the client\u2019s browser, demonstrating cross-site scripting (XSS).\n\nExample request:\n\n\u0060\u0060\u0060http\nGET /flash/addcrypted2?jk=function(){alert(1)}\u0026crypted=12345 HTTP/1.1\nHost: 127.0.0.1:8000\nContent-Type: application/x-www-form-urlencoded\nContent-Length: 107\n\u0060\u0060\u0060\n\n### Impact\n\nExploiting this vulnerability allows an attacker to inject and execute arbitrary JavaScript within the browser session of a user accessing the pyLoad Web UI. In practice, this means an attacker could impersonate an administrator, steal authentication cookies or tokens, and perform unauthorized actions on behalf of the victim. Because the affected endpoints are part of the core interface, a successful attack undermines the trust and security of the entire application, potentially leading to a full compromise of the management interface and the data it controls. The impact is particularly severe in cases where the Web UI is exposed over a network without additional access restrictions, as it enables remote attackers to directly target users with crafted links or requests that trigger the vulnerability.",
- "aliases": [
- "CVE-2025-61773"
- ],
- "modified": "2025-10-09T15:59:13.250015Z",
- "published": "2025-10-09T15:19:48Z",
- "database_specific": {
- "github_reviewed_at": "2025-10-09T15:19:48Z",
- "github_reviewed": true,
- "cwe_ids": [
- "CWE-116",
- "CWE-74",
- "CWE-79",
- "CWE-94"
- ],
- "severity": "HIGH",
- "nvd_published_at": null
- },
- "references": [
- {
- "type": "WEB",
- "url": "https://github.com/pyload/pyload/security/advisories/GHSA-cjjf-27cc-pvmv"
- },
- {
- "type": "WEB",
- "url": "https://github.com/pyload/pyload/pull/4624"
- },
- {
- "type": "WEB",
- "url": "https://github.com/pyload/pyload/commit/5823327d0b797161c7195a1f660266d30a69f0ca"
- },
- {
- "type": "PACKAGE",
- "url": "https://github.com/pyload/pyload"
- }
- ],
- "affected": [
- {
- "package": {
- "name": "pyload-ng",
- "ecosystem": "PyPI",
- "purl": "pkg:pypi/pyload-ng"
- },
- "ranges": [
- {
- "type": "ECOSYSTEM",
- "events": [
- {
- "introduced": "0"
- },
- {
- "fixed": "0.5.0b3.dev91"
- }
- ]
- }
- ],
- "versions": [
- "0.5.0a5.dev528",
- "0.5.0a5.dev532",
- "0.5.0a5.dev535",
- "0.5.0a5.dev536",
- "0.5.0a5.dev537",
- "0.5.0a5.dev539",
- "0.5.0a5.dev540",
- "0.5.0a5.dev545",
- "0.5.0a5.dev562",
- "0.5.0a5.dev564",
- "0.5.0a5.dev565",
- "0.5.0a6.dev570",
- "0.5.0a6.dev578",
- "0.5.0a6.dev587",
- "0.5.0a7.dev596",
- "0.5.0a8.dev602",
- "0.5.0a9.dev615",
- "0.5.0a9.dev629",
- "0.5.0a9.dev632",
- "0.5.0a9.dev641",
- "0.5.0a9.dev643",
- "0.5.0a9.dev655",
- "0.5.0a9.dev806",
- "0.5.0b1.dev1",
- "0.5.0b1.dev2",
- "0.5.0b1.dev3",
- "0.5.0b1.dev4",
- "0.5.0b1.dev5",
- "0.5.0b2.dev10",
- "0.5.0b2.dev11",
- "0.5.0b2.dev12",
- "0.5.0b2.dev9",
- "0.5.0b3.dev13",
- "0.5.0b3.dev14",
- "0.5.0b3.dev17",
- "0.5.0b3.dev18",
- "0.5.0b3.dev19",
- "0.5.0b3.dev20",
- "0.5.0b3.dev21",
- "0.5.0b3.dev22",
- "0.5.0b3.dev24",
- "0.5.0b3.dev26",
- "0.5.0b3.dev27",
- "0.5.0b3.dev28",
- "0.5.0b3.dev29",
- "0.5.0b3.dev30",
- "0.5.0b3.dev31",
- "0.5.0b3.dev32",
- "0.5.0b3.dev33",
- "0.5.0b3.dev34",
- "0.5.0b3.dev35",
- "0.5.0b3.dev38",
- "0.5.0b3.dev39",
- "0.5.0b3.dev40",
- "0.5.0b3.dev41",
- "0.5.0b3.dev42",
- "0.5.0b3.dev43",
- "0.5.0b3.dev44",
- "0.5.0b3.dev45",
- "0.5.0b3.dev46",
- "0.5.0b3.dev47",
- "0.5.0b3.dev48",
- "0.5.0b3.dev49",
- "0.5.0b3.dev50",
- "0.5.0b3.dev51",
- "0.5.0b3.dev52",
- "0.5.0b3.dev53",
- "0.5.0b3.dev54",
- "0.5.0b3.dev57",
- "0.5.0b3.dev60",
- "0.5.0b3.dev62",
- "0.5.0b3.dev64",
- "0.5.0b3.dev65",
- "0.5.0b3.dev66",
- "0.5.0b3.dev67",
- "0.5.0b3.dev68",
- "0.5.0b3.dev69",
- "0.5.0b3.dev70",
- "0.5.0b3.dev71",
- "0.5.0b3.dev72",
- "0.5.0b3.dev73",
- "0.5.0b3.dev74",
- "0.5.0b3.dev75",
- "0.5.0b3.dev76",
- "0.5.0b3.dev77",
- "0.5.0b3.dev78",
- "0.5.0b3.dev79",
- "0.5.0b3.dev80",
- "0.5.0b3.dev81",
- "0.5.0b3.dev82",
- "0.5.0b3.dev85",
- "0.5.0b3.dev87",
- "0.5.0b3.dev88",
- "0.5.0b3.dev89",
- "0.5.0b3.dev90"
- ],
- "database_specific": {
- "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2025/10/GHSA-cjjf-27cc-pvmv/GHSA-cjjf-27cc-pvmv.json"
- }
- }
- ],
- "schema_version": "1.7.3",
- "severity": [
- {
- "type": "CVSS_V3",
- "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N"
- }
- ]
- },
- {
- "id": "GHSA-77vh-xpmg-72qh",
- "summary": "Clarify \u0060mediaType\u0060 handling",
- "details": "### Impact\nIn the OCI Image Specification version 1.0.1 and prior, manifest and index documents are not self-describing and documents with a single digest could be interpreted as either a manifest or an index.\n\n### Patches\nThe Image Specification will be updated to recommend that both manifest and index documents contain a \u0060mediaType\u0060 field to identify the type of document.\nRelease [v1.0.2](https://github.com/opencontainers/image-spec/releases/tag/v1.0.2) includes these updates.\n\n### Workarounds\nSoftware attempting to deserialize an ambiguous document may reject the document if it contains both \u201Cmanifests\u201D and \u201Clayers\u201D fields or \u201Cmanifests\u201D and \u201Cconfig\u201D fields.\n\n### References\nhttps://github.com/opencontainers/distribution-spec/security/advisories/GHSA-mc8v-mgrf-8f4m\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue in https://github.com/opencontainers/image-spec\n* Email us at [security@opencontainers.org](mailto:security@opencontainers.org)\n* https://github.com/opencontainers/image-spec/commits/v1.0.2\n",
- "modified": "2021-11-24T19:43:35Z",
- "published": "2021-11-18T16:02:41Z",
- "related": [
- "CGA-j36r-723f-8c29"
- ],
- "database_specific": {
- "github_reviewed": true,
- "nvd_published_at": null,
- "github_reviewed_at": "2021-11-17T23:13:41Z",
- "cwe_ids": [
- "CWE-843"
- ],
- "severity": "LOW"
- },
- "references": [
- {
- "type": "WEB",
- "url": "https://github.com/opencontainers/distribution-spec/security/advisories/GHSA-mc8v-mgrf-8f4m"
- },
- {
- "type": "WEB",
- "url": "https://github.com/opencontainers/image-spec/security/advisories/GHSA-77vh-xpmg-72qh"
- },
- {
- "type": "WEB",
- "url": "https://github.com/opencontainers/image-spec/commit/693428a734f5bab1a84bd2f990d92ef1111cd60c"
- },
- {
- "type": "PACKAGE",
- "url": "https://github.com/opencontainers/image-spec"
- },
- {
- "type": "WEB",
- "url": "https://github.com/opencontainers/image-spec/releases/tag/v1.0.2"
- }
- ],
- "affected": [
- {
- "package": {
- "name": "github.com/opencontainers/image-spec",
- "ecosystem": "Go",
- "purl": "pkg:golang/github.com/opencontainers/image-spec"
- },
- "ranges": [
- {
- "type": "SEMVER",
- "events": [
- {
- "introduced": "0"
- },
- {
- "fixed": "1.0.2"
- }
- ]
- }
- ],
- "database_specific": {
- "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/11/GHSA-77vh-xpmg-72qh/GHSA-77vh-xpmg-72qh.json"
- }
- }
- ],
- "schema_version": "1.7.3",
- "severity": [
- {
- "type": "CVSS_V3",
- "score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:N/I:L/A:N"
- }
- ]
- },
- {
- "id": "GHSA-7rjr-3q55-vv33",
- "summary": "Incomplete fix for Apache Log4j vulnerability",
- "details": "# Impact\n\nThe fix to address [CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228) in Apache Log4j 2.15.0 was incomplete in certain non-default configurations. This could allow attackers with control over Thread Context Map (MDC) input data when the logging configuration uses a non-default Pattern Layout with either a Context Lookup (for example, $${ctx:loginId}) or a Thread Context Map pattern (%X, %mdc, or %MDC) to craft malicious input data using a JNDI Lookup pattern resulting in a remote code execution (RCE) attack. \n\n## Affected packages\nOnly the \u0060org.apache.logging.log4j:log4j-core\u0060 package is directly affected by this vulnerability. The \u0060org.apache.logging.log4j:log4j-api\u0060 should be kept at the same version as the \u0060org.apache.logging.log4j:log4j-core\u0060 package to ensure compatability if in use.\n\n# Mitigation\n\nLog4j 2.16.0 fixes this issue by removing support for message lookup patterns and disabling JNDI functionality by default. This issue can be mitigated in prior releases (\u003C 2.16.0) by removing the JndiLookup class from the classpath (example: zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class).\n\nLog4j 2.15.0 restricts JNDI LDAP lookups to localhost by default. Note that previous mitigations involving configuration such as to set the system property \u0060log4j2.formatMsgNoLookups\u0060 to \u0060true\u0060 do NOT mitigate this specific vulnerability.",
- "aliases": [
- "CVE-2021-45046"
- ],
- "modified": "2025-05-09T13:13:16.169374Z",
- "published": "2021-12-14T18:01:28Z",
- "database_specific": {
- "github_reviewed_at": "2021-12-14T17:55:00Z",
- "cwe_ids": [
- "CWE-502",
- "CWE-917"
- ],
- "github_reviewed": true,
- "severity": "CRITICAL",
- "nvd_published_at": "2021-12-14T19:15:00Z"
- },
- "references": [
- {
- "type": "ADVISORY",
- "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-45046"
- },
- {
- "type": "WEB",
- "url": "https://www.oracle.com/security-alerts/cpujul2022.html"
- },
- {
- "type": "WEB",
- "url": "https://www.oracle.com/security-alerts/cpujan2022.html"
- },
- {
- "type": "WEB",
- "url": "https://www.oracle.com/security-alerts/cpuapr2022.html"
- },
- {
- "type": "WEB",
- "url": "https://www.oracle.com/security-alerts/alert-cve-2021-44228.html"
- },
- {
- "type": "WEB",
- "url": "https://www.openwall.com/lists/oss-security/2021/12/14/4"
- },
- {
- "type": "WEB",
- "url": "https://www.kb.cert.org/vuls/id/930724"
- },
- {
- "type": "WEB",
- "url": "https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00646.html"
- },
- {
- "type": "WEB",
- "url": "https://www.debian.org/security/2021/dsa-5022"
- },
- {
- "type": "WEB",
- "url": "https://www.cve.org/CVERecord?id=CVE-2021-44228"
- },
- {
- "type": "WEB",
- "url": "https://security.gentoo.org/glsa/202310-16"
- },
- {
- "type": "WEB",
- "url": "https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-apache-log4j-qRuKNEbd"
- },
- {
- "type": "WEB",
- "url": "https://psirt.global.sonicwall.com/vuln-detail/SNWLID-2021-0032"
- },
- {
- "type": "WEB",
- "url": "https://logging.apache.org/log4j/2.x/security.html"
- },
- {
- "type": "WEB",
- "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/SIG7FZULMNK2XF6FZRU4VWYDQXNMUGAJ"
- },
- {
- "type": "WEB",
- "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/EOKPQGV24RRBBI4TBZUDQMM4MEH7MXCY"
- },
- {
- "type": "ADVISORY",
- "url": "https://github.com/advisories/GHSA-jfh8-c2jp-5v3q"
- },
- {
- "type": "WEB",
- "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-714170.pdf"
- },
- {
- "type": "WEB",
- "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-661247.pdf"
- },
- {
- "type": "WEB",
- "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-479842.pdf"
- },
- {
- "type": "WEB",
- "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-397453.pdf"
- },
- {
- "type": "WEB",
- "url": "http://www.openwall.com/lists/oss-security/2021/12/14/4"
- },
- {
- "type": "WEB",
- "url": "http://www.openwall.com/lists/oss-security/2021/12/15/3"
- },
- {
- "type": "WEB",
- "url": "http://www.openwall.com/lists/oss-security/2021/12/18/1"
- }
- ],
- "affected": [
- {
- "package": {
- "name": "org.apache.logging.log4j:log4j-core",
- "ecosystem": "Maven",
- "purl": "pkg:maven/org.apache.logging.log4j/log4j-core"
- },
- "ranges": [
- {
- "type": "ECOSYSTEM",
- "events": [
- {
- "introduced": "2.13.0"
- },
- {
- "fixed": "2.16.0"
- }
- ]
- }
- ],
- "versions": [
- "2.13.0",
- "2.13.1",
- "2.13.2",
- "2.13.3",
- "2.14.0",
- "2.14.1",
- "2.15.0"
- ],
- "database_specific": {
- "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/12/GHSA-7rjr-3q55-vv33/GHSA-7rjr-3q55-vv33.json"
- }
- },
- {
- "package": {
- "name": "org.apache.logging.log4j:log4j-core",
- "ecosystem": "Maven",
- "purl": "pkg:maven/org.apache.logging.log4j/log4j-core"
- },
- "ranges": [
- {
- "type": "ECOSYSTEM",
- "events": [
- {
- "introduced": "0"
- },
- {
- "fixed": "2.12.2"
- }
- ]
- }
- ],
- "versions": [
- "2.0",
- "2.0-alpha1",
- "2.0-alpha2",
- "2.0-beta1",
- "2.0-beta2",
- "2.0-beta3",
- "2.0-beta4",
- "2.0-beta5",
- "2.0-beta6",
- "2.0-beta7",
- "2.0-beta8",
- "2.0-beta9",
- "2.0-rc1",
- "2.0-rc2",
- "2.0.1",
- "2.0.2",
- "2.1",
- "2.10.0",
- "2.11.0",
- "2.11.1",
- "2.11.2",
- "2.12.0",
- "2.12.1",
- "2.2",
- "2.3",
- "2.3.1",
- "2.3.2",
- "2.4",
- "2.4.1",
- "2.5",
- "2.6",
- "2.6.1",
- "2.6.2",
- "2.7",
- "2.8",
- "2.8.1",
- "2.8.2",
- "2.9.0",
- "2.9.1"
- ],
- "database_specific": {
- "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/12/GHSA-7rjr-3q55-vv33/GHSA-7rjr-3q55-vv33.json"
- }
- },
- {
- "package": {
- "name": "org.ops4j.pax.logging:pax-logging-log4j2",
- "ecosystem": "Maven",
- "purl": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2"
- },
- "ranges": [
- {
- "type": "ECOSYSTEM",
- "events": [
- {
- "introduced": "1.8.0"
- },
- {
- "fixed": "1.9.2"
- }
- ]
- }
- ],
- "versions": [
- "1.8.0",
- "1.8.1",
- "1.8.2",
- "1.8.3",
- "1.8.4",
- "1.8.5",
- "1.8.6",
- "1.8.7",
- "1.9.0",
- "1.9.1"
- ],
- "database_specific": {
- "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/12/GHSA-7rjr-3q55-vv33/GHSA-7rjr-3q55-vv33.json"
- }
- },
- {
- "package": {
- "name": "org.ops4j.pax.logging:pax-logging-log4j2",
- "ecosystem": "Maven",
- "purl": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2"
- },
- "ranges": [
- {
- "type": "ECOSYSTEM",
- "events": [
- {
- "introduced": "1.10.0"
- },
- {
- "fixed": "1.10.8"
- }
- ]
- }
- ],
- "versions": [
- "1.10.0",
- "1.10.1",
- "1.10.2",
- "1.10.3",
- "1.10.4",
- "1.10.5",
- "1.10.6",
- "1.10.7"
- ],
- "database_specific": {
- "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/12/GHSA-7rjr-3q55-vv33/GHSA-7rjr-3q55-vv33.json"
- }
- },
- {
- "package": {
- "name": "org.ops4j.pax.logging:pax-logging-log4j2",
- "ecosystem": "Maven",
- "purl": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2"
- },
- "ranges": [
- {
- "type": "ECOSYSTEM",
- "events": [
- {
- "introduced": "1.11.0"
- },
- {
- "fixed": "1.11.11"
- }
- ]
- }
- ],
- "versions": [
- "1.11.0",
- "1.11.1",
- "1.11.10",
- "1.11.2",
- "1.11.3",
- "1.11.4",
- "1.11.5",
- "1.11.6",
- "1.11.7",
- "1.11.8",
- "1.11.9"
- ],
- "database_specific": {
- "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/12/GHSA-7rjr-3q55-vv33/GHSA-7rjr-3q55-vv33.json"
- }
- },
- {
- "package": {
- "name": "org.ops4j.pax.logging:pax-logging-log4j2",
- "ecosystem": "Maven",
- "purl": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2"
- },
- "ranges": [
- {
- "type": "ECOSYSTEM",
- "events": [
- {
- "introduced": "2.0.0"
- },
- {
- "fixed": "2.0.12"
- }
- ]
- }
- ],
- "versions": [
- "2.0.0",
- "2.0.1",
- "2.0.10",
- "2.0.11",
- "2.0.2",
- "2.0.3",
- "2.0.4",
- "2.0.5",
- "2.0.6",
- "2.0.7",
- "2.0.8",
- "2.0.9"
- ],
- "database_specific": {
- "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/12/GHSA-7rjr-3q55-vv33/GHSA-7rjr-3q55-vv33.json"
- }
- }
- ],
- "schema_version": "1.7.3",
- "severity": [
- {
- "type": "CVSS_V3",
- "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H"
- }
- ]
- }
+[
+ {
+ "id": "GHSA-wv4w-6qv2-qqfg",
+ "summary": "Python Social Auth - Django has unsafe account association ",
+ "details": "### Impact\n\nUpon authentication, the user could be associated by e-mail even if the \u0060associate_by_email\u0060 pipeline was not included. This could lead to account compromise when a third-party authentication service does not validate provided e-mail addresses or doesn\u0027t require unique e-mail addresses.\n\n### Patches\n\n* https://github.com/python-social-auth/social-app-django/pull/803\n\n### Workarounds\n\nReview the authentication service policy on e-mail addresses; many will not allow exploiting this vulnerability.",
+ "aliases": [
+ "CVE-2025-61783"
+ ],
+ "modified": "2025-10-09T17:57:29.916841Z",
+ "published": "2025-10-09T17:08:05Z",
+ "database_specific": {
+ "github_reviewed_at": "2025-10-09T17:08:05Z",
+ "severity": "MODERATE",
+ "cwe_ids": [
+ "CWE-290"
+ ],
+ "github_reviewed": true,
+ "nvd_published_at": null
+ },
+ "references": [
+ {
+ "type": "WEB",
+ "url": "https://github.com/python-social-auth/social-app-django/security/advisories/GHSA-wv4w-6qv2-qqfg"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/python-social-auth/social-app-django/issues/220"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/python-social-auth/social-app-django/issues/231"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/python-social-auth/social-app-django/issues/634"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/python-social-auth/social-app-django/pull/803"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/python-social-auth/social-app-django/commit/10c80e2ebabeccd4e9c84ad0e16e1db74148ed4c"
+ },
+ {
+ "type": "PACKAGE",
+ "url": "https://github.com/python-social-auth/social-app-django"
+ }
+ ],
+ "affected": [
+ {
+ "package": {
+ "name": "social-auth-app-django",
+ "ecosystem": "PyPI",
+ "purl": "pkg:pypi/social-auth-app-django"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "0"
+ },
+ {
+ "fixed": "5.6.0"
+ }
+ ]
+ }
+ ],
+ "versions": [
+ "0.0.1",
+ "0.1.0",
+ "1.0.0",
+ "1.0.1",
+ "1.1.0",
+ "1.2.0",
+ "2.0.0",
+ "2.1.0",
+ "3.0.0",
+ "3.1.0",
+ "3.3.0",
+ "3.4.0",
+ "4.0.0",
+ "5.0.0",
+ "5.1.0",
+ "5.2.0",
+ "5.3.0",
+ "5.4.0",
+ "5.4.1",
+ "5.4.2",
+ "5.4.3",
+ "5.5.0",
+ "5.5.1"
+ ],
+ "database_specific": {
+ "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2025/10/GHSA-wv4w-6qv2-qqfg/GHSA-wv4w-6qv2-qqfg.json"
+ }
+ }
+ ],
+ "schema_version": "1.7.3",
+ "severity": [
+ {
+ "type": "CVSS_V4",
+ "score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N"
+ }
+ ]
+ },
+ {
+ "id": "GHSA-cjjf-27cc-pvmv",
+ "summary": "pyLoad CNL and captcha handlers allow Code Injection via unsanitized parameters",
+ "details": "### Summary\npyLoad web interface contained insufficient input validation in both the Captcha script endpoint and the Click\u0027N\u0027Load (CNL) Blueprint. This flaw allowed untrusted user input to be processed unsafely, which could be exploited by an attacker to inject arbitrary content into the web UI or manipulate request handling. The vulnerability could lead to client-side code execution (XSS) or other unintended behaviors when a malicious payload is submitted.\n\nuser-supplied parameters from HTTP requests were not adequately validated or sanitized before being passed into the application logic and response generation. This allowed crafted input to alter the expected execution flow.\n CNL (Click\u0027N\u0027Load) blueprint exposed unsafe handling of untrusted parameters in HTTP requests. The application did not consistently enforce input validation or encoding, making it possible for an attacker to craft malicious requests.\n\n### PoC\n\n1. Run a vulnerable version of pyLoad prior to commit [\u0060f9d27f2\u0060](https://github.com/pyload/pyload/pull/4624).\n2. Start the web UI and access the Captcha or CNL endpoints.\n3. Submit a crafted request containing malicious JavaScript payloads in unvalidated parameters (\u0060/flash/addcrypted2?jk=function(){alert(1)}\u0026crypted=12345\u0060).\n4. Observe that the payload is reflected and executed in the client\u2019s browser, demonstrating cross-site scripting (XSS).\n\nExample request:\n\n\u0060\u0060\u0060http\nGET /flash/addcrypted2?jk=function(){alert(1)}\u0026crypted=12345 HTTP/1.1\nHost: 127.0.0.1:8000\nContent-Type: application/x-www-form-urlencoded\nContent-Length: 107\n\u0060\u0060\u0060\n\n### Impact\n\nExploiting this vulnerability allows an attacker to inject and execute arbitrary JavaScript within the browser session of a user accessing the pyLoad Web UI. In practice, this means an attacker could impersonate an administrator, steal authentication cookies or tokens, and perform unauthorized actions on behalf of the victim. Because the affected endpoints are part of the core interface, a successful attack undermines the trust and security of the entire application, potentially leading to a full compromise of the management interface and the data it controls. The impact is particularly severe in cases where the Web UI is exposed over a network without additional access restrictions, as it enables remote attackers to directly target users with crafted links or requests that trigger the vulnerability.",
+ "aliases": [
+ "CVE-2025-61773"
+ ],
+ "modified": "2025-10-09T15:59:13.250015Z",
+ "published": "2025-10-09T15:19:48Z",
+ "database_specific": {
+ "github_reviewed_at": "2025-10-09T15:19:48Z",
+ "github_reviewed": true,
+ "cwe_ids": [
+ "CWE-116",
+ "CWE-74",
+ "CWE-79",
+ "CWE-94"
+ ],
+ "severity": "HIGH",
+ "nvd_published_at": null
+ },
+ "references": [
+ {
+ "type": "WEB",
+ "url": "https://github.com/pyload/pyload/security/advisories/GHSA-cjjf-27cc-pvmv"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/pyload/pyload/pull/4624"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/pyload/pyload/commit/5823327d0b797161c7195a1f660266d30a69f0ca"
+ },
+ {
+ "type": "PACKAGE",
+ "url": "https://github.com/pyload/pyload"
+ }
+ ],
+ "affected": [
+ {
+ "package": {
+ "name": "pyload-ng",
+ "ecosystem": "PyPI",
+ "purl": "pkg:pypi/pyload-ng"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "0"
+ },
+ {
+ "fixed": "0.5.0b3.dev91"
+ }
+ ]
+ }
+ ],
+ "versions": [
+ "0.5.0a5.dev528",
+ "0.5.0a5.dev532",
+ "0.5.0a5.dev535",
+ "0.5.0a5.dev536",
+ "0.5.0a5.dev537",
+ "0.5.0a5.dev539",
+ "0.5.0a5.dev540",
+ "0.5.0a5.dev545",
+ "0.5.0a5.dev562",
+ "0.5.0a5.dev564",
+ "0.5.0a5.dev565",
+ "0.5.0a6.dev570",
+ "0.5.0a6.dev578",
+ "0.5.0a6.dev587",
+ "0.5.0a7.dev596",
+ "0.5.0a8.dev602",
+ "0.5.0a9.dev615",
+ "0.5.0a9.dev629",
+ "0.5.0a9.dev632",
+ "0.5.0a9.dev641",
+ "0.5.0a9.dev643",
+ "0.5.0a9.dev655",
+ "0.5.0a9.dev806",
+ "0.5.0b1.dev1",
+ "0.5.0b1.dev2",
+ "0.5.0b1.dev3",
+ "0.5.0b1.dev4",
+ "0.5.0b1.dev5",
+ "0.5.0b2.dev10",
+ "0.5.0b2.dev11",
+ "0.5.0b2.dev12",
+ "0.5.0b2.dev9",
+ "0.5.0b3.dev13",
+ "0.5.0b3.dev14",
+ "0.5.0b3.dev17",
+ "0.5.0b3.dev18",
+ "0.5.0b3.dev19",
+ "0.5.0b3.dev20",
+ "0.5.0b3.dev21",
+ "0.5.0b3.dev22",
+ "0.5.0b3.dev24",
+ "0.5.0b3.dev26",
+ "0.5.0b3.dev27",
+ "0.5.0b3.dev28",
+ "0.5.0b3.dev29",
+ "0.5.0b3.dev30",
+ "0.5.0b3.dev31",
+ "0.5.0b3.dev32",
+ "0.5.0b3.dev33",
+ "0.5.0b3.dev34",
+ "0.5.0b3.dev35",
+ "0.5.0b3.dev38",
+ "0.5.0b3.dev39",
+ "0.5.0b3.dev40",
+ "0.5.0b3.dev41",
+ "0.5.0b3.dev42",
+ "0.5.0b3.dev43",
+ "0.5.0b3.dev44",
+ "0.5.0b3.dev45",
+ "0.5.0b3.dev46",
+ "0.5.0b3.dev47",
+ "0.5.0b3.dev48",
+ "0.5.0b3.dev49",
+ "0.5.0b3.dev50",
+ "0.5.0b3.dev51",
+ "0.5.0b3.dev52",
+ "0.5.0b3.dev53",
+ "0.5.0b3.dev54",
+ "0.5.0b3.dev57",
+ "0.5.0b3.dev60",
+ "0.5.0b3.dev62",
+ "0.5.0b3.dev64",
+ "0.5.0b3.dev65",
+ "0.5.0b3.dev66",
+ "0.5.0b3.dev67",
+ "0.5.0b3.dev68",
+ "0.5.0b3.dev69",
+ "0.5.0b3.dev70",
+ "0.5.0b3.dev71",
+ "0.5.0b3.dev72",
+ "0.5.0b3.dev73",
+ "0.5.0b3.dev74",
+ "0.5.0b3.dev75",
+ "0.5.0b3.dev76",
+ "0.5.0b3.dev77",
+ "0.5.0b3.dev78",
+ "0.5.0b3.dev79",
+ "0.5.0b3.dev80",
+ "0.5.0b3.dev81",
+ "0.5.0b3.dev82",
+ "0.5.0b3.dev85",
+ "0.5.0b3.dev87",
+ "0.5.0b3.dev88",
+ "0.5.0b3.dev89",
+ "0.5.0b3.dev90"
+ ],
+ "database_specific": {
+ "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2025/10/GHSA-cjjf-27cc-pvmv/GHSA-cjjf-27cc-pvmv.json"
+ }
+ }
+ ],
+ "schema_version": "1.7.3",
+ "severity": [
+ {
+ "type": "CVSS_V3",
+ "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N"
+ }
+ ]
+ },
+ {
+ "id": "GHSA-77vh-xpmg-72qh",
+ "summary": "Clarify \u0060mediaType\u0060 handling",
+ "details": "### Impact\nIn the OCI Image Specification version 1.0.1 and prior, manifest and index documents are not self-describing and documents with a single digest could be interpreted as either a manifest or an index.\n\n### Patches\nThe Image Specification will be updated to recommend that both manifest and index documents contain a \u0060mediaType\u0060 field to identify the type of document.\nRelease [v1.0.2](https://github.com/opencontainers/image-spec/releases/tag/v1.0.2) includes these updates.\n\n### Workarounds\nSoftware attempting to deserialize an ambiguous document may reject the document if it contains both \u201Cmanifests\u201D and \u201Clayers\u201D fields or \u201Cmanifests\u201D and \u201Cconfig\u201D fields.\n\n### References\nhttps://github.com/opencontainers/distribution-spec/security/advisories/GHSA-mc8v-mgrf-8f4m\n\n### For more information\nIf you have any questions or comments about this advisory:\n* Open an issue in https://github.com/opencontainers/image-spec\n* Email us at [security@opencontainers.org](mailto:security@opencontainers.org)\n* https://github.com/opencontainers/image-spec/commits/v1.0.2\n",
+ "modified": "2021-11-24T19:43:35Z",
+ "published": "2021-11-18T16:02:41Z",
+ "related": [
+ "CGA-j36r-723f-8c29"
+ ],
+ "database_specific": {
+ "github_reviewed": true,
+ "nvd_published_at": null,
+ "github_reviewed_at": "2021-11-17T23:13:41Z",
+ "cwe_ids": [
+ "CWE-843"
+ ],
+ "severity": "LOW"
+ },
+ "references": [
+ {
+ "type": "WEB",
+ "url": "https://github.com/opencontainers/distribution-spec/security/advisories/GHSA-mc8v-mgrf-8f4m"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/opencontainers/image-spec/security/advisories/GHSA-77vh-xpmg-72qh"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/opencontainers/image-spec/commit/693428a734f5bab1a84bd2f990d92ef1111cd60c"
+ },
+ {
+ "type": "PACKAGE",
+ "url": "https://github.com/opencontainers/image-spec"
+ },
+ {
+ "type": "WEB",
+ "url": "https://github.com/opencontainers/image-spec/releases/tag/v1.0.2"
+ }
+ ],
+ "affected": [
+ {
+ "package": {
+ "name": "github.com/opencontainers/image-spec",
+ "ecosystem": "Go",
+ "purl": "pkg:golang/github.com/opencontainers/image-spec"
+ },
+ "ranges": [
+ {
+ "type": "SEMVER",
+ "events": [
+ {
+ "introduced": "0"
+ },
+ {
+ "fixed": "1.0.2"
+ }
+ ]
+ }
+ ],
+ "database_specific": {
+ "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/11/GHSA-77vh-xpmg-72qh/GHSA-77vh-xpmg-72qh.json"
+ }
+ }
+ ],
+ "schema_version": "1.7.3",
+ "severity": [
+ {
+ "type": "CVSS_V3",
+ "score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:N/I:L/A:N"
+ }
+ ]
+ },
+ {
+ "id": "GHSA-7rjr-3q55-vv33",
+ "summary": "Incomplete fix for Apache Log4j vulnerability",
+ "details": "# Impact\n\nThe fix to address [CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228) in Apache Log4j 2.15.0 was incomplete in certain non-default configurations. This could allow attackers with control over Thread Context Map (MDC) input data when the logging configuration uses a non-default Pattern Layout with either a Context Lookup (for example, $${ctx:loginId}) or a Thread Context Map pattern (%X, %mdc, or %MDC) to craft malicious input data using a JNDI Lookup pattern resulting in a remote code execution (RCE) attack. \n\n## Affected packages\nOnly the \u0060org.apache.logging.log4j:log4j-core\u0060 package is directly affected by this vulnerability. The \u0060org.apache.logging.log4j:log4j-api\u0060 should be kept at the same version as the \u0060org.apache.logging.log4j:log4j-core\u0060 package to ensure compatability if in use.\n\n# Mitigation\n\nLog4j 2.16.0 fixes this issue by removing support for message lookup patterns and disabling JNDI functionality by default. This issue can be mitigated in prior releases (\u003C 2.16.0) by removing the JndiLookup class from the classpath (example: zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class).\n\nLog4j 2.15.0 restricts JNDI LDAP lookups to localhost by default. Note that previous mitigations involving configuration such as to set the system property \u0060log4j2.formatMsgNoLookups\u0060 to \u0060true\u0060 do NOT mitigate this specific vulnerability.",
+ "aliases": [
+ "CVE-2021-45046"
+ ],
+ "modified": "2025-05-09T13:13:16.169374Z",
+ "published": "2021-12-14T18:01:28Z",
+ "database_specific": {
+ "github_reviewed_at": "2021-12-14T17:55:00Z",
+ "cwe_ids": [
+ "CWE-502",
+ "CWE-917"
+ ],
+ "github_reviewed": true,
+ "severity": "CRITICAL",
+ "nvd_published_at": "2021-12-14T19:15:00Z"
+ },
+ "references": [
+ {
+ "type": "ADVISORY",
+ "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-45046"
+ },
+ {
+ "type": "WEB",
+ "url": "https://www.oracle.com/security-alerts/cpujul2022.html"
+ },
+ {
+ "type": "WEB",
+ "url": "https://www.oracle.com/security-alerts/cpujan2022.html"
+ },
+ {
+ "type": "WEB",
+ "url": "https://www.oracle.com/security-alerts/cpuapr2022.html"
+ },
+ {
+ "type": "WEB",
+ "url": "https://www.oracle.com/security-alerts/alert-cve-2021-44228.html"
+ },
+ {
+ "type": "WEB",
+ "url": "https://www.openwall.com/lists/oss-security/2021/12/14/4"
+ },
+ {
+ "type": "WEB",
+ "url": "https://www.kb.cert.org/vuls/id/930724"
+ },
+ {
+ "type": "WEB",
+ "url": "https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00646.html"
+ },
+ {
+ "type": "WEB",
+ "url": "https://www.debian.org/security/2021/dsa-5022"
+ },
+ {
+ "type": "WEB",
+ "url": "https://www.cve.org/CVERecord?id=CVE-2021-44228"
+ },
+ {
+ "type": "WEB",
+ "url": "https://security.gentoo.org/glsa/202310-16"
+ },
+ {
+ "type": "WEB",
+ "url": "https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-apache-log4j-qRuKNEbd"
+ },
+ {
+ "type": "WEB",
+ "url": "https://psirt.global.sonicwall.com/vuln-detail/SNWLID-2021-0032"
+ },
+ {
+ "type": "WEB",
+ "url": "https://logging.apache.org/log4j/2.x/security.html"
+ },
+ {
+ "type": "WEB",
+ "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/SIG7FZULMNK2XF6FZRU4VWYDQXNMUGAJ"
+ },
+ {
+ "type": "WEB",
+ "url": "https://lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/EOKPQGV24RRBBI4TBZUDQMM4MEH7MXCY"
+ },
+ {
+ "type": "ADVISORY",
+ "url": "https://github.com/advisories/GHSA-jfh8-c2jp-5v3q"
+ },
+ {
+ "type": "WEB",
+ "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-714170.pdf"
+ },
+ {
+ "type": "WEB",
+ "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-661247.pdf"
+ },
+ {
+ "type": "WEB",
+ "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-479842.pdf"
+ },
+ {
+ "type": "WEB",
+ "url": "https://cert-portal.siemens.com/productcert/pdf/ssa-397453.pdf"
+ },
+ {
+ "type": "WEB",
+ "url": "http://www.openwall.com/lists/oss-security/2021/12/14/4"
+ },
+ {
+ "type": "WEB",
+ "url": "http://www.openwall.com/lists/oss-security/2021/12/15/3"
+ },
+ {
+ "type": "WEB",
+ "url": "http://www.openwall.com/lists/oss-security/2021/12/18/1"
+ }
+ ],
+ "affected": [
+ {
+ "package": {
+ "name": "org.apache.logging.log4j:log4j-core",
+ "ecosystem": "Maven",
+ "purl": "pkg:maven/org.apache.logging.log4j/log4j-core"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "2.13.0"
+ },
+ {
+ "fixed": "2.16.0"
+ }
+ ]
+ }
+ ],
+ "versions": [
+ "2.13.0",
+ "2.13.1",
+ "2.13.2",
+ "2.13.3",
+ "2.14.0",
+ "2.14.1",
+ "2.15.0"
+ ],
+ "database_specific": {
+ "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/12/GHSA-7rjr-3q55-vv33/GHSA-7rjr-3q55-vv33.json"
+ }
+ },
+ {
+ "package": {
+ "name": "org.apache.logging.log4j:log4j-core",
+ "ecosystem": "Maven",
+ "purl": "pkg:maven/org.apache.logging.log4j/log4j-core"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "0"
+ },
+ {
+ "fixed": "2.12.2"
+ }
+ ]
+ }
+ ],
+ "versions": [
+ "2.0",
+ "2.0-alpha1",
+ "2.0-alpha2",
+ "2.0-beta1",
+ "2.0-beta2",
+ "2.0-beta3",
+ "2.0-beta4",
+ "2.0-beta5",
+ "2.0-beta6",
+ "2.0-beta7",
+ "2.0-beta8",
+ "2.0-beta9",
+ "2.0-rc1",
+ "2.0-rc2",
+ "2.0.1",
+ "2.0.2",
+ "2.1",
+ "2.10.0",
+ "2.11.0",
+ "2.11.1",
+ "2.11.2",
+ "2.12.0",
+ "2.12.1",
+ "2.2",
+ "2.3",
+ "2.3.1",
+ "2.3.2",
+ "2.4",
+ "2.4.1",
+ "2.5",
+ "2.6",
+ "2.6.1",
+ "2.6.2",
+ "2.7",
+ "2.8",
+ "2.8.1",
+ "2.8.2",
+ "2.9.0",
+ "2.9.1"
+ ],
+ "database_specific": {
+ "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/12/GHSA-7rjr-3q55-vv33/GHSA-7rjr-3q55-vv33.json"
+ }
+ },
+ {
+ "package": {
+ "name": "org.ops4j.pax.logging:pax-logging-log4j2",
+ "ecosystem": "Maven",
+ "purl": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "1.8.0"
+ },
+ {
+ "fixed": "1.9.2"
+ }
+ ]
+ }
+ ],
+ "versions": [
+ "1.8.0",
+ "1.8.1",
+ "1.8.2",
+ "1.8.3",
+ "1.8.4",
+ "1.8.5",
+ "1.8.6",
+ "1.8.7",
+ "1.9.0",
+ "1.9.1"
+ ],
+ "database_specific": {
+ "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/12/GHSA-7rjr-3q55-vv33/GHSA-7rjr-3q55-vv33.json"
+ }
+ },
+ {
+ "package": {
+ "name": "org.ops4j.pax.logging:pax-logging-log4j2",
+ "ecosystem": "Maven",
+ "purl": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "1.10.0"
+ },
+ {
+ "fixed": "1.10.8"
+ }
+ ]
+ }
+ ],
+ "versions": [
+ "1.10.0",
+ "1.10.1",
+ "1.10.2",
+ "1.10.3",
+ "1.10.4",
+ "1.10.5",
+ "1.10.6",
+ "1.10.7"
+ ],
+ "database_specific": {
+ "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/12/GHSA-7rjr-3q55-vv33/GHSA-7rjr-3q55-vv33.json"
+ }
+ },
+ {
+ "package": {
+ "name": "org.ops4j.pax.logging:pax-logging-log4j2",
+ "ecosystem": "Maven",
+ "purl": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "1.11.0"
+ },
+ {
+ "fixed": "1.11.11"
+ }
+ ]
+ }
+ ],
+ "versions": [
+ "1.11.0",
+ "1.11.1",
+ "1.11.10",
+ "1.11.2",
+ "1.11.3",
+ "1.11.4",
+ "1.11.5",
+ "1.11.6",
+ "1.11.7",
+ "1.11.8",
+ "1.11.9"
+ ],
+ "database_specific": {
+ "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/12/GHSA-7rjr-3q55-vv33/GHSA-7rjr-3q55-vv33.json"
+ }
+ },
+ {
+ "package": {
+ "name": "org.ops4j.pax.logging:pax-logging-log4j2",
+ "ecosystem": "Maven",
+ "purl": "pkg:maven/org.ops4j.pax.logging/pax-logging-log4j2"
+ },
+ "ranges": [
+ {
+ "type": "ECOSYSTEM",
+ "events": [
+ {
+ "introduced": "2.0.0"
+ },
+ {
+ "fixed": "2.0.12"
+ }
+ ]
+ }
+ ],
+ "versions": [
+ "2.0.0",
+ "2.0.1",
+ "2.0.10",
+ "2.0.11",
+ "2.0.2",
+ "2.0.3",
+ "2.0.4",
+ "2.0.5",
+ "2.0.6",
+ "2.0.7",
+ "2.0.8",
+ "2.0.9"
+ ],
+ "database_specific": {
+ "source": "https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2021/12/GHSA-7rjr-3q55-vv33/GHSA-7rjr-3q55-vv33.json"
+ }
+ }
+ ],
+ "schema_version": "1.7.3",
+ "severity": [
+ {
+ "type": "CVSS_V3",
+ "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H"
+ }
+ ]
+ }
]
\ No newline at end of file
diff --git a/src/StellaOps.Feedser.Source.Osv.Tests/Osv/OsvMapperTests.cs b/src/StellaOps.Feedser.Source.Osv.Tests/Osv/OsvMapperTests.cs
index 40b2b91e..87df844e 100644
--- a/src/StellaOps.Feedser.Source.Osv.Tests/Osv/OsvMapperTests.cs
+++ b/src/StellaOps.Feedser.Source.Osv.Tests/Osv/OsvMapperTests.cs
@@ -1,25 +1,28 @@
-using System;
-using System.Collections.Generic;
-using System.Text.Json;
-using MongoDB.Bson;
-using StellaOps.Feedser.Models;
-using StellaOps.Feedser.Source.Common;
-using StellaOps.Feedser.Source.Osv;
-using StellaOps.Feedser.Source.Osv.Internal;
-using StellaOps.Feedser.Storage.Mongo.Documents;
-using StellaOps.Feedser.Storage.Mongo.Dtos;
-using Xunit;
+using System;
+using System.Collections.Generic;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+using System.Reflection;
+using MongoDB.Bson;
+using StellaOps.Feedser.Models;
+using StellaOps.Feedser.Source.Common;
+using StellaOps.Feedser.Source.Osv;
+using StellaOps.Feedser.Source.Osv.Internal;
+using StellaOps.Feedser.Normalization.Identifiers;
+using StellaOps.Feedser.Storage.Mongo.Documents;
+using StellaOps.Feedser.Storage.Mongo.Dtos;
+using Xunit;
namespace StellaOps.Feedser.Source.Osv.Tests;
public sealed class OsvMapperTests
{
[Fact]
- public void Map_NormalizesAliasesReferencesAndRanges()
- {
- var published = DateTimeOffset.UtcNow.AddDays(-2);
- var modified = DateTimeOffset.UtcNow.AddDays(-1);
-
+ public void Map_NormalizesAliasesReferencesAndRanges()
+ {
+ var published = DateTimeOffset.UtcNow.AddDays(-2);
+ var modified = DateTimeOffset.UtcNow.AddDays(-1);
+
using var databaseSpecificJson = JsonDocument.Parse("{}");
using var ecosystemSpecificJson = JsonDocument.Parse("{}");
@@ -117,7 +120,81 @@ public sealed class OsvMapperTests
Assert.Equal("1.0.1", semver.Fixed);
Assert.False(semver.FixedInclusive);
- Assert.Single(advisory.CvssMetrics);
- Assert.Equal("3.1", advisory.CvssMetrics[0].Version);
- }
-}
+ Assert.Single(advisory.CvssMetrics);
+ Assert.Equal("3.1", advisory.CvssMetrics[0].Version);
+ }
+
+ [Theory]
+ [InlineData("Go", "github.com/example/project", "pkg:golang/github.com/example/project")]
+ [InlineData("PyPI", "social_auth_app_django", "pkg:pypi/social-auth-app-django")]
+ [InlineData("npm", "@Scope/Package", "pkg:npm/%40scope/package")]
+ [InlineData("Maven", "org.example:library", "pkg:maven/org.example/library")]
+ [InlineData("crates", "serde", "pkg:cargo/serde")]
+ public void Map_InfersCanonicalPackageUrlWhenPurlMissing(string ecosystem, string packageName, string expectedIdentifier)
+ {
+ var dto = new OsvVulnerabilityDto
+ {
+ Id = $"OSV-{ecosystem}-PURL",
+ Summary = "Test advisory",
+ Details = "Details",
+ Published = DateTimeOffset.UtcNow.AddDays(-1),
+ Modified = DateTimeOffset.UtcNow,
+ Affected = new[]
+ {
+ new OsvAffectedPackageDto
+ {
+ Package = new OsvPackageDto
+ {
+ Ecosystem = ecosystem,
+ Name = packageName,
+ Purl = null,
+ },
+ Ranges = null,
+ }
+ }
+ };
+
+ if (string.Equals(ecosystem, "npm", StringComparison.OrdinalIgnoreCase))
+ {
+ Assert.True(IdentifierNormalizer.TryNormalizePackageUrl("pkg:npm/%40scope/package", out var canonical));
+ Assert.Equal(expectedIdentifier, canonical);
+ }
+
+ var method = typeof(OsvMapper).GetMethod("DetermineIdentifier", BindingFlags.NonPublic | BindingFlags.Static);
+ Assert.NotNull(method);
+ var directIdentifier = method!.Invoke(null, new object?[] { dto.Affected![0].Package!, ecosystem }) as string;
+ Assert.Equal(expectedIdentifier, directIdentifier);
+
+ var (document, dtoRecord) = CreateDocumentAndDtoRecord(dto, ecosystem);
+ var advisory = OsvMapper.Map(dto, document, dtoRecord, ecosystem);
+
+ var affected = Assert.Single(advisory.AffectedPackages);
+ Assert.Equal(expectedIdentifier, affected.Identifier);
+ }
+
+ private static (DocumentRecord Document, DtoRecord DtoRecord) CreateDocumentAndDtoRecord(OsvVulnerabilityDto dto, string ecosystem)
+ {
+ var recordedAt = DateTimeOffset.UtcNow;
+ var document = new DocumentRecord(
+ Guid.NewGuid(),
+ OsvConnectorPlugin.SourceName,
+ $"https://osv.dev/vulnerability/{dto.Id}",
+ recordedAt,
+ "sha256",
+ DocumentStatuses.PendingParse,
+ "application/json",
+ null,
+ new Dictionary(StringComparer.Ordinal)
+ {
+ ["osv.ecosystem"] = ecosystem,
+ },
+ null,
+ dto.Modified,
+ null,
+ null);
+
+ var payload = new BsonDocument("id", dto.Id);
+ var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, OsvConnectorPlugin.SourceName, "osv.v1", payload, recordedAt);
+ return (document, dtoRecord);
+ }
+}
diff --git a/src/StellaOps.Feedser.Source.Osv/Internal/OsvMapper.cs b/src/StellaOps.Feedser.Source.Osv/Internal/OsvMapper.cs
index 8272ecf9..8d09dcc0 100644
--- a/src/StellaOps.Feedser.Source.Osv/Internal/OsvMapper.cs
+++ b/src/StellaOps.Feedser.Source.Osv/Internal/OsvMapper.cs
@@ -12,9 +12,29 @@ using StellaOps.Feedser.Storage.Mongo.Dtos;
namespace StellaOps.Feedser.Source.Osv.Internal;
-internal static class OsvMapper
-{
- private static readonly string[] SeverityOrder = { "none", "low", "medium", "high", "critical" };
+internal static class OsvMapper
+{
+ private static readonly string[] SeverityOrder = { "none", "low", "medium", "high", "critical" };
+
+ private static readonly IReadOnlyDictionary> PackageUrlBuilders =
+ new Dictionary>(StringComparer.OrdinalIgnoreCase)
+ {
+ ["pypi"] = static name => $"pkg:pypi/{NormalizePyPiName(name)}",
+ ["python"] = static name => $"pkg:pypi/{NormalizePyPiName(name)}",
+ ["maven"] = static name => $"pkg:maven/{NormalizeMavenName(name)}",
+ ["go"] = static name => $"pkg:golang/{NormalizeGoName(name)}",
+ ["golang"] = static name => $"pkg:golang/{NormalizeGoName(name)}",
+ ["crates"] = static name => $"pkg:cargo/{NormalizeCratesName(name)}",
+ ["crates.io"] = static name => $"pkg:cargo/{NormalizeCratesName(name)}",
+ ["cargo"] = static name => $"pkg:cargo/{NormalizeCratesName(name)}",
+ ["nuget"] = static name => $"pkg:nuget/{NormalizeNugetName(name)}",
+ ["rubygems"] = static name => $"pkg:gem/{NormalizeRubyName(name)}",
+ ["gem"] = static name => $"pkg:gem/{NormalizeRubyName(name)}",
+ ["packagist"] = static name => $"pkg:composer/{NormalizeComposerName(name)}",
+ ["composer"] = static name => $"pkg:composer/{NormalizeComposerName(name)}",
+ ["hex"] = static name => $"pkg:hex/{NormalizeHexName(name)}",
+ ["hex.pm"] = static name => $"pkg:hex/{NormalizeHexName(name)}",
+ };
public static Advisory Map(
OsvVulnerabilityDto dto,
@@ -416,24 +436,35 @@ internal static class OsvMapper
return new RangePrimitives(semver, null, null, null);
}
- private static string? DetermineIdentifier(OsvPackageDto package, string ecosystem)
- {
- if (!string.IsNullOrWhiteSpace(package.Purl)
- && IdentifierNormalizer.TryNormalizePackageUrl(package.Purl, out var normalized))
- {
- return normalized;
- }
-
- if (!string.IsNullOrWhiteSpace(package.Name))
- {
- var name = package.Name.Trim();
- return string.IsNullOrWhiteSpace(package.Ecosystem)
- ? $"{ecosystem}:{name}"
- : $"{package.Ecosystem.Trim()}:{name}";
- }
-
- return null;
- }
+ private static string? DetermineIdentifier(OsvPackageDto package, string ecosystem)
+ {
+ if (IdentifierNormalizer.TryNormalizePackageUrl(package.Purl, out var normalized))
+ {
+ return normalized;
+ }
+
+ var name = Validation.TrimToNull(package.Name);
+ if (name is null)
+ {
+ return null;
+ }
+
+ var ecosystemHint = Validation.TrimToNull(package.Ecosystem) ?? Validation.TrimToNull(ecosystem);
+ if (ecosystemHint is not null
+ && string.Equals(ecosystemHint, "npm", StringComparison.OrdinalIgnoreCase)
+ && TryBuildNpmPackageUrl(name, out normalized))
+ {
+ return normalized;
+ }
+
+ if (TryBuildCanonicalPackageUrl(ecosystemHint, name, out normalized))
+ {
+ return normalized;
+ }
+
+ var fallbackEcosystem = ecosystemHint ?? Validation.TrimToNull(ecosystem) ?? "osv";
+ return $"{fallbackEcosystem}:{name}";
+ }
private static IReadOnlyList BuildCvssMetrics(OsvVulnerabilityDto dto, DateTimeOffset recordedAt, out string? severity)
{
@@ -520,11 +551,11 @@ internal static class OsvMapper
return left.Provenance.RecordedAt.CompareTo(right.Provenance.RecordedAt);
}
- private static int CompareNullable(string? left, string? right)
- {
- if (left is null && right is null)
- {
- return 0;
+ private static int CompareNullable(string? left, string? right)
+ {
+ if (left is null && right is null)
+ {
+ return 0;
}
if (left is null)
@@ -536,7 +567,80 @@ internal static class OsvMapper
{
return -1;
}
-
- return StringComparer.Ordinal.Compare(left, right);
- }
-}
+
+ return StringComparer.Ordinal.Compare(left, right);
+ }
+
+ private static bool TryBuildCanonicalPackageUrl(string? ecosystem, string name, out string? canonical)
+ {
+ canonical = null;
+ var trimmedEcosystem = Validation.TrimToNull(ecosystem);
+ if (trimmedEcosystem is null)
+ {
+ return false;
+ }
+
+ if (!PackageUrlBuilders.TryGetValue(trimmedEcosystem, out var factory))
+ {
+ return false;
+ }
+
+ var candidate = factory(name.Trim());
+ return IdentifierNormalizer.TryNormalizePackageUrl(candidate, out canonical);
+ }
+
+ private static string NormalizePyPiName(string name) => name.Trim().Replace('_', '-');
+
+ private static bool TryBuildNpmPackageUrl(string name, out string? canonical)
+ {
+ canonical = null;
+ var trimmed = name.Trim();
+ if (trimmed.Length == 0)
+ {
+ return false;
+ }
+
+ if (trimmed[0] == '@')
+ {
+ var slashIndex = trimmed.IndexOf('/', 1);
+ if (slashIndex <= 1 || slashIndex >= trimmed.Length - 1)
+ {
+ return false;
+ }
+
+ var scope = trimmed[..slashIndex].ToLowerInvariant();
+ var package = trimmed[(slashIndex + 1)..].ToLowerInvariant();
+ var candidate = $"pkg:npm/{Uri.EscapeDataString(scope)}/{Uri.EscapeDataString(package)}";
+ return IdentifierNormalizer.TryNormalizePackageUrl(candidate, out canonical);
+ }
+
+ if (trimmed.Contains('/', StringComparison.Ordinal))
+ {
+ return false;
+ }
+
+ var normalized = trimmed.ToLowerInvariant();
+ var simpleCandidate = $"pkg:npm/{Uri.EscapeDataString(normalized)}";
+ return IdentifierNormalizer.TryNormalizePackageUrl(simpleCandidate, out canonical);
+ }
+
+ private static string NormalizeMavenName(string name)
+ {
+ var trimmed = name.Trim();
+ return trimmed.Contains(':', StringComparison.Ordinal)
+ ? trimmed.Replace(':', '/')
+ : trimmed.Replace('\\', '/');
+ }
+
+ private static string NormalizeGoName(string name) => name.Trim();
+
+ private static string NormalizeCratesName(string name) => name.Trim();
+
+ private static string NormalizeNugetName(string name) => name.Trim();
+
+ private static string NormalizeRubyName(string name) => name.Trim();
+
+ private static string NormalizeComposerName(string name) => name.Trim();
+
+ private static string NormalizeHexName(string name) => name.Trim();
+}
diff --git a/src/StellaOps.Feedser.Source.Osv/TASKS.md b/src/StellaOps.Feedser.Source.Osv/TASKS.md
index 7420cc13..aac3da8d 100644
--- a/src/StellaOps.Feedser.Source.Osv/TASKS.md
+++ b/src/StellaOps.Feedser.Source.Osv/TASKS.md
@@ -12,7 +12,7 @@
|Connector DI routine & job registration|BE-Conn-OSV|Core|**DONE** – DI routine registers fetch/parse/map jobs with scheduler.|
|Implement OSV fetch/parse/map skeleton|BE-Conn-OSV|Source.Common|**DONE** – connector now persists documents, DTOs, and canonical advisories.|
|FEEDCONN-OSV-02-004 OSV references & credits alignment|BE-Conn-OSV|Models `FEEDMODELS-SCHEMA-01-002`|**DONE (2025-10-11)** – Mapper normalizes references with provenance masks, emits advisory credits, and regression fixtures/assertions cover the new fields.|
-|FEEDCONN-OSV-02-005 Fixture updater workflow|BE-Conn-OSV, QA|Docs|TODO – Document `tools/FixtureUpdater`, add parity regression steps, and ensure future refreshes capture credit metadata consistently.|
+|FEEDCONN-OSV-02-005 Fixture updater workflow|BE-Conn-OSV, QA|Docs|**DONE (2025-10-12)** – Canonical PURL derivation now covers Go + scoped npm advisories without upstream `purl`; legacy invalid npm names still fall back to `ecosystem:name`. OSV/GHSA/NVD suites and normalization/storage tests rerun clean.|
|FEEDCONN-OSV-02-003 Normalized versions rollout|BE-Conn-OSV|Models `FEEDMODELS-SCHEMA-01-003`, Normalization playbook|**DONE (2025-10-11)** – `OsvMapper` now emits SemVer primitives + normalized rules with `osv:{ecosystem}:{advisoryId}:{identifier}` notes; npm/PyPI/Parity fixtures refreshed; merge coordination pinged (OSV handoff).|
|FEEDCONN-OSV-04-003 Parity fixture refresh|QA, BE-Conn-OSV|Normalized versions rollout, GHSA parity tests|**DONE (2025-10-12)** – Parity fixtures include normalizedVersions notes (`osv:::`); regression math rerun via `dotnet test src/StellaOps.Feedser.Source.Osv.Tests` and docs flagged for workflow sync.|
|FEEDCONN-OSV-04-002 Conflict regression fixtures|BE-Conn-OSV, QA|Merge `FEEDMERGE-ENGINE-04-001`|**DONE (2025-10-12)** – Added `conflict-osv.canonical.json` + regression asserting SemVer range + CVSS medium severity; dataset matches GHSA/NVD fixtures for merge tests. Validation: `dotnet test src/StellaOps.Feedser.Source.Osv.Tests/StellaOps.Feedser.Source.Osv.Tests.csproj --filter OsvConflictFixtureTests`.|
diff --git a/src/StellaOps.Feedser.Storage.Mongo.Tests/AdvisoryStorePerformanceTests.cs b/src/StellaOps.Feedser.Storage.Mongo.Tests/AdvisoryStorePerformanceTests.cs
index f6a7d744..07d79762 100644
--- a/src/StellaOps.Feedser.Storage.Mongo.Tests/AdvisoryStorePerformanceTests.cs
+++ b/src/StellaOps.Feedser.Storage.Mongo.Tests/AdvisoryStorePerformanceTests.cs
@@ -62,7 +62,12 @@ public sealed class AdvisoryStorePerformanceTests : IClassFixture.Instance);
- var store = new AdvisoryStore(database, aliasStore, NullLogger.Instance, TimeProvider.System);
+ var store = new AdvisoryStore(
+ database,
+ aliasStore,
+ NullLogger.Instance,
+ Options.Create(new MongoStorageOptions()),
+ TimeProvider.System);
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(45));
// Warm up collections (indexes, serialization caches) so perf timings exclude one-time setup work.
diff --git a/src/StellaOps.Feedser.Storage.Mongo.Tests/AdvisoryStoreTests.cs b/src/StellaOps.Feedser.Storage.Mongo.Tests/AdvisoryStoreTests.cs
index 68a45fa6..e5df0be3 100644
--- a/src/StellaOps.Feedser.Storage.Mongo.Tests/AdvisoryStoreTests.cs
+++ b/src/StellaOps.Feedser.Storage.Mongo.Tests/AdvisoryStoreTests.cs
@@ -1,9 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Microsoft.Extensions.Logging.Abstractions;
-using MongoDB.Driver;
-using StellaOps.Feedser.Models;
+using Microsoft.Extensions.Logging.Abstractions;
+using Microsoft.Extensions.Options;
+using MongoDB.Driver;
+using StellaOps.Feedser.Models;
using StellaOps.Feedser.Storage.Mongo.Advisories;
using StellaOps.Feedser.Storage.Mongo.Aliases;
@@ -25,8 +26,13 @@ public sealed class AdvisoryStoreTests : IClassFixture
await DropCollectionAsync(MongoStorageDefaults.Collections.Advisory);
await DropCollectionAsync(MongoStorageDefaults.Collections.Alias);
- var aliasStore = new AliasStore(_fixture.Database, NullLogger.Instance);
- var store = new AdvisoryStore(_fixture.Database, aliasStore, NullLogger.Instance, TimeProvider.System);
+ var aliasStore = new AliasStore(_fixture.Database, NullLogger.Instance);
+ var store = new AdvisoryStore(
+ _fixture.Database,
+ aliasStore,
+ NullLogger.Instance,
+ Options.Create(new MongoStorageOptions()),
+ TimeProvider.System);
var advisory = new Advisory(
advisoryKey: "ADV-1",
title: "Sample Advisory",
@@ -62,8 +68,13 @@ public sealed class AdvisoryStoreTests : IClassFixture
await DropCollectionAsync(MongoStorageDefaults.Collections.Advisory);
await DropCollectionAsync(MongoStorageDefaults.Collections.Alias);
- var aliasStore = new AliasStore(_fixture.Database, NullLogger.Instance);
- var store = new AdvisoryStore(_fixture.Database, aliasStore, NullLogger.Instance, TimeProvider.System);
+ var aliasStore = new AliasStore(_fixture.Database, NullLogger.Instance);
+ var store = new AdvisoryStore(
+ _fixture.Database,
+ aliasStore,
+ NullLogger.Instance,
+ Options.Create(new MongoStorageOptions()),
+ TimeProvider.System);
var recordedAt = new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero);
var provenance = new AdvisoryProvenance("source-x", "mapper", "payload-123", recordedAt);
@@ -144,15 +155,147 @@ public sealed class AdvisoryStoreTests : IClassFixture
Assert.NotNull(fetchedRange.Primitives);
Assert.Equal(rangePrimitives.SemVer, fetchedRange.Primitives!.SemVer);
Assert.Equal(rangePrimitives.Nevra, fetchedRange.Primitives.Nevra);
- Assert.Equal(rangePrimitives.Evr, fetchedRange.Primitives.Evr);
- Assert.Equal(rangePrimitives.VendorExtensions, fetchedRange.Primitives.VendorExtensions);
- }
-
- private async Task DropCollectionAsync(string collectionName)
- {
- try
- {
- await _fixture.Database.DropCollectionAsync(collectionName);
+ Assert.Equal(rangePrimitives.Evr, fetchedRange.Primitives.Evr);
+ Assert.Equal(rangePrimitives.VendorExtensions, fetchedRange.Primitives.VendorExtensions);
+ }
+
+ [Fact]
+ public async Task UpsertAsync_SkipsNormalizedVersionsWhenFeatureDisabled()
+ {
+ await DropCollectionAsync(MongoStorageDefaults.Collections.Advisory);
+ await DropCollectionAsync(MongoStorageDefaults.Collections.Alias);
+
+ var aliasStore = new AliasStore(_fixture.Database, NullLogger.Instance);
+ var store = new AdvisoryStore(
+ _fixture.Database,
+ aliasStore,
+ NullLogger.Instance,
+ Options.Create(new MongoStorageOptions { EnableSemVerStyle = false }),
+ TimeProvider.System);
+
+ var advisory = CreateNormalizedAdvisory("ADV-NORM-DISABLED");
+ await store.UpsertAsync(advisory, CancellationToken.None);
+
+ var document = await _fixture.Database
+ .GetCollection(MongoStorageDefaults.Collections.Advisory)
+ .Find(x => x.AdvisoryKey == advisory.AdvisoryKey)
+ .FirstOrDefaultAsync();
+
+ Assert.NotNull(document);
+ Assert.True(document!.NormalizedVersions is null || document.NormalizedVersions.Count == 0);
+ }
+
+ [Fact]
+ public async Task UpsertAsync_PopulatesNormalizedVersionsWhenFeatureEnabled()
+ {
+ await DropCollectionAsync(MongoStorageDefaults.Collections.Advisory);
+ await DropCollectionAsync(MongoStorageDefaults.Collections.Alias);
+
+ var aliasStore = new AliasStore(_fixture.Database, NullLogger.Instance);
+ var store = new AdvisoryStore(
+ _fixture.Database,
+ aliasStore,
+ NullLogger.Instance,
+ Options.Create(new MongoStorageOptions { EnableSemVerStyle = true }),
+ TimeProvider.System);
+
+ var advisory = CreateNormalizedAdvisory("ADV-NORM-ENABLED");
+ await store.UpsertAsync(advisory, CancellationToken.None);
+
+ var document = await _fixture.Database
+ .GetCollection(MongoStorageDefaults.Collections.Advisory)
+ .Find(x => x.AdvisoryKey == advisory.AdvisoryKey)
+ .FirstOrDefaultAsync();
+
+ Assert.NotNull(document);
+ var normalizedCollection = document!.NormalizedVersions;
+ Assert.NotNull(normalizedCollection);
+ var normalized = Assert.Single(normalizedCollection!);
+ Assert.Equal("pkg:npm/example", normalized.PackageId);
+ Assert.Equal(AffectedPackageTypes.SemVer, normalized.PackageType);
+ Assert.Equal(NormalizedVersionSchemes.SemVer, normalized.Scheme);
+ Assert.Equal(NormalizedVersionRuleTypes.Range, normalized.Type);
+ Assert.Equal("range", normalized.Style);
+ Assert.Equal("1.0.0", normalized.Min);
+ Assert.True(normalized.MinInclusive);
+ Assert.Equal("2.0.0", normalized.Max);
+ Assert.False(normalized.MaxInclusive);
+ Assert.Null(normalized.Value);
+ Assert.Equal("ghsa:pkg:npm/example", normalized.Notes);
+ Assert.Equal("range-decision", normalized.DecisionReason);
+ Assert.Equal(">= 1.0.0 < 2.0.0", normalized.Constraint);
+ Assert.Equal("ghsa", normalized.Source);
+ Assert.Equal(new DateTime(2025, 10, 9, 0, 0, 0, DateTimeKind.Utc), normalized.RecordedAtUtc);
+ }
+
+ private static Advisory CreateNormalizedAdvisory(string advisoryKey)
+ {
+ var recordedAt = new DateTimeOffset(2025, 10, 9, 0, 0, 0, TimeSpan.Zero);
+ var rangeProvenance = new AdvisoryProvenance(
+ source: "ghsa",
+ kind: "affected-range",
+ value: "pkg:npm/example",
+ recordedAt: recordedAt,
+ fieldMask: new[] { "affectedpackages[].versionranges[]" },
+ decisionReason: "range-decision");
+
+ var semverPrimitive = new SemVerPrimitive(
+ Introduced: "1.0.0",
+ IntroducedInclusive: true,
+ Fixed: "2.0.0",
+ FixedInclusive: false,
+ LastAffected: null,
+ LastAffectedInclusive: false,
+ ConstraintExpression: ">= 1.0.0 < 2.0.0");
+
+ var normalizedRule = semverPrimitive.ToNormalizedVersionRule("ghsa:pkg:npm/example")!;
+ var versionRange = new AffectedVersionRange(
+ rangeKind: "semver",
+ introducedVersion: "1.0.0",
+ fixedVersion: "2.0.0",
+ lastAffectedVersion: null,
+ rangeExpression: ">= 1.0.0 < 2.0.0",
+ provenance: rangeProvenance,
+ primitives: new RangePrimitives(semverPrimitive, null, null, null));
+
+ var package = new AffectedPackage(
+ type: AffectedPackageTypes.SemVer,
+ identifier: "pkg:npm/example",
+ platform: "npm",
+ versionRanges: new[] { versionRange },
+ statuses: Array.Empty(),
+ provenance: new[] { rangeProvenance },
+ normalizedVersions: new[] { normalizedRule });
+
+ var advisoryProvenance = new AdvisoryProvenance(
+ source: "ghsa",
+ kind: "document",
+ value: advisoryKey,
+ recordedAt: recordedAt,
+ fieldMask: new[] { "advisory" },
+ decisionReason: "document-decision");
+
+ return new Advisory(
+ advisoryKey: advisoryKey,
+ title: "Normalized advisory",
+ summary: "Contains normalized versions for storage testing.",
+ language: "en",
+ published: recordedAt,
+ modified: recordedAt,
+ severity: "medium",
+ exploitKnown: false,
+ aliases: new[] { $"{advisoryKey}-ALIAS" },
+ references: Array.Empty(),
+ affectedPackages: new[] { package },
+ cvssMetrics: Array.Empty(),
+ provenance: new[] { advisoryProvenance });
+ }
+
+ private async Task DropCollectionAsync(string collectionName)
+ {
+ try
+ {
+ await _fixture.Database.DropCollectionAsync(collectionName);
}
catch (MongoDB.Driver.MongoCommandException ex) when (ex.CodeName == "NamespaceNotFound" || ex.Message.Contains("ns not found", StringComparison.OrdinalIgnoreCase))
{
diff --git a/src/StellaOps.Feedser.Storage.Mongo.Tests/MongoBootstrapperTests.cs b/src/StellaOps.Feedser.Storage.Mongo.Tests/MongoBootstrapperTests.cs
new file mode 100644
index 00000000..80b5fefd
--- /dev/null
+++ b/src/StellaOps.Feedser.Storage.Mongo.Tests/MongoBootstrapperTests.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Linq;
+using System.Threading;
+using Microsoft.Extensions.Logging.Abstractions;
+using Microsoft.Extensions.Options;
+using MongoDB.Bson;
+using MongoDB.Driver;
+using StellaOps.Feedser.Storage.Mongo;
+using StellaOps.Feedser.Storage.Mongo.Migrations;
+using Xunit;
+
+namespace StellaOps.Feedser.Storage.Mongo.Tests;
+
+[Collection("mongo-fixture")]
+public sealed class MongoBootstrapperTests : IClassFixture
+{
+ private readonly MongoIntegrationFixture _fixture;
+
+ public MongoBootstrapperTests(MongoIntegrationFixture fixture)
+ {
+ _fixture = fixture;
+ }
+
+ [Fact]
+ public async Task InitializeAsync_CreatesNormalizedIndexesWhenSemVerStyleEnabled()
+ {
+ var databaseName = $"feedser-bootstrap-semver-{Guid.NewGuid():N}";
+ var database = _fixture.Client.GetDatabase(databaseName);
+
+ try
+ {
+ var runner = new MongoMigrationRunner(
+ database,
+ Array.Empty(),
+ NullLogger.Instance,
+ TimeProvider.System);
+
+ var bootstrapper = new MongoBootstrapper(
+ database,
+ Options.Create(new MongoStorageOptions { EnableSemVerStyle = true }),
+ NullLogger.Instance,
+ runner);
+
+ await bootstrapper.InitializeAsync(CancellationToken.None);
+
+ var indexCursor = await database
+ .GetCollection(MongoStorageDefaults.Collections.Advisory)
+ .Indexes
+ .ListAsync();
+ var indexNames = (await indexCursor.ToListAsync()).Select(x => x["name"].AsString).ToArray();
+
+ Assert.Contains("advisory_normalizedVersions_pkg_scheme_type", indexNames);
+ Assert.Contains("advisory_normalizedVersions_value", indexNames);
+ }
+ finally
+ {
+ await _fixture.Client.DropDatabaseAsync(databaseName);
+ }
+ }
+
+ [Fact]
+ public async Task InitializeAsync_DoesNotCreateNormalizedIndexesWhenFeatureDisabled()
+ {
+ var databaseName = $"feedser-bootstrap-no-semver-{Guid.NewGuid():N}";
+ var database = _fixture.Client.GetDatabase(databaseName);
+
+ try
+ {
+ var runner = new MongoMigrationRunner(
+ database,
+ Array.Empty(),
+ NullLogger.Instance,
+ TimeProvider.System);
+
+ var bootstrapper = new MongoBootstrapper(
+ database,
+ Options.Create(new MongoStorageOptions { EnableSemVerStyle = false }),
+ NullLogger.Instance,
+ runner);
+
+ await bootstrapper.InitializeAsync(CancellationToken.None);
+
+ var indexCursor = await database
+ .GetCollection(MongoStorageDefaults.Collections.Advisory)
+ .Indexes
+ .ListAsync();
+ var indexNames = (await indexCursor.ToListAsync()).Select(x => x["name"].AsString).ToArray();
+
+ Assert.DoesNotContain("advisory_normalizedVersions_pkg_scheme_type", indexNames);
+ Assert.DoesNotContain("advisory_normalizedVersions_value", indexNames);
+ }
+ finally
+ {
+ await _fixture.Client.DropDatabaseAsync(databaseName);
+ }
+ }
+}
diff --git a/src/StellaOps.Feedser.Storage.Mongo/Advisories/AdvisoryStore.cs b/src/StellaOps.Feedser.Storage.Mongo/Advisories/AdvisoryStore.cs
index fe685339..1275ab40 100644
--- a/src/StellaOps.Feedser.Storage.Mongo/Advisories/AdvisoryStore.cs
+++ b/src/StellaOps.Feedser.Storage.Mongo/Advisories/AdvisoryStore.cs
@@ -4,33 +4,37 @@ using System.Linq;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.Json.Serialization;
-using Microsoft.Extensions.Logging;
-using MongoDB.Bson;
-using MongoDB.Driver;
-using StellaOps.Feedser.Models;
-using StellaOps.Feedser.Storage.Mongo.Aliases;
-
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Options;
+using MongoDB.Bson;
+using MongoDB.Driver;
+using StellaOps.Feedser.Models;
+using StellaOps.Feedser.Storage.Mongo.Aliases;
+
namespace StellaOps.Feedser.Storage.Mongo.Advisories;
public sealed class AdvisoryStore : IAdvisoryStore
{
- private readonly IMongoCollection _collection;
- private readonly ILogger _logger;
- private readonly IAliasStore _aliasStore;
- private readonly TimeProvider _timeProvider;
-
- public AdvisoryStore(
- IMongoDatabase database,
- IAliasStore aliasStore,
- ILogger logger,
- TimeProvider? timeProvider = null)
- {
- _collection = (database ?? throw new ArgumentNullException(nameof(database)))
- .GetCollection(MongoStorageDefaults.Collections.Advisory);
- _aliasStore = aliasStore ?? throw new ArgumentNullException(nameof(aliasStore));
- _logger = logger ?? throw new ArgumentNullException(nameof(logger));
- _timeProvider = timeProvider ?? TimeProvider.System;
- }
+ private readonly IMongoCollection _collection;
+ private readonly ILogger _logger;
+ private readonly IAliasStore _aliasStore;
+ private readonly TimeProvider _timeProvider;
+ private readonly MongoStorageOptions _options;
+
+ public AdvisoryStore(
+ IMongoDatabase database,
+ IAliasStore aliasStore,
+ ILogger logger,
+ IOptions options,
+ TimeProvider? timeProvider = null)
+ {
+ _collection = (database ?? throw new ArgumentNullException(nameof(database)))
+ .GetCollection(MongoStorageDefaults.Collections.Advisory);
+ _aliasStore = aliasStore ?? throw new ArgumentNullException(nameof(aliasStore));
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
+ _options = options?.Value ?? throw new ArgumentNullException(nameof(options));
+ _timeProvider = timeProvider ?? TimeProvider.System;
+ }
public async Task UpsertAsync(Advisory advisory, CancellationToken cancellationToken)
@@ -51,7 +55,9 @@ public sealed class AdvisoryStore : IAdvisoryStore
}
var payload = CanonicalJsonSerializer.Serialize(advisory);
- var normalizedVersions = NormalizedVersionDocumentFactory.Create(advisory);
+ var normalizedVersions = _options.EnableSemVerStyle
+ ? NormalizedVersionDocumentFactory.Create(advisory)
+ : null;
var document = new AdvisoryDocument
{
AdvisoryKey = advisory.AdvisoryKey,
diff --git a/src/StellaOps.Feedser.Storage.Mongo/Advisories/NormalizedVersionDocumentFactory.cs b/src/StellaOps.Feedser.Storage.Mongo/Advisories/NormalizedVersionDocumentFactory.cs
index 12cd060e..bf9238a2 100644
--- a/src/StellaOps.Feedser.Storage.Mongo/Advisories/NormalizedVersionDocumentFactory.cs
+++ b/src/StellaOps.Feedser.Storage.Mongo/Advisories/NormalizedVersionDocumentFactory.cs
@@ -41,10 +41,10 @@ internal static class NormalizedVersionDocumentFactory
?? package.Provenance.FirstOrDefault()?.RecordedAt
?? advisoryFallbackRecordedAt;
- var constraint = matchingRange?.RangeExpression
- ?? matchingRange?.Primitives?.SemVer?.ConstraintExpression;
+ var constraint = matchingRange?.Primitives?.SemVer?.ConstraintExpression
+ ?? matchingRange?.RangeExpression;
- var style = rule.Type;
+ var style = matchingRange?.Primitives?.SemVer?.Style ?? rule.Type;
documents.Add(new NormalizedVersionDocument
{
diff --git a/src/StellaOps.Feedser.Storage.Mongo/MongoBootstrapper.cs b/src/StellaOps.Feedser.Storage.Mongo/MongoBootstrapper.cs
index 48c04d85..04006964 100644
--- a/src/StellaOps.Feedser.Storage.Mongo/MongoBootstrapper.cs
+++ b/src/StellaOps.Feedser.Storage.Mongo/MongoBootstrapper.cs
@@ -125,21 +125,35 @@ public sealed class MongoBootstrapper
private Task EnsureAdvisoryIndexesAsync(CancellationToken cancellationToken)
{
var collection = _database.GetCollection(MongoStorageDefaults.Collections.Advisory);
- var indexes = new List>
- {
- new(
- Builders.IndexKeys.Ascending("advisoryKey"),
- new CreateIndexOptions { Name = "advisory_key_unique", Unique = true }),
- new(
- Builders.IndexKeys.Descending("modified"),
- new CreateIndexOptions { Name = "advisory_modified_desc" }),
- new(
- Builders.IndexKeys.Descending("published"),
- new CreateIndexOptions { Name = "advisory_published_desc" }),
- };
-
- return collection.Indexes.CreateManyAsync(indexes, cancellationToken);
- }
+ var indexes = new List>
+ {
+ new(
+ Builders.IndexKeys.Ascending("advisoryKey"),
+ new CreateIndexOptions { Name = "advisory_key_unique", Unique = true }),
+ new(
+ Builders.IndexKeys.Descending("modified"),
+ new CreateIndexOptions { Name = "advisory_modified_desc" }),
+ new(
+ Builders.IndexKeys.Descending("published"),
+ new CreateIndexOptions { Name = "advisory_published_desc" }),
+ };
+
+ if (_options.EnableSemVerStyle)
+ {
+ indexes.Add(new CreateIndexModel(
+ Builders.IndexKeys
+ .Ascending("normalizedVersions.packageId")
+ .Ascending("normalizedVersions.scheme")
+ .Ascending("normalizedVersions.type"),
+ new CreateIndexOptions { Name = "advisory_normalizedVersions_pkg_scheme_type" }));
+
+ indexes.Add(new CreateIndexModel(
+ Builders.IndexKeys.Ascending("normalizedVersions.value"),
+ new CreateIndexOptions { Name = "advisory_normalizedVersions_value", Sparse = true }));
+ }
+
+ return collection.Indexes.CreateManyAsync(indexes, cancellationToken);
+ }
private Task EnsureDocumentsIndexesAsync(CancellationToken cancellationToken)
{
diff --git a/src/StellaOps.Feedser.Storage.Mongo/ServiceCollectionExtensions.cs b/src/StellaOps.Feedser.Storage.Mongo/ServiceCollectionExtensions.cs
index 27f28c74..a28b22e7 100644
--- a/src/StellaOps.Feedser.Storage.Mongo/ServiceCollectionExtensions.cs
+++ b/src/StellaOps.Feedser.Storage.Mongo/ServiceCollectionExtensions.cs
@@ -81,10 +81,11 @@ public static class ServiceCollectionExtensions
services.AddHostedService();
- services.AddSingleton();
- services.AddSingleton();
- services.AddSingleton();
-
- return services;
- }
-}
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
+
+ return services;
+ }
+}
diff --git a/src/StellaOps.Feedser.Storage.Mongo/TASKS.md b/src/StellaOps.Feedser.Storage.Mongo/TASKS.md
index 5bfa9333..5051b49e 100644
--- a/src/StellaOps.Feedser.Storage.Mongo/TASKS.md
+++ b/src/StellaOps.Feedser.Storage.Mongo/TASKS.md
@@ -11,9 +11,11 @@
|ExportState store|BE-Export|Exporters|DONE – ExportStateStore upserts and retrieves exporter metadata.|
|Performance tests for large advisories|QA|Storage.Mongo|DONE – `AdvisoryStorePerformanceTests` exercises large payload upsert/find throughput budgets.|
|Migration playbook for schema/index changes|BE-Storage|Storage.Mongo|DONE – `MongoMigrationRunner` executes `IMongoMigration` steps recorded in `schema_migrations`; see `MIGRATIONS.md`.|
-|Raw document retention/TTL strategy|BE-Storage|Storage.Mongo|DONE – retention options flow into `RawDocumentRetentionService` and TTL migrations for `document`/GridFS indexes.|
-|Persist last failure reason in SourceState|BE-Storage|Storage.Mongo|DONE – `MongoSourceStateRepository.MarkFailureAsync` stores `lastFailureReason` with length guard + reset on success.|
+|Raw document retention/TTL strategy|BE-Storage|Storage.Mongo|DONE – retention options flow into `RawDocumentRetentionService` and TTL migrations for `document`/GridFS indexes.|
+|Persist last failure reason in SourceState|BE-Storage|Storage.Mongo|DONE – `MongoSourceStateRepository.MarkFailureAsync` stores `lastFailureReason` with length guard + reset on success.|
|AdvisoryStore range primitives deserialization|BE-Storage|Models|DONE – BSON helpers handle `RangePrimitives`; regression test covers SemVer/NEVRA/EVR envelopes persisted through Mongo.|
|FEEDSTORAGE-DATA-03-001 Merge event provenance audit prep|BE-Storage|Merge|DONE – merge events now persist field-level decision reasons via `MergeFieldDecision` documents for analytics. **Coordination:** log any new precedence signals to storage@ so indexes/serializers stay aligned.|
-|FEEDSTORAGE-DATA-02-001 Normalized range dual-write + backfill|BE-Storage|Core|DONE – advisory documents store `normalizedVersions`, migration respects `EnableSemVerStyle`, and decision reasons flow into normalized write path. **Action:** connector owners confirm `EnableSemVerStyle=true` readiness before 2025-10-18 rollout.|
+|FEEDSTORAGE-DATA-02-001 Normalized range dual-write + backfill|BE-Storage|Core|**DONE (2025-10-12)** – `AdvisoryStore` honors `EnableSemVerStyle`, dual-writes normalized docs, and SemVer backfill migration registered for staged rollout.|
|FEEDSTORAGE-TESTS-02-004 Restore AdvisoryStore build after normalized versions refactor|QA|Storage.Mongo|DONE – storage tests updated to cover normalized version payloads and new provenance fields. **Heads-up:** QA to watch for fixture bumps touching normalized rule arrays when connectors roll out support.|
+|FEEDSTORAGE-DATA-02-002 Provenance decision persistence|BE-Storage|Models `FEEDMODELS-SCHEMA-01-002`|**DONE (2025-10-12)** – Normalized documents carry decision reasons/source/timestamps with regression coverage verifying SemVer notes + provenance fallbacks.|
+|FEEDSTORAGE-DATA-02-003 Normalized versions index creation|BE-Storage|Normalization, Mongo bootstrapper|**DONE (2025-10-12)** – Bootstrapper seeds `normalizedVersions.*` indexes when SemVer style is enabled; docs/tests confirm index presence.|