feat: add security sink detection patterns for JavaScript/TypeScript
- 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.
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user