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:
236
src/Policy/__Libraries/StellaOps.Policy/Deltas/DeltaVerdict.cs
Normal file
236
src/Policy/__Libraries/StellaOps.Policy/Deltas/DeltaVerdict.cs
Normal file
@@ -0,0 +1,236 @@
|
||||
namespace StellaOps.Policy.Deltas;
|
||||
|
||||
/// <summary>
|
||||
/// Verdict for a security state delta.
|
||||
/// Determines whether a change should be allowed to proceed.
|
||||
/// </summary>
|
||||
public sealed record DeltaVerdict
|
||||
{
|
||||
/// <summary>
|
||||
/// Unique identifier for this verdict.
|
||||
/// </summary>
|
||||
public required string VerdictId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Reference to the delta being evaluated.
|
||||
/// </summary>
|
||||
public required string DeltaId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// When this verdict was rendered.
|
||||
/// </summary>
|
||||
public required DateTimeOffset EvaluatedAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The verdict outcome.
|
||||
/// </summary>
|
||||
public required DeltaVerdictStatus Status { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Recommended gate level based on delta risk.
|
||||
/// </summary>
|
||||
public DeltaGateLevel RecommendedGate { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Risk points consumed by this change.
|
||||
/// </summary>
|
||||
public int RiskPoints { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Drivers that contributed to the verdict.
|
||||
/// </summary>
|
||||
public IReadOnlyList<DeltaDriver> BlockingDrivers { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Drivers that raised warnings but didn't block.
|
||||
/// </summary>
|
||||
public IReadOnlyList<DeltaDriver> WarningDrivers { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Applied exceptions that allowed blocking drivers.
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> AppliedExceptions { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Human-readable explanation.
|
||||
/// </summary>
|
||||
public string? Explanation { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Recommendations for addressing issues.
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> Recommendations { get; init; } = [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Possible verdict outcomes for a delta.
|
||||
/// </summary>
|
||||
public enum DeltaVerdictStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Delta is safe to proceed.
|
||||
/// </summary>
|
||||
Pass,
|
||||
|
||||
/// <summary>
|
||||
/// Delta has warnings but can proceed.
|
||||
/// </summary>
|
||||
Warn,
|
||||
|
||||
/// <summary>
|
||||
/// Delta should not proceed without remediation.
|
||||
/// </summary>
|
||||
Fail,
|
||||
|
||||
/// <summary>
|
||||
/// Delta is blocked but covered by exceptions.
|
||||
/// </summary>
|
||||
PassWithExceptions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gate levels aligned with diff-aware release gates.
|
||||
/// </summary>
|
||||
public enum DeltaGateLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// G0: No-risk (docs, comments only).
|
||||
/// </summary>
|
||||
G0,
|
||||
|
||||
/// <summary>
|
||||
/// G1: Low risk (unit tests, 1 review).
|
||||
/// </summary>
|
||||
G1,
|
||||
|
||||
/// <summary>
|
||||
/// G2: Moderate risk (integration tests, code owner, canary).
|
||||
/// </summary>
|
||||
G2,
|
||||
|
||||
/// <summary>
|
||||
/// G3: High risk (security scan, migration plan, release captain).
|
||||
/// </summary>
|
||||
G3,
|
||||
|
||||
/// <summary>
|
||||
/// G4: Very high risk (formal review, extended canary, comms plan).
|
||||
/// </summary>
|
||||
G4
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builder for delta verdicts.
|
||||
/// </summary>
|
||||
public sealed class DeltaVerdictBuilder
|
||||
{
|
||||
private DeltaVerdictStatus _status = DeltaVerdictStatus.Pass;
|
||||
private DeltaGateLevel _gate = DeltaGateLevel.G1;
|
||||
private int _riskPoints;
|
||||
private readonly List<DeltaDriver> _blockingDrivers = [];
|
||||
private readonly List<DeltaDriver> _warningDrivers = [];
|
||||
private readonly List<string> _exceptions = [];
|
||||
private readonly List<string> _recommendations = [];
|
||||
private string? _explanation;
|
||||
|
||||
public DeltaVerdictBuilder WithStatus(DeltaVerdictStatus status)
|
||||
{
|
||||
_status = status;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeltaVerdictBuilder WithGate(DeltaGateLevel gate)
|
||||
{
|
||||
_gate = gate;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeltaVerdictBuilder WithRiskPoints(int points)
|
||||
{
|
||||
_riskPoints = points;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeltaVerdictBuilder AddBlockingDriver(DeltaDriver driver)
|
||||
{
|
||||
_blockingDrivers.Add(driver);
|
||||
_status = DeltaVerdictStatus.Fail;
|
||||
|
||||
// Escalate gate based on severity
|
||||
if (driver.Severity == DeltaDriverSeverity.Critical && _gate < DeltaGateLevel.G4)
|
||||
_gate = DeltaGateLevel.G4;
|
||||
else if (driver.Severity == DeltaDriverSeverity.High && _gate < DeltaGateLevel.G3)
|
||||
_gate = DeltaGateLevel.G3;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeltaVerdictBuilder AddWarningDriver(DeltaDriver driver)
|
||||
{
|
||||
_warningDrivers.Add(driver);
|
||||
if (_status == DeltaVerdictStatus.Pass)
|
||||
_status = DeltaVerdictStatus.Warn;
|
||||
|
||||
// Escalate gate for medium severity warnings
|
||||
if (driver.Severity >= DeltaDriverSeverity.Medium && _gate < DeltaGateLevel.G2)
|
||||
_gate = DeltaGateLevel.G2;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeltaVerdictBuilder AddException(string exceptionId)
|
||||
{
|
||||
_exceptions.Add(exceptionId);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeltaVerdictBuilder AddRecommendation(string recommendation)
|
||||
{
|
||||
_recommendations.Add(recommendation);
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeltaVerdictBuilder WithExplanation(string explanation)
|
||||
{
|
||||
_explanation = explanation;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeltaVerdict Build(string deltaId)
|
||||
{
|
||||
// If all blocking drivers are excepted, change to PassWithExceptions
|
||||
if (_status == DeltaVerdictStatus.Fail &&
|
||||
_blockingDrivers.Count > 0 &&
|
||||
_exceptions.Count >= _blockingDrivers.Count)
|
||||
{
|
||||
_status = DeltaVerdictStatus.PassWithExceptions;
|
||||
}
|
||||
|
||||
return new DeltaVerdict
|
||||
{
|
||||
VerdictId = $"dv:{Guid.NewGuid():N}",
|
||||
DeltaId = deltaId,
|
||||
EvaluatedAt = DateTimeOffset.UtcNow,
|
||||
Status = _status,
|
||||
RecommendedGate = _gate,
|
||||
RiskPoints = _riskPoints,
|
||||
BlockingDrivers = _blockingDrivers.ToList(),
|
||||
WarningDrivers = _warningDrivers.ToList(),
|
||||
AppliedExceptions = _exceptions.ToList(),
|
||||
Explanation = _explanation ?? GenerateExplanation(),
|
||||
Recommendations = _recommendations.ToList()
|
||||
};
|
||||
}
|
||||
|
||||
private string GenerateExplanation()
|
||||
{
|
||||
return _status switch
|
||||
{
|
||||
DeltaVerdictStatus.Pass => "No blocking changes detected",
|
||||
DeltaVerdictStatus.Warn => $"{_warningDrivers.Count} warning(s) detected",
|
||||
DeltaVerdictStatus.Fail => $"{_blockingDrivers.Count} blocking issue(s) detected",
|
||||
DeltaVerdictStatus.PassWithExceptions => $"Blocked by {_blockingDrivers.Count} issue(s), covered by exceptions",
|
||||
_ => "Unknown status"
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user