- Introduced `sink-detect.js` with various security sink detection patterns categorized by type (e.g., command injection, SQL injection, file operations). - Implemented functions to build a lookup map for fast sink detection and to match sink calls against known patterns. - Added `package-lock.json` for dependency management.
219 lines
7.6 KiB
C#
219 lines
7.6 KiB
C#
// -----------------------------------------------------------------------------
|
|
// CounterfactualEndpointsTests.cs
|
|
// Sprint: SPRINT_4200_0002_0005_counterfactuals
|
|
// Description: Integration tests for counterfactual analysis endpoints.
|
|
// -----------------------------------------------------------------------------
|
|
|
|
using System.Net;
|
|
using System.Net.Http.Json;
|
|
using System.Text.Json;
|
|
using StellaOps.Scanner.WebService.Endpoints;
|
|
|
|
namespace StellaOps.Scanner.WebService.Tests;
|
|
|
|
/// <summary>
|
|
/// Integration tests for counterfactual analysis endpoints.
|
|
/// </summary>
|
|
public sealed class CounterfactualEndpointsTests
|
|
{
|
|
private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web);
|
|
|
|
[Fact]
|
|
public async Task PostCompute_ValidRequest_ReturnsCounterfactuals()
|
|
{
|
|
using var factory = new ScannerApplicationFactory();
|
|
using var client = factory.CreateClient();
|
|
|
|
var request = new CounterfactualRequestDto
|
|
{
|
|
FindingId = "finding-123",
|
|
VulnId = "CVE-2021-44228",
|
|
Purl = "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1",
|
|
CurrentVerdict = "Block"
|
|
};
|
|
|
|
var response = await client.PostAsJsonAsync("/api/v1/counterfactuals/compute", request);
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
|
|
var result = await response.Content.ReadFromJsonAsync<CounterfactualResponseDto>(SerializerOptions);
|
|
Assert.NotNull(result);
|
|
Assert.Equal("finding-123", result!.FindingId);
|
|
Assert.Equal("Block", result.CurrentVerdict);
|
|
Assert.True(result.HasPaths);
|
|
Assert.NotEmpty(result.Paths);
|
|
Assert.NotEmpty(result.WouldPassIf);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PostCompute_MissingFindingId_ReturnsBadRequest()
|
|
{
|
|
using var factory = new ScannerApplicationFactory();
|
|
using var client = factory.CreateClient();
|
|
|
|
var request = new CounterfactualRequestDto
|
|
{
|
|
FindingId = "",
|
|
VulnId = "CVE-2021-44228"
|
|
};
|
|
|
|
var response = await client.PostAsJsonAsync("/api/v1/counterfactuals/compute", request);
|
|
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PostCompute_IncludesVexPath()
|
|
{
|
|
using var factory = new ScannerApplicationFactory();
|
|
using var client = factory.CreateClient();
|
|
|
|
var request = new CounterfactualRequestDto
|
|
{
|
|
FindingId = "finding-123",
|
|
VulnId = "CVE-2021-44228",
|
|
CurrentVerdict = "Block"
|
|
};
|
|
|
|
var response = await client.PostAsJsonAsync("/api/v1/counterfactuals/compute", request);
|
|
var result = await response.Content.ReadFromJsonAsync<CounterfactualResponseDto>(SerializerOptions);
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Contains(result!.Paths, p => p.Type == "Vex");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PostCompute_IncludesReachabilityPath()
|
|
{
|
|
using var factory = new ScannerApplicationFactory();
|
|
using var client = factory.CreateClient();
|
|
|
|
var request = new CounterfactualRequestDto
|
|
{
|
|
FindingId = "finding-123",
|
|
VulnId = "CVE-2021-44228",
|
|
CurrentVerdict = "Block"
|
|
};
|
|
|
|
var response = await client.PostAsJsonAsync("/api/v1/counterfactuals/compute", request);
|
|
var result = await response.Content.ReadFromJsonAsync<CounterfactualResponseDto>(SerializerOptions);
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Contains(result!.Paths, p => p.Type == "Reachability");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PostCompute_IncludesExceptionPath()
|
|
{
|
|
using var factory = new ScannerApplicationFactory();
|
|
using var client = factory.CreateClient();
|
|
|
|
var request = new CounterfactualRequestDto
|
|
{
|
|
FindingId = "finding-123",
|
|
VulnId = "CVE-2021-44228",
|
|
CurrentVerdict = "Block"
|
|
};
|
|
|
|
var response = await client.PostAsJsonAsync("/api/v1/counterfactuals/compute", request);
|
|
var result = await response.Content.ReadFromJsonAsync<CounterfactualResponseDto>(SerializerOptions);
|
|
|
|
Assert.NotNull(result);
|
|
Assert.Contains(result!.Paths, p => p.Type == "Exception");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PostCompute_WithMaxPaths_LimitsResults()
|
|
{
|
|
using var factory = new ScannerApplicationFactory();
|
|
using var client = factory.CreateClient();
|
|
|
|
var request = new CounterfactualRequestDto
|
|
{
|
|
FindingId = "finding-123",
|
|
VulnId = "CVE-2021-44228",
|
|
CurrentVerdict = "Block",
|
|
MaxPaths = 2
|
|
};
|
|
|
|
var response = await client.PostAsJsonAsync("/api/v1/counterfactuals/compute", request);
|
|
var result = await response.Content.ReadFromJsonAsync<CounterfactualResponseDto>(SerializerOptions);
|
|
|
|
Assert.NotNull(result);
|
|
Assert.True(result!.Paths.Count <= 2);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetForFinding_ValidId_ReturnsCounterfactuals()
|
|
{
|
|
using var factory = new ScannerApplicationFactory();
|
|
using var client = factory.CreateClient();
|
|
|
|
var response = await client.GetAsync("/api/v1/counterfactuals/finding/finding-123");
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
|
|
var result = await response.Content.ReadFromJsonAsync<CounterfactualResponseDto>(SerializerOptions);
|
|
Assert.NotNull(result);
|
|
Assert.Equal("finding-123", result!.FindingId);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetScanSummary_ValidId_ReturnsSummary()
|
|
{
|
|
using var factory = new ScannerApplicationFactory();
|
|
using var client = factory.CreateClient();
|
|
|
|
var response = await client.GetAsync("/api/v1/counterfactuals/scan/scan-123/summary");
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
|
|
var result = await response.Content.ReadFromJsonAsync<CounterfactualScanSummaryDto>(SerializerOptions);
|
|
Assert.NotNull(result);
|
|
Assert.Equal("scan-123", result!.ScanId);
|
|
Assert.NotNull(result.Findings);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetScanSummary_IncludesPathCounts()
|
|
{
|
|
using var factory = new ScannerApplicationFactory();
|
|
using var client = factory.CreateClient();
|
|
|
|
var response = await client.GetAsync("/api/v1/counterfactuals/scan/scan-123/summary");
|
|
var result = await response.Content.ReadFromJsonAsync<CounterfactualScanSummaryDto>(SerializerOptions);
|
|
|
|
Assert.NotNull(result);
|
|
Assert.True(result!.TotalBlocked >= 0);
|
|
Assert.True(result.WithVexPath >= 0);
|
|
Assert.True(result.WithReachabilityPath >= 0);
|
|
Assert.True(result.WithUpgradePath >= 0);
|
|
Assert.True(result.WithExceptionPath >= 0);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PostCompute_PathsHaveConditions()
|
|
{
|
|
using var factory = new ScannerApplicationFactory();
|
|
using var client = factory.CreateClient();
|
|
|
|
var request = new CounterfactualRequestDto
|
|
{
|
|
FindingId = "finding-123",
|
|
VulnId = "CVE-2021-44228",
|
|
CurrentVerdict = "Block"
|
|
};
|
|
|
|
var response = await client.PostAsJsonAsync("/api/v1/counterfactuals/compute", request);
|
|
var result = await response.Content.ReadFromJsonAsync<CounterfactualResponseDto>(SerializerOptions);
|
|
|
|
Assert.NotNull(result);
|
|
foreach (var path in result!.Paths)
|
|
{
|
|
Assert.NotEmpty(path.Description);
|
|
Assert.NotEmpty(path.Conditions);
|
|
foreach (var condition in path.Conditions)
|
|
{
|
|
Assert.NotEmpty(condition.Field);
|
|
Assert.NotEmpty(condition.RequiredValue);
|
|
}
|
|
}
|
|
}
|
|
}
|