Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IAST] Lock vulnerabilities list access #6531

Merged
merged 1 commit into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 84 additions & 72 deletions tracer/src/Datadog.Trace/Iast/VulnerabilityBatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,10 @@

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Datadog.Trace.AppSec.Rasp;
using Datadog.Trace.Iast.SensitiveData;
using Datadog.Trace.Iast.Settings;
using Datadog.Trace.Logging;
using Datadog.Trace.Util.Http;
using Datadog.Trace.Vendors.dnlib;
using Datadog.Trace.Vendors.Newtonsoft.Json;
using Datadog.Trace.Vendors.Newtonsoft.Json.Serialization;

Expand All @@ -31,6 +26,8 @@ internal class VulnerabilityBatch
private static Lazy<JsonSerializerSettings> _truncatedSettings = new(() => CreateTruncatedSettings());

private readonly int _truncationMaxValueLength;
private readonly List<Vulnerability> _vulnerabilities = new List<Vulnerability>();
private List<Source>? _sources = null;
private EvidenceRedactor? _evidenceRedactor;
private JsonSerializerSettings _serializerSettings;
private string? _vulnerabilitiesJson;
Expand All @@ -52,9 +49,9 @@ public VulnerabilityBatch(int truncationMaxValueLength = IastSettings.Truncation
}
}

public List<Vulnerability> Vulnerabilities { get; } = new List<Vulnerability>();
public ICollection<Vulnerability> Vulnerabilities => _vulnerabilities;

public List<Source>? Sources { get; private set; } = null;
public ICollection<Source>? Sources => _sources;

public bool IsTruncated() => _isTruncated;

Expand Down Expand Up @@ -87,27 +84,30 @@ private static JsonSerializerSettings CreateTruncatedSettings()

public void Add(Vulnerability vulnerability)
{
_vulnerabilitiesJson = null;
var ranges = vulnerability.Evidence?.Ranges;

if (ranges != null)
lock (_vulnerabilities)
{
foreach (var range in ranges)
_vulnerabilitiesJson = null;
var ranges = vulnerability.Evidence?.Ranges;

if (ranges != null)
{
if (Sources is null)
foreach (var range in ranges)
{
Sources = new List<Source>();
}
if (Sources is null)
{
_sources = new List<Source>();
}

if (range.Source != null && !Sources.Contains(range.Source))
{
range.Source.SetInternalId(Sources.Count);
Sources.Add(range.Source);
if (range.Source != null && _sources is not null && !_sources.Contains(range.Source))
{
range.Source.SetInternalId(_sources.Count);
_sources.Add(range.Source);
}
}
}
}

Vulnerabilities.Add(vulnerability);
_vulnerabilities.Add(vulnerability);
}
}

public string ToJson()
Expand All @@ -116,32 +116,35 @@ public string ToJson()
{
if (_vulnerabilitiesJson == null)
{
if (_evidenceRedactor == null)
{
_vulnerabilitiesJson = JsonConvert.SerializeObject(this, Formatting.Indented, _serializerSettings);
}
else
lock (_vulnerabilities)
{
if (Sources != null)
if (_evidenceRedactor == null)
{
foreach (var source in Sources)
_vulnerabilitiesJson = JsonConvert.SerializeObject(this, Formatting.Indented, _serializerSettings);
}
else
{
if (Sources != null)
{
_evidenceRedactor.Process(source);
foreach (var source in Sources)
{
_evidenceRedactor.Process(source);
}
}

for (int x = 0; x < _vulnerabilities.Count; x++)
{
_vulnerabilities[x] = _evidenceRedactor.RedactVulnerability(_vulnerabilities[x]);
}

_vulnerabilitiesJson = JsonConvert.SerializeObject(this, Formatting.Indented, _serializerSettings);
}

for (int x = 0; x < Vulnerabilities.Count; x++)
if (System.Text.ASCIIEncoding.Unicode.GetByteCount(_vulnerabilitiesJson) > MaxSpanTagSize)
{
Vulnerabilities[x] = _evidenceRedactor.RedactVulnerability(Vulnerabilities[x]);
_vulnerabilitiesJson = ToTruncatedJson();
_isTruncated = true;
}

_vulnerabilitiesJson = JsonConvert.SerializeObject(this, Formatting.Indented, _serializerSettings);
}

if (System.Text.ASCIIEncoding.Unicode.GetByteCount(_vulnerabilitiesJson) > MaxSpanTagSize)
{
_vulnerabilitiesJson = ToTruncatedJson();
_isTruncated = true;
}
}

Expand All @@ -158,40 +161,43 @@ public byte[] ToMessagePack()
{
try
{
byte[] result;
Dictionary<string, object> toSerialize;

if (_evidenceRedactor == null)
{
toSerialize = MetaStructHelper.VulnerabilityBatchToDictionary(this);
result = MetaStructHelper.ObjectToByteArray(toSerialize);
}
else
lock (_vulnerabilities)
{
if (Sources != null)
byte[] result;
Dictionary<string, object> toSerialize;

if (_evidenceRedactor == null)
{
toSerialize = MetaStructHelper.VulnerabilityBatchToDictionary(this);
result = MetaStructHelper.ObjectToByteArray(toSerialize);
}
else
{
foreach (var source in Sources)
if (Sources != null)
{
foreach (var source in Sources)
{
_evidenceRedactor.Process(source);
}
}

for (var x = 0; x < _vulnerabilities.Count; x++)
{
_evidenceRedactor.Process(source);
_vulnerabilities[x] = _evidenceRedactor.RedactVulnerability(_vulnerabilities[x]);
}

toSerialize = MetaStructHelper.VulnerabilityBatchToDictionary(this);
result = MetaStructHelper.ObjectToByteArray(toSerialize);
}

for (var x = 0; x < Vulnerabilities.Count; x++)
if (result.Length > MaxSpanTagSize)
{
Vulnerabilities[x] = _evidenceRedactor.RedactVulnerability(Vulnerabilities[x]);
result = ToTruncatedMessagePack(toSerialize);
_isTruncated = true;
}

toSerialize = MetaStructHelper.VulnerabilityBatchToDictionary(this);
result = MetaStructHelper.ObjectToByteArray(toSerialize);
}

if (result.Length > MaxSpanTagSize)
{
result = ToTruncatedMessagePack(toSerialize);
_isTruncated = true;
return result;
}

return result;
}
catch (Exception ex)
{
Expand All @@ -202,26 +208,32 @@ public byte[] ToMessagePack()

internal string ToTruncatedJson()
{
return JsonConvert.SerializeObject(new TruncatedVulnerabilities(Vulnerabilities), Formatting.Indented, _truncatedSettings.Value);
lock (_vulnerabilities)
{
return JsonConvert.SerializeObject(new TruncatedVulnerabilities(_vulnerabilities), Formatting.Indented, _truncatedSettings.Value);
}
}

internal byte[] ToTruncatedMessagePack(Dictionary<string, object> vulnerabilityBatchDictionary)
{
if (vulnerabilityBatchDictionary["vulnerabilities"] is List<Dictionary<string, object>> vulnerabilities)
lock (_vulnerabilities)
{
foreach (var vulnerability in vulnerabilities)
if (vulnerabilityBatchDictionary["vulnerabilities"] is List<Dictionary<string, object>> vulnerabilities)
{
if (vulnerability["evidence"] is Dictionary<string, object> evidence)
foreach (var vulnerability in vulnerabilities)
{
evidence.Clear();
evidence["value"] = TruncatedVulnerabilities.MaxSizeExceeded;
if (vulnerability["evidence"] is Dictionary<string, object> evidence)
{
evidence.Clear();
evidence["value"] = TruncatedVulnerabilities.MaxSizeExceeded;
}
}
}
}

vulnerabilityBatchDictionary.Remove("sources");
vulnerabilityBatchDictionary.Remove("sources");

return MetaStructHelper.ObjectToByteArray(vulnerabilityBatchDictionary);
return MetaStructHelper.ObjectToByteArray(vulnerabilityBatchDictionary);
}
}

public override string ToString()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
// </copyright>

using System.Linq;
using System.Text;
using Datadog.Trace.AppSec.Rasp;
using Datadog.Trace.Iast;
Expand Down Expand Up @@ -166,9 +167,10 @@ public void GivenAVulnerabilityBatch_WhenAddTwoVulnerabilities_VulnerabilitiesAr
batch.Add(vulnerability2);

batch.Vulnerabilities.Count.Should().Be(2);
batch.Sources.Count.Should().Be(2);
batch.Sources[0].GetInternalId().Should().Be(0);
batch.Sources[1].GetInternalId().Should().Be(1);
var sources = batch.Sources.ToList();
sources.Count.Should().Be(2);
sources[0].GetInternalId().Should().Be(0);
sources[1].GetInternalId().Should().Be(1);

var json = batch.ToJson();
var metaStructJson = VulnerabilityBatchMetaStructToJson(batch);
Expand Down
Loading