Finish off old sprints
This commit is contained in:
@@ -280,7 +280,7 @@ public sealed class AstraConnector : IFeedConnector
|
||||
|
||||
// Create base provenance record
|
||||
var baseProvenance = new AdvisoryProvenance(
|
||||
source: AstraOptions.SourceName,
|
||||
source: AstraConnectorPlugin.SourceName,
|
||||
kind: "oval-definition",
|
||||
value: definition.DefinitionId,
|
||||
recordedAt: recordedAt,
|
||||
@@ -379,7 +379,7 @@ public sealed class AstraConnector : IFeedConnector
|
||||
/// <remarks>
|
||||
/// Temporary model until full OVAL schema mapping is implemented.
|
||||
/// </remarks>
|
||||
internal sealed record AstraVulnerabilityDefinition
|
||||
public sealed record AstraVulnerabilityDefinition
|
||||
{
|
||||
public required string DefinitionId { get; init; }
|
||||
public required string Title { get; init; }
|
||||
@@ -393,7 +393,7 @@ internal sealed record AstraVulnerabilityDefinition
|
||||
/// <summary>
|
||||
/// Represents an affected package from OVAL test/state elements.
|
||||
/// </summary>
|
||||
internal sealed record AstraAffectedPackage
|
||||
public sealed record AstraAffectedPackage
|
||||
{
|
||||
public required string PackageName { get; init; }
|
||||
public string? MinVersion { get; init; }
|
||||
|
||||
@@ -58,6 +58,13 @@ public sealed class OvalParser
|
||||
return Array.Empty<AstraVulnerabilityDefinition>();
|
||||
}
|
||||
|
||||
// Validate this is an OVAL document by checking root element namespace
|
||||
if (root.Name.Namespace != OvalDefsNs)
|
||||
{
|
||||
throw new OvalParseException(
|
||||
$"Invalid OVAL document: expected root element in namespace '{OvalDefsNs}', got '{root.Name.Namespace}'");
|
||||
}
|
||||
|
||||
// Extract definitions, tests, objects, and states
|
||||
var definitions = ExtractDefinitions(root);
|
||||
var tests = ExtractTests(root);
|
||||
@@ -91,6 +98,10 @@ public sealed class OvalParser
|
||||
_logger.LogDebug("Parsed {Count} vulnerability definitions from OVAL XML", results.Count);
|
||||
return results;
|
||||
}
|
||||
catch (OvalParseException)
|
||||
{
|
||||
throw; // Re-throw validation exceptions as-is
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Failed to parse OVAL XML");
|
||||
@@ -281,15 +292,17 @@ public sealed class OvalParser
|
||||
continue;
|
||||
}
|
||||
|
||||
var evrElement = stateElement.Element(DpkgNs + "evr");
|
||||
var version = evrElement?.Value ?? string.Empty;
|
||||
var operation = evrElement?.Attribute("operation")?.Value ?? "less than";
|
||||
var evrElements = stateElement.Elements(DpkgNs + "evr").ToList();
|
||||
var constraints = evrElements.Select(evr => new OvalVersionConstraint
|
||||
{
|
||||
Version = evr.Value ?? string.Empty,
|
||||
Operation = evr.Attribute("operation")?.Value ?? "less than"
|
||||
}).ToList();
|
||||
|
||||
states.Add(new OvalState
|
||||
{
|
||||
Id = id,
|
||||
Version = version,
|
||||
Operation = operation
|
||||
Constraints = constraints
|
||||
});
|
||||
}
|
||||
|
||||
@@ -318,17 +331,32 @@ public sealed class OvalParser
|
||||
|
||||
string? fixedVersion = null;
|
||||
string? maxVersion = null;
|
||||
string? minVersion = null;
|
||||
|
||||
if (!string.IsNullOrEmpty(test.StateRef) && stateLookup.TryGetValue(test.StateRef, out var state))
|
||||
{
|
||||
// Parse operation to determine if this is a fixed version or affected version range
|
||||
if (state.Operation.Contains("less than", StringComparison.OrdinalIgnoreCase))
|
||||
foreach (var constraint in state.Constraints)
|
||||
{
|
||||
fixedVersion = state.Version; // Versions less than this are affected
|
||||
}
|
||||
else
|
||||
{
|
||||
maxVersion = state.Version;
|
||||
if (constraint.Operation.Contains("less than", StringComparison.OrdinalIgnoreCase) &&
|
||||
!constraint.Operation.Contains("or equal", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// "less than" -> versions below this are affected; this is the fixed version
|
||||
fixedVersion = constraint.Version;
|
||||
}
|
||||
else if (constraint.Operation.Contains("less than or equal", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// "less than or equal" -> upper bound of affected range
|
||||
maxVersion = constraint.Version;
|
||||
}
|
||||
else if (constraint.Operation.Contains("greater than or equal", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// "greater than or equal" -> lower bound of affected range
|
||||
minVersion = constraint.Version;
|
||||
}
|
||||
else if (constraint.Operation.Contains("greater than", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
minVersion = constraint.Version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,7 +368,7 @@ public sealed class OvalParser
|
||||
PackageName = obj.PackageName,
|
||||
FixedVersion = fixedVersion,
|
||||
MaxVersion = maxVersion,
|
||||
MinVersion = null
|
||||
MinVersion = minVersion
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -377,6 +405,11 @@ public sealed class OvalParser
|
||||
private sealed record OvalState
|
||||
{
|
||||
public required string Id { get; init; }
|
||||
public required List<OvalVersionConstraint> Constraints { get; init; }
|
||||
}
|
||||
|
||||
private sealed record OvalVersionConstraint
|
||||
{
|
||||
public required string Version { get; init; }
|
||||
public required string Operation { get; init; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user