Add comprehensive security tests for OWASP A02, A05, A07, and A08 categories
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Findings Ledger CI / build-test (push) Has been cancelled
Findings Ledger CI / migration-validation (push) Has been cancelled
Findings Ledger CI / generate-manifest (push) Has been cancelled
Manifest Integrity / Validate Schema Integrity (push) Has been cancelled
Lighthouse CI / Lighthouse Audit (push) Has been cancelled
Lighthouse CI / Axe Accessibility Audit (push) Has been cancelled
Manifest Integrity / Validate Contract Documents (push) Has been cancelled
Manifest Integrity / Validate Pack Fixtures (push) Has been cancelled
Manifest Integrity / Audit SHA256SUMS Files (push) Has been cancelled
Manifest Integrity / Verify Merkle Roots (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled

- Implemented tests for Cryptographic Failures (A02) to ensure proper handling of sensitive data, secure algorithms, and key management.
- Added tests for Security Misconfiguration (A05) to validate production configurations, security headers, CORS settings, and feature management.
- Developed tests for Authentication Failures (A07) to enforce strong password policies, rate limiting, session management, and MFA support.
- Created tests for Software and Data Integrity Failures (A08) to verify artifact signatures, SBOM integrity, attestation chains, and feed updates.
This commit is contained in:
master
2025-12-16 16:40:19 +02:00
parent 415eff1207
commit 2170a58734
206 changed files with 30547 additions and 534 deletions

View File

@@ -0,0 +1,165 @@
using Microsoft.Extensions.Logging;
namespace StellaOps.Scanner.Reachability.Gates;
/// <summary>
/// Interface for gate detectors.
/// </summary>
public interface IGateDetector
{
/// <summary>The type of gate this detector finds.</summary>
GateType GateType { get; }
/// <summary>Detects gates in the given call path.</summary>
Task<IReadOnlyList<DetectedGate>> DetectAsync(
CallPathContext context,
CancellationToken cancellationToken = default);
}
/// <summary>
/// Context for gate detection on a call path.
/// </summary>
public sealed record CallPathContext
{
/// <summary>Symbols in the call path from entry to vulnerability.</summary>
public required IReadOnlyList<string> CallPath { get; init; }
/// <summary>Source files associated with each symbol (if available).</summary>
public IReadOnlyDictionary<string, string>? SourceFiles { get; init; }
/// <summary>AST or CFG data for deeper analysis (optional).</summary>
public object? AstData { get; init; }
/// <summary>Language of the code being analyzed.</summary>
public required string Language { get; init; }
}
/// <summary>
/// Composite gate detector that orchestrates all individual detectors.
/// SPRINT_3405_0001_0001 - Task #7
/// </summary>
public sealed class CompositeGateDetector
{
private readonly IReadOnlyList<IGateDetector> _detectors;
private readonly GateMultiplierConfig _config;
private readonly ILogger<CompositeGateDetector> _logger;
public CompositeGateDetector(
IEnumerable<IGateDetector> detectors,
GateMultiplierConfig? config = null,
ILogger<CompositeGateDetector>? logger = null)
{
_detectors = detectors?.ToList() ?? throw new ArgumentNullException(nameof(detectors));
_config = config ?? GateMultiplierConfig.Default;
_logger = logger ?? Microsoft.Extensions.Logging.Abstractions.NullLogger<CompositeGateDetector>.Instance;
if (_detectors.Count == 0)
{
_logger.LogWarning("CompositeGateDetector initialized with no detectors");
}
}
/// <summary>
/// Detects all gates in the given call path using all registered detectors.
/// </summary>
public async Task<GateDetectionResult> DetectAllAsync(
CallPathContext context,
CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(context);
if (context.CallPath.Count == 0)
{
return GateDetectionResult.Empty;
}
var allGates = new List<DetectedGate>();
// Run all detectors in parallel
var tasks = _detectors.Select(async detector =>
{
try
{
var gates = await detector.DetectAsync(context, cancellationToken);
return gates;
}
catch (Exception ex)
{
_logger.LogWarning(ex,
"Gate detector {DetectorType} failed for path with {PathLength} symbols",
detector.GateType, context.CallPath.Count);
return Array.Empty<DetectedGate>();
}
});
var results = await Task.WhenAll(tasks);
foreach (var gates in results)
{
allGates.AddRange(gates);
}
// Deduplicate gates by symbol+type
var uniqueGates = allGates
.GroupBy(g => (g.GuardSymbol, g.Type))
.Select(g => g.OrderByDescending(x => x.Confidence).First())
.OrderByDescending(g => g.Confidence)
.ToList();
// Calculate combined multiplier
var combinedMultiplier = CalculateCombinedMultiplier(uniqueGates);
_logger.LogDebug(
"Detected {GateCount} gates on path, combined multiplier: {Multiplier}bps",
uniqueGates.Count, combinedMultiplier);
return new GateDetectionResult
{
Gates = uniqueGates,
CombinedMultiplierBps = combinedMultiplier,
};
}
/// <summary>
/// Calculates the combined multiplier for all detected gates.
/// Gates are multiplicative: auth(30%) * feature_flag(20%) = 6%
/// </summary>
private int CalculateCombinedMultiplier(IReadOnlyList<DetectedGate> gates)
{
if (gates.Count == 0)
{
return 10000; // 100% - no reduction
}
// Start with 100% (10000 bps)
double multiplier = 10000.0;
// Group gates by type and take the lowest multiplier per type
// (multiple auth gates don't stack, but auth + feature_flag do)
var gatesByType = gates
.GroupBy(g => g.Type)
.Select(g => g.Key);
foreach (var gateType in gatesByType)
{
var typeMultiplier = GetMultiplierForType(gateType);
multiplier = multiplier * typeMultiplier / 10000.0;
}
// Apply floor
var result = (int)Math.Round(multiplier);
return Math.Max(result, _config.MinimumMultiplierBps);
}
private int GetMultiplierForType(GateType type)
{
return type switch
{
GateType.AuthRequired => _config.AuthRequiredMultiplierBps,
GateType.FeatureFlag => _config.FeatureFlagMultiplierBps,
GateType.AdminOnly => _config.AdminOnlyMultiplierBps,
GateType.NonDefaultConfig => _config.NonDefaultConfigMultiplierBps,
_ => 10000, // Unknown gate type - no reduction
};
}
}