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:
@@ -44,7 +44,7 @@ public sealed record RuntimeStaticMergeResult
|
||||
/// <summary>
|
||||
/// Merged graph with runtime annotations.
|
||||
/// </summary>
|
||||
public required CallGraph MergedGraph { get; init; }
|
||||
public required RichGraph MergedGraph { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Statistics about the merge operation.
|
||||
@@ -141,7 +141,7 @@ public sealed class RuntimeStaticMerger
|
||||
/// Merge runtime events into a static call graph.
|
||||
/// </summary>
|
||||
public RuntimeStaticMergeResult Merge(
|
||||
CallGraph staticGraph,
|
||||
RichGraph staticGraph,
|
||||
IEnumerable<RuntimeCallEvent> runtimeEvents)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(staticGraph);
|
||||
@@ -158,7 +158,7 @@ public sealed class RuntimeStaticMerger
|
||||
|
||||
var observedEdges = new List<ObservedEdge>();
|
||||
var runtimeOnlyEdges = new List<RuntimeOnlyEdge>();
|
||||
var modifiedEdges = new List<CallEdge>();
|
||||
var modifiedEdges = new List<RichGraphEdge>();
|
||||
var matchedEdgeKeys = new HashSet<string>(StringComparer.Ordinal);
|
||||
|
||||
foreach (var (edgeKey, aggregate) in runtimeEdgeAggregates)
|
||||
@@ -177,21 +177,12 @@ public sealed class RuntimeStaticMerger
|
||||
|
||||
if (staticEdgeIndex.TryGetValue(edgeKey, out var staticEdge))
|
||||
{
|
||||
// Edge exists in static graph - mark as observed
|
||||
// Edge exists in static graph - mark as observed with boosted confidence
|
||||
matchedEdgeKeys.Add(edgeKey);
|
||||
|
||||
var observedMetadata = new ObservedEdgeMetadata
|
||||
{
|
||||
FirstObserved = aggregate.FirstObserved,
|
||||
LastObserved = aggregate.LastObserved,
|
||||
ObservationCount = aggregate.ObservationCount,
|
||||
TraceDigest = aggregate.TraceDigest
|
||||
};
|
||||
|
||||
var boostedEdge = staticEdge with
|
||||
{
|
||||
Confidence = _options.ObservedConfidenceBoost,
|
||||
Observed = observedMetadata
|
||||
Confidence = _options.ObservedConfidenceBoost
|
||||
};
|
||||
|
||||
modifiedEdges.Add(boostedEdge);
|
||||
@@ -207,22 +198,16 @@ public sealed class RuntimeStaticMerger
|
||||
}
|
||||
else if (_options.AddRuntimeOnlyEdges)
|
||||
{
|
||||
// Edge only exists in runtime - add it
|
||||
var runtimeEdge = new CallEdge
|
||||
{
|
||||
From = aggregate.From,
|
||||
To = aggregate.To,
|
||||
Kind = CallEdgeKind.Dynamic,
|
||||
Confidence = ComputeRuntimeOnlyConfidence(aggregate),
|
||||
Evidence = "runtime_observation",
|
||||
Observed = new ObservedEdgeMetadata
|
||||
{
|
||||
FirstObserved = aggregate.FirstObserved,
|
||||
LastObserved = aggregate.LastObserved,
|
||||
ObservationCount = aggregate.ObservationCount,
|
||||
TraceDigest = aggregate.TraceDigest
|
||||
}
|
||||
};
|
||||
// Edge only exists in runtime - add it as dynamic edge
|
||||
var runtimeEdge = new RichGraphEdge(
|
||||
From: aggregate.From,
|
||||
To: aggregate.To,
|
||||
Kind: "dynamic",
|
||||
Purl: null,
|
||||
SymbolDigest: null,
|
||||
Evidence: new[] { "runtime_observation" },
|
||||
Confidence: ComputeRuntimeOnlyConfidence(aggregate),
|
||||
Candidates: null);
|
||||
|
||||
modifiedEdges.Add(runtimeEdge);
|
||||
runtimeOnlyEdges.Add(new RuntimeOnlyEdge
|
||||
@@ -239,7 +224,7 @@ public sealed class RuntimeStaticMerger
|
||||
}
|
||||
|
||||
// Build merged edge list: unmatched static + modified
|
||||
var mergedEdges = new List<CallEdge>();
|
||||
var mergedEdges = new List<RichGraphEdge>();
|
||||
foreach (var edge in staticGraph.Edges)
|
||||
{
|
||||
var key = BuildEdgeKey(edge.From, edge.To);
|
||||
@@ -252,16 +237,16 @@ public sealed class RuntimeStaticMerger
|
||||
|
||||
var mergedGraph = staticGraph with
|
||||
{
|
||||
Edges = mergedEdges.ToImmutableArray()
|
||||
Edges = mergedEdges
|
||||
};
|
||||
|
||||
var statistics = new MergeStatistics
|
||||
{
|
||||
StaticEdgeCount = staticGraph.Edges.Length,
|
||||
StaticEdgeCount = staticGraph.Edges.Count,
|
||||
RuntimeEventCount = runtimeEdgeAggregates.Count,
|
||||
MatchedEdgeCount = matchedEdgeKeys.Count,
|
||||
RuntimeOnlyEdgeCount = runtimeOnlyEdges.Count,
|
||||
UnmatchedStaticEdgeCount = staticGraph.Edges.Length - matchedEdgeKeys.Count
|
||||
UnmatchedStaticEdgeCount = staticGraph.Edges.Count - matchedEdgeKeys.Count
|
||||
};
|
||||
|
||||
_logger.LogInformation(
|
||||
@@ -280,9 +265,9 @@ public sealed class RuntimeStaticMerger
|
||||
};
|
||||
}
|
||||
|
||||
private static Dictionary<string, CallEdge> BuildStaticEdgeIndex(CallGraph graph)
|
||||
private static Dictionary<string, RichGraphEdge> BuildStaticEdgeIndex(RichGraph graph)
|
||||
{
|
||||
var index = new Dictionary<string, CallEdge>(StringComparer.Ordinal);
|
||||
var index = new Dictionary<string, RichGraphEdge>(StringComparer.Ordinal);
|
||||
foreach (var edge in graph.Edges)
|
||||
{
|
||||
var key = BuildEdgeKey(edge.From, edge.To);
|
||||
|
||||
@@ -1,25 +1 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.0" />
|
||||
<PackageReference Include="Npgsql" Version="9.0.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\StellaOps.Scanner.Core\StellaOps.Scanner.Core.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Scanner.Cache\StellaOps.Scanner.Cache.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Scanner.ProofSpine\StellaOps.Scanner.ProofSpine.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Scanner.Surface.Env\StellaOps.Scanner.Surface.Env.csproj" />
|
||||
<ProjectReference Include="..\StellaOps.Scanner.SmartDiff\StellaOps.Scanner.SmartDiff.csproj" />
|
||||
<ProjectReference Include="..\..\StellaOps.Scanner.Analyzers.Native\StellaOps.Scanner.Analyzers.Native.csproj" />
|
||||
<ProjectReference Include="..\..\..\Attestor\StellaOps.Attestor\StellaOps.Attestor.Core\StellaOps.Attestor.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\Attestor\StellaOps.Attestor.Envelope\StellaOps.Attestor.Envelope.csproj" />
|
||||
<ProjectReference Include="..\..\..\Attestor\__Libraries\StellaOps.Attestor.ProofChain\StellaOps.Attestor.ProofChain.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Replay.Core\StellaOps.Replay.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\__Libraries\StellaOps.Cryptography\StellaOps.Cryptography.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user