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,211 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// BudgetExceededEventFactory.cs
|
||||
// Sprint: SPRINT_4300_0002_0001 (Unknowns Budget Policy Integration)
|
||||
// Task: BUDGET-018 - Create `UnknownBudgetExceeded` notification event
|
||||
// Description: Factory for creating budget exceeded notification events.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System.Collections.Immutable;
|
||||
using System.Text.Json.Nodes;
|
||||
using StellaOps.Policy.Unknowns.Models;
|
||||
|
||||
namespace StellaOps.Policy.Unknowns.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Factory for creating budget exceeded notification events.
|
||||
/// </summary>
|
||||
public static class BudgetExceededEventFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Event kind for budget exceeded (blocking).
|
||||
/// </summary>
|
||||
public const string BudgetExceededKind = "policy.budget.exceeded";
|
||||
|
||||
/// <summary>
|
||||
/// Event kind for budget warning (non-blocking).
|
||||
/// </summary>
|
||||
public const string BudgetWarningKind = "policy.budget.warning";
|
||||
|
||||
/// <summary>
|
||||
/// Creates a budget exceeded notification event payload.
|
||||
/// </summary>
|
||||
public static BudgetEventPayload CreatePayload(
|
||||
string environment,
|
||||
BudgetCheckResult result,
|
||||
string? imageDigest = null,
|
||||
string? policyRevisionId = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(result);
|
||||
|
||||
var violations = result.Violations
|
||||
.Select(kvp => new BudgetViolationInfo(
|
||||
kvp.Key.ToString(),
|
||||
GetShortCode(kvp.Key),
|
||||
kvp.Value.Count,
|
||||
kvp.Value.Limit))
|
||||
.ToImmutableList();
|
||||
|
||||
return new BudgetEventPayload
|
||||
{
|
||||
Environment = environment,
|
||||
IsWithinBudget = result.IsWithinBudget,
|
||||
Action = result.RecommendedAction.ToString().ToLowerInvariant(),
|
||||
TotalUnknowns = result.TotalUnknowns,
|
||||
TotalLimit = result.TotalLimit,
|
||||
ViolationCount = result.Violations.Count,
|
||||
Violations = violations,
|
||||
Message = result.Message,
|
||||
ImageDigest = imageDigest,
|
||||
PolicyRevisionId = policyRevisionId,
|
||||
Timestamp = DateTimeOffset.UtcNow
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the payload to a JsonNode for the notification event.
|
||||
/// </summary>
|
||||
public static JsonNode ToJsonNode(BudgetEventPayload payload)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(payload);
|
||||
|
||||
var obj = new JsonObject
|
||||
{
|
||||
["environment"] = payload.Environment,
|
||||
["isWithinBudget"] = payload.IsWithinBudget,
|
||||
["action"] = payload.Action,
|
||||
["totalUnknowns"] = payload.TotalUnknowns,
|
||||
["violationCount"] = payload.ViolationCount,
|
||||
["timestamp"] = payload.Timestamp.ToString("O")
|
||||
};
|
||||
|
||||
if (payload.TotalLimit.HasValue)
|
||||
{
|
||||
obj["totalLimit"] = payload.TotalLimit.Value;
|
||||
}
|
||||
|
||||
if (payload.Message is not null)
|
||||
{
|
||||
obj["message"] = payload.Message;
|
||||
}
|
||||
|
||||
if (payload.ImageDigest is not null)
|
||||
{
|
||||
obj["imageDigest"] = payload.ImageDigest;
|
||||
}
|
||||
|
||||
if (payload.PolicyRevisionId is not null)
|
||||
{
|
||||
obj["policyRevisionId"] = payload.PolicyRevisionId;
|
||||
}
|
||||
|
||||
if (payload.Violations.Count > 0)
|
||||
{
|
||||
var violations = new JsonArray();
|
||||
foreach (var v in payload.Violations)
|
||||
{
|
||||
violations.Add(new JsonObject
|
||||
{
|
||||
["reasonCode"] = v.ReasonCode,
|
||||
["shortCode"] = v.ShortCode,
|
||||
["count"] = v.Count,
|
||||
["limit"] = v.Limit
|
||||
});
|
||||
}
|
||||
obj["violations"] = violations;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the event kind based on the budget action.
|
||||
/// </summary>
|
||||
public static string GetEventKind(BudgetAction action)
|
||||
{
|
||||
return action == BudgetAction.Block
|
||||
? BudgetExceededKind
|
||||
: BudgetWarningKind;
|
||||
}
|
||||
|
||||
private static string GetShortCode(UnknownReasonCode code) => code switch
|
||||
{
|
||||
UnknownReasonCode.Reachability => "U-RCH",
|
||||
UnknownReasonCode.Identity => "U-ID",
|
||||
UnknownReasonCode.Provenance => "U-PROV",
|
||||
UnknownReasonCode.VexConflict => "U-VEX",
|
||||
UnknownReasonCode.FeedGap => "U-FEED",
|
||||
UnknownReasonCode.ConfigUnknown => "U-CONFIG",
|
||||
UnknownReasonCode.AnalyzerLimit => "U-ANALYZER",
|
||||
_ => "U-UNK"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Payload for budget exceeded/warning notification events.
|
||||
/// </summary>
|
||||
public sealed record BudgetEventPayload
|
||||
{
|
||||
/// <summary>
|
||||
/// Environment where budget was exceeded.
|
||||
/// </summary>
|
||||
public required string Environment { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the result is within budget.
|
||||
/// </summary>
|
||||
public required bool IsWithinBudget { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Recommended action: "warn" or "block".
|
||||
/// </summary>
|
||||
public required string Action { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Total unknown count.
|
||||
/// </summary>
|
||||
public required int TotalUnknowns { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Configured total limit.
|
||||
/// </summary>
|
||||
public int? TotalLimit { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of violations.
|
||||
/// </summary>
|
||||
public required int ViolationCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Violation details.
|
||||
/// </summary>
|
||||
public ImmutableList<BudgetViolationInfo> Violations { get; init; } = ImmutableList<BudgetViolationInfo>.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Budget exceeded message.
|
||||
/// </summary>
|
||||
public string? Message { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Image digest if applicable.
|
||||
/// </summary>
|
||||
public string? ImageDigest { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Policy revision ID if applicable.
|
||||
/// </summary>
|
||||
public string? PolicyRevisionId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Event timestamp.
|
||||
/// </summary>
|
||||
public DateTimeOffset Timestamp { get; init; } = DateTimeOffset.UtcNow;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Information about a specific budget violation.
|
||||
/// </summary>
|
||||
public sealed record BudgetViolationInfo(
|
||||
string ReasonCode,
|
||||
string ShortCode,
|
||||
int Count,
|
||||
int Limit);
|
||||
Reference in New Issue
Block a user