up
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				Build Test Deploy / authority-container (push) Has been cancelled
				
			
		
			
				
	
				Build Test Deploy / docs (push) Has been cancelled
				
			
		
			
				
	
				Build Test Deploy / deploy (push) Has been cancelled
				
			
		
			
				
	
				Build Test Deploy / build-test (push) Has been cancelled
				
			
		
			
				
	
				Docs CI / lint-and-preview (push) Has been cancelled
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	Build Test Deploy / authority-container (push) Has been cancelled
				
			Build Test Deploy / docs (push) Has been cancelled
				
			Build Test Deploy / deploy (push) Has been cancelled
				
			Build Test Deploy / build-test (push) Has been cancelled
				
			Docs CI / lint-and-preview (push) Has been cancelled
				
			This commit is contained in:
		| @@ -1,6 +1,9 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.Collections.Immutable; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using StellaOps.Feedser.Models; | ||||
| using StellaOps.Feedser.Normalization.Cvss; | ||||
| using StellaOps.Feedser.Normalization.SemVer; | ||||
| using StellaOps.Feedser.Storage.Mongo.Documents; | ||||
|  | ||||
| @@ -51,9 +54,12 @@ internal static class GhsaMapper | ||||
|  | ||||
|         var affected = CreateAffectedPackages(dto, recordedAt); | ||||
|         var credits = CreateCredits(dto.Credits, recordedAt); | ||||
|         var weaknesses = CreateWeaknesses(dto.Cwes, recordedAt); | ||||
|         var cvssMetrics = CreateCvssMetrics(dto.Cvss, recordedAt, out var cvssSeverity, out var canonicalMetricId); | ||||
|  | ||||
|         var severity = dto.Severity?.ToLowerInvariant(); | ||||
|         var severity = SeverityNormalization.Normalize(dto.Severity) ?? cvssSeverity; | ||||
|         var summary = dto.Summary ?? dto.Description; | ||||
|         var description = Validation.TrimToNull(dto.Description); | ||||
|  | ||||
|         return new Advisory( | ||||
|             advisoryKey: dto.GhsaId, | ||||
| @@ -68,8 +74,11 @@ internal static class GhsaMapper | ||||
|             credits: credits, | ||||
|             references: references, | ||||
|             affectedPackages: affected, | ||||
|             cvssMetrics: Array.Empty<CvssMetric>(), | ||||
|             provenance: new[] { fetchProvenance, mapProvenance }); | ||||
|             cvssMetrics: cvssMetrics, | ||||
|             provenance: new[] { fetchProvenance, mapProvenance }, | ||||
|             description: description, | ||||
|             cwes: weaknesses, | ||||
|             canonicalMetricId: canonicalMetricId); | ||||
|     } | ||||
|  | ||||
|     private static AdvisoryReference? CreateReference(GhsaReferenceDto reference, DateTimeOffset recordedAt) | ||||
| @@ -189,6 +198,100 @@ internal static class GhsaMapper | ||||
|         return results.Count == 0 ? Array.Empty<AdvisoryCredit>() : results; | ||||
|     } | ||||
|  | ||||
|     private static IReadOnlyList<AdvisoryWeakness> CreateWeaknesses(IReadOnlyList<GhsaWeaknessDto> cwes, DateTimeOffset recordedAt) | ||||
|     { | ||||
|         if (cwes.Count == 0) | ||||
|         { | ||||
|             return Array.Empty<AdvisoryWeakness>(); | ||||
|         } | ||||
|  | ||||
|         var list = new List<AdvisoryWeakness>(cwes.Count); | ||||
|         foreach (var cwe in cwes) | ||||
|         { | ||||
|             if (cwe is null || string.IsNullOrWhiteSpace(cwe.CweId)) | ||||
|             { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             var identifier = cwe.CweId.Trim(); | ||||
|             var provenance = new AdvisoryProvenance( | ||||
|                 GhsaConnectorPlugin.SourceName, | ||||
|                 "weakness", | ||||
|                 identifier, | ||||
|                 recordedAt, | ||||
|                 new[] { ProvenanceFieldMasks.Weaknesses }); | ||||
|  | ||||
|             var provenanceArray = ImmutableArray.Create(provenance); | ||||
|             list.Add(new AdvisoryWeakness( | ||||
|                 taxonomy: "cwe", | ||||
|                 identifier: identifier, | ||||
|                 name: Validation.TrimToNull(cwe.Name), | ||||
|                 uri: BuildCweUrl(identifier), | ||||
|                 provenance: provenanceArray)); | ||||
|         } | ||||
|  | ||||
|         return list.Count == 0 ? Array.Empty<AdvisoryWeakness>() : list; | ||||
|     } | ||||
|  | ||||
|     private static IReadOnlyList<CvssMetric> CreateCvssMetrics(GhsaCvssDto? cvss, DateTimeOffset recordedAt, out string? severity, out string? canonicalMetricId) | ||||
|     { | ||||
|         severity = null; | ||||
|         canonicalMetricId = null; | ||||
|  | ||||
|         if (cvss is null) | ||||
|         { | ||||
|             return Array.Empty<CvssMetric>(); | ||||
|         } | ||||
|  | ||||
|         var vector = Validation.TrimToNull(cvss.VectorString); | ||||
|         if (!CvssMetricNormalizer.TryNormalize(null, vector, cvss.Score, cvss.Severity, out var normalized)) | ||||
|         { | ||||
|             return Array.Empty<CvssMetric>(); | ||||
|         } | ||||
|  | ||||
|         severity = normalized.BaseSeverity; | ||||
|         canonicalMetricId = $"{normalized.Version}|{normalized.Vector}"; | ||||
|  | ||||
|         var provenance = new AdvisoryProvenance( | ||||
|             GhsaConnectorPlugin.SourceName, | ||||
|             "cvss", | ||||
|             normalized.Vector, | ||||
|             recordedAt, | ||||
|             new[] { ProvenanceFieldMasks.CvssMetrics }); | ||||
|  | ||||
|         return new[] | ||||
|         { | ||||
|             normalized.ToModel(provenance), | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     private static string? BuildCweUrl(string? cweId) | ||||
|     { | ||||
|         if (string.IsNullOrWhiteSpace(cweId)) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         var trimmed = cweId.Trim(); | ||||
|         var dashIndex = trimmed.IndexOf('-'); | ||||
|         if (dashIndex < 0 || dashIndex == trimmed.Length - 1) | ||||
|         { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         var digits = new StringBuilder(); | ||||
|         for (var i = dashIndex + 1; i < trimmed.Length; i++) | ||||
|         { | ||||
|             var ch = trimmed[i]; | ||||
|             if (char.IsDigit(ch)) | ||||
|             { | ||||
|                 digits.Append(ch); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return digits.Length == 0 ? null : $"https://cwe.mitre.org/data/definitions/{digits}.html"; | ||||
|     } | ||||
|  | ||||
|     private static (IReadOnlyList<AffectedVersionRange> Ranges, IReadOnlyList<NormalizedVersionRule> Normalized) CreateSemVerVersionArtifacts( | ||||
|         GhsaAffectedDto affected, | ||||
|         string identifier, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user