feat: Add native binary analyzer test utilities and implement SM2 signing tests
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Manifest Integrity / Audit SHA256SUMS Files (push) Has been cancelled
Manifest Integrity / Validate Schema Integrity (push) Has been cancelled
Manifest Integrity / Validate Contract Documents (push) Has been cancelled
Manifest Integrity / Validate Pack Fixtures (push) Has been cancelled
Manifest Integrity / Verify Merkle Roots (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled

- Introduced `NativeTestBase` class for ELF, PE, and Mach-O binary parsing helpers and assertions.
- Created `TestCryptoFactory` for SM2 cryptographic provider setup and key generation.
- Implemented `Sm2SigningTests` to validate signing functionality with environment gate checks.
- Developed console export service and store with comprehensive unit tests for export status management.
This commit is contained in:
StellaOps Bot
2025-12-07 13:12:41 +02:00
parent d907729778
commit e53a282fbe
387 changed files with 21941 additions and 1518 deletions

View File

@@ -0,0 +1,116 @@
namespace StellaOps.Scanner.Analyzers.Lang;
/// <summary>
/// Base record representing evidence of a capability usage in source code.
/// This provides a consistent structure across all language analyzers for
/// reporting detected capabilities.
/// </summary>
public record CapabilityEvidence
{
/// <summary>
/// Creates a new capability evidence instance.
/// </summary>
/// <param name="kind">The capability category.</param>
/// <param name="sourceFile">The source file path where the capability was detected.</param>
/// <param name="sourceLine">The line number of the detection.</param>
/// <param name="pattern">The function, API, or pattern that was matched.</param>
/// <param name="snippet">Optional code snippet for context.</param>
/// <param name="confidence">Confidence level (0.0 to 1.0).</param>
/// <param name="risk">Risk level of this usage.</param>
public CapabilityEvidence(
CapabilityKind kind,
string sourceFile,
int sourceLine,
string pattern,
string? snippet = null,
float confidence = 1.0f,
CapabilityRisk risk = CapabilityRisk.Low)
{
ArgumentException.ThrowIfNullOrWhiteSpace(sourceFile, nameof(sourceFile));
ArgumentException.ThrowIfNullOrWhiteSpace(pattern, nameof(pattern));
Kind = kind;
SourceFile = NormalizePath(sourceFile);
SourceLine = sourceLine;
Pattern = pattern;
Snippet = snippet;
Confidence = Math.Clamp(confidence, 0f, 1f);
Risk = risk;
}
/// <summary>
/// The capability category.
/// </summary>
public CapabilityKind Kind { get; }
/// <summary>
/// The source file where the capability is used (normalized to forward slashes).
/// </summary>
public string SourceFile { get; }
/// <summary>
/// The line number of the capability usage (1-based).
/// </summary>
public int SourceLine { get; }
/// <summary>
/// The function name, API, or pattern that was matched.
/// </summary>
public string Pattern { get; }
/// <summary>
/// Optional snippet of the code for context (may be truncated).
/// </summary>
public string? Snippet { get; }
/// <summary>
/// Confidence level from 0.0 (low) to 1.0 (high).
/// Lower confidence indicates pattern-based detection that may have false positives.
/// </summary>
public float Confidence { get; }
/// <summary>
/// Risk level associated with this capability usage.
/// </summary>
public CapabilityRisk Risk { get; }
/// <summary>
/// Creates a unique key for deduplication purposes.
/// </summary>
public string DeduplicationKey => $"{Kind}|{SourceFile}|{SourceLine}|{Pattern}";
/// <summary>
/// Creates metadata entries for SBOM generation.
/// </summary>
public virtual IEnumerable<KeyValuePair<string, string?>> CreateMetadata()
{
yield return new KeyValuePair<string, string?>("capability.kind", Kind.ToString().ToLowerInvariant());
yield return new KeyValuePair<string, string?>("capability.source", $"{SourceFile}:{SourceLine}");
yield return new KeyValuePair<string, string?>("capability.pattern", Pattern);
yield return new KeyValuePair<string, string?>("capability.risk", Risk.ToString().ToLowerInvariant());
yield return new KeyValuePair<string, string?>("capability.confidence", Confidence.ToString("F2", CultureInfo.InvariantCulture));
if (!string.IsNullOrWhiteSpace(Snippet))
{
// Truncate snippet to reasonable length for metadata
var truncated = Snippet.Length > 200 ? Snippet[..197] + "..." : Snippet;
yield return new KeyValuePair<string, string?>("capability.snippet", truncated);
}
}
/// <summary>
/// Creates a LanguageComponentEvidence from this capability evidence.
/// </summary>
public LanguageComponentEvidence ToLanguageEvidence()
{
return new LanguageComponentEvidence(
Kind: LanguageEvidenceKind.Metadata,
Source: SourceFile,
Locator: $"line:{SourceLine}",
Value: $"{Kind}:{Pattern}",
Sha256: null);
}
private static string NormalizePath(string path)
=> path.Replace('\\', '/');
}

View File

@@ -0,0 +1,110 @@
namespace StellaOps.Scanner.Analyzers.Lang;
/// <summary>
/// Categories of runtime capabilities that can be detected in source code.
/// These represent security-relevant functionality that may indicate potential
/// attack surface or require careful review.
/// </summary>
public enum CapabilityKind
{
/// <summary>
/// Command/process execution capabilities.
/// Examples: exec, spawn, ProcessBuilder, os/exec, Process.Start
/// </summary>
Exec,
/// <summary>
/// Filesystem operations including read, write, delete, and permission changes.
/// Examples: open, write, unlink, chmod, fs.readFile
/// </summary>
Filesystem,
/// <summary>
/// Network I/O including sockets, HTTP clients, and network listeners.
/// Examples: Socket, HttpClient, net.Dial, fetch
/// </summary>
Network,
/// <summary>
/// Environment variable access for reading or writing.
/// Examples: getenv, process.env, os.Getenv, Environment.GetEnvironmentVariable
/// </summary>
Environment,
/// <summary>
/// Object serialization and deserialization operations.
/// Examples: serialize/unserialize, ObjectInputStream, JSON.parse with reviver
/// </summary>
Serialization,
/// <summary>
/// Cryptographic operations including encryption, hashing, and signing.
/// Examples: AES, RSA, SHA256, crypto.*, openssl_*
/// </summary>
Crypto,
/// <summary>
/// Database access and query execution.
/// Examples: SQL queries, MongoDB operations, database/sql, SqlConnection
/// </summary>
Database,
/// <summary>
/// Dynamic code execution including eval and runtime code generation.
/// Examples: eval, Function(), DynamicMethod, ScriptEngine.eval
/// </summary>
DynamicCode,
/// <summary>
/// Reflection and runtime type introspection.
/// Examples: reflect.*, Type.GetMethod, Class.forName
/// </summary>
Reflection,
/// <summary>
/// Native code interop including FFI, P/Invoke, JNI, and CGO.
/// Examples: DllImport, import "C", System.loadLibrary, FFI::cdef
/// </summary>
NativeCode,
/// <summary>
/// File upload handling (web-specific).
/// Examples: $_FILES, move_uploaded_file, multipart handling
/// </summary>
Upload,
/// <summary>
/// Stream wrappers and protocol handlers.
/// Examples: php://, data://, custom URL schemes
/// </summary>
StreamWrapper,
/// <summary>
/// Session management and authentication state.
/// Examples: session_start, $_SESSION, express-session
/// </summary>
Session,
/// <summary>
/// Output control and HTTP response manipulation.
/// Examples: header, setcookie, ob_start with callback
/// </summary>
OutputControl,
/// <summary>
/// Error handling that may expose sensitive information.
/// Examples: phpinfo, stack trace exposure, error_reporting
/// </summary>
ErrorHandling,
/// <summary>
/// Plugin/module loading at runtime.
/// Examples: plugin.Open, Assembly.LoadFrom, dlopen
/// </summary>
PluginLoading,
/// <summary>
/// Language-specific capabilities not covered by other categories.
/// </summary>
Other
}

View File

@@ -0,0 +1,35 @@
namespace StellaOps.Scanner.Analyzers.Lang;
/// <summary>
/// Risk levels for capability usage.
/// Used to prioritize security review and flag potentially dangerous code patterns.
/// </summary>
public enum CapabilityRisk
{
/// <summary>
/// Low risk - common, safe usage patterns.
/// Examples: reading files with sanitized paths, standard logging.
/// </summary>
Low = 0,
/// <summary>
/// Medium risk - potentially dangerous in certain contexts.
/// Requires context-aware security review.
/// Examples: environment variable access, standard network operations.
/// </summary>
Medium = 1,
/// <summary>
/// High risk - requires careful security review.
/// Often involves untrusted input or sensitive operations.
/// Examples: dynamic assembly loading, reflection invocation, native code.
/// </summary>
High = 2,
/// <summary>
/// Critical risk - often associated with security vulnerabilities.
/// Should be flagged for immediate security review.
/// Examples: eval, command execution, unsafe deserialization.
/// </summary>
Critical = 3
}

View File

@@ -0,0 +1,233 @@
using System.Collections.Immutable;
namespace StellaOps.Scanner.Analyzers.Lang;
/// <summary>
/// Aggregates capability scan results from source code analysis.
/// Provides methods for querying and summarizing detected capabilities.
/// </summary>
public class CapabilityScanResult
{
private readonly IReadOnlyList<CapabilityEvidence> _evidences;
private ILookup<CapabilityKind, CapabilityEvidence>? _byKind;
private ILookup<CapabilityRisk, CapabilityEvidence>? _byRisk;
private ILookup<string, CapabilityEvidence>? _byFile;
/// <summary>
/// Creates a new capability scan result.
/// </summary>
public CapabilityScanResult(IReadOnlyList<CapabilityEvidence> evidences)
{
_evidences = evidences ?? Array.Empty<CapabilityEvidence>();
}
/// <summary>
/// All capability evidences found.
/// </summary>
public IReadOnlyList<CapabilityEvidence> Evidences => _evidences;
/// <summary>
/// Gets whether any capabilities were detected.
/// </summary>
public bool HasCapabilities => _evidences.Count > 0;
/// <summary>
/// Gets evidences grouped by capability kind.
/// </summary>
public ILookup<CapabilityKind, CapabilityEvidence> EvidencesByKind
=> _byKind ??= _evidences.ToLookup(e => e.Kind);
/// <summary>
/// Gets evidences grouped by risk level.
/// </summary>
public ILookup<CapabilityRisk, CapabilityEvidence> EvidencesByRisk
=> _byRisk ??= _evidences.ToLookup(e => e.Risk);
/// <summary>
/// Gets evidences grouped by source file.
/// </summary>
public ILookup<string, CapabilityEvidence> EvidencesByFile
=> _byFile ??= _evidences.ToLookup(e => e.SourceFile, StringComparer.OrdinalIgnoreCase);
/// <summary>
/// Gets all critical risk evidences.
/// </summary>
public IEnumerable<CapabilityEvidence> CriticalRiskEvidences
=> _evidences.Where(e => e.Risk == CapabilityRisk.Critical);
/// <summary>
/// Gets all high risk evidences.
/// </summary>
public IEnumerable<CapabilityEvidence> HighRiskEvidences
=> _evidences.Where(e => e.Risk == CapabilityRisk.High);
/// <summary>
/// Gets the set of detected capability kinds.
/// </summary>
public IReadOnlySet<CapabilityKind> DetectedKinds
=> _evidences.Select(e => e.Kind).ToHashSet();
/// <summary>
/// Gets the highest risk level found.
/// </summary>
public CapabilityRisk HighestRisk
=> _evidences.Count > 0
? _evidences.Max(e => e.Risk)
: CapabilityRisk.Low;
/// <summary>
/// Gets evidences for a specific capability kind.
/// </summary>
public IEnumerable<CapabilityEvidence> GetByKind(CapabilityKind kind)
=> EvidencesByKind[kind];
/// <summary>
/// Gets evidences at or above a specific risk level.
/// </summary>
public IEnumerable<CapabilityEvidence> GetByMinimumRisk(CapabilityRisk minRisk)
=> _evidences.Where(e => e.Risk >= minRisk);
/// <summary>
/// Creates metadata entries for the scan result.
/// </summary>
public virtual IEnumerable<KeyValuePair<string, string?>> CreateMetadata()
{
yield return new KeyValuePair<string, string?>(
"capability.total_count",
_evidences.Count.ToString(CultureInfo.InvariantCulture));
// Count by kind (only emit non-zero)
foreach (var kindGroup in EvidencesByKind.OrderBy(g => g.Key.ToString(), StringComparer.Ordinal))
{
yield return new KeyValuePair<string, string?>(
$"capability.{kindGroup.Key.ToString().ToLowerInvariant()}_count",
kindGroup.Count().ToString(CultureInfo.InvariantCulture));
}
// Count by risk
var criticalCount = CriticalRiskEvidences.Count();
var highCount = HighRiskEvidences.Count();
var mediumCount = _evidences.Count(e => e.Risk == CapabilityRisk.Medium);
var lowCount = _evidences.Count(e => e.Risk == CapabilityRisk.Low);
yield return new KeyValuePair<string, string?>("capability.critical_risk_count", criticalCount.ToString(CultureInfo.InvariantCulture));
yield return new KeyValuePair<string, string?>("capability.high_risk_count", highCount.ToString(CultureInfo.InvariantCulture));
yield return new KeyValuePair<string, string?>("capability.medium_risk_count", mediumCount.ToString(CultureInfo.InvariantCulture));
yield return new KeyValuePair<string, string?>("capability.low_risk_count", lowCount.ToString(CultureInfo.InvariantCulture));
// Highest risk
if (_evidences.Count > 0)
{
yield return new KeyValuePair<string, string?>(
"capability.highest_risk",
HighestRisk.ToString().ToLowerInvariant());
}
// Detected capabilities as semicolon-separated list
if (DetectedKinds.Count > 0)
{
yield return new KeyValuePair<string, string?>(
"capability.detected_kinds",
string.Join(';', DetectedKinds.OrderBy(k => k.ToString(), StringComparer.Ordinal).Select(k => k.ToString().ToLowerInvariant())));
}
// Files with critical issues (first 10)
var criticalFiles = CriticalRiskEvidences
.Select(e => e.SourceFile)
.Distinct(StringComparer.OrdinalIgnoreCase)
.OrderBy(f => f, StringComparer.Ordinal)
.ToList();
if (criticalFiles.Count > 0)
{
yield return new KeyValuePair<string, string?>(
"capability.critical_files",
string.Join(';', criticalFiles.Take(10)));
if (criticalFiles.Count > 10)
{
yield return new KeyValuePair<string, string?>(
"capability.critical_files_truncated",
"true");
}
}
// Unique patterns detected
var uniquePatterns = _evidences
.Select(e => e.Pattern)
.Distinct(StringComparer.OrdinalIgnoreCase)
.Count();
yield return new KeyValuePair<string, string?>(
"capability.unique_pattern_count",
uniquePatterns.ToString(CultureInfo.InvariantCulture));
}
/// <summary>
/// Creates a summary of detected capabilities.
/// </summary>
public CapabilitySummary CreateSummary()
{
return new CapabilitySummary(
HasExec: EvidencesByKind[CapabilityKind.Exec].Any(),
HasFilesystem: EvidencesByKind[CapabilityKind.Filesystem].Any(),
HasNetwork: EvidencesByKind[CapabilityKind.Network].Any(),
HasEnvironment: EvidencesByKind[CapabilityKind.Environment].Any(),
HasSerialization: EvidencesByKind[CapabilityKind.Serialization].Any(),
HasCrypto: EvidencesByKind[CapabilityKind.Crypto].Any(),
HasDatabase: EvidencesByKind[CapabilityKind.Database].Any(),
HasDynamicCode: EvidencesByKind[CapabilityKind.DynamicCode].Any(),
HasReflection: EvidencesByKind[CapabilityKind.Reflection].Any(),
HasNativeCode: EvidencesByKind[CapabilityKind.NativeCode].Any(),
HasUpload: EvidencesByKind[CapabilityKind.Upload].Any(),
HasSession: EvidencesByKind[CapabilityKind.Session].Any(),
CriticalCount: CriticalRiskEvidences.Count(),
HighRiskCount: HighRiskEvidences.Count(),
TotalCount: _evidences.Count);
}
/// <summary>
/// Empty scan result with no capabilities detected.
/// </summary>
public static CapabilityScanResult Empty { get; } = new(Array.Empty<CapabilityEvidence>());
}
/// <summary>
/// Summary of detected capabilities as boolean flags.
/// </summary>
public sealed record CapabilitySummary(
bool HasExec,
bool HasFilesystem,
bool HasNetwork,
bool HasEnvironment,
bool HasSerialization,
bool HasCrypto,
bool HasDatabase,
bool HasDynamicCode,
bool HasReflection,
bool HasNativeCode,
bool HasUpload,
bool HasSession,
int CriticalCount,
int HighRiskCount,
int TotalCount)
{
/// <summary>
/// Creates metadata entries for the summary.
/// </summary>
public IEnumerable<KeyValuePair<string, string?>> CreateMetadata()
{
yield return new KeyValuePair<string, string?>("capability.has_exec", HasExec.ToString().ToLowerInvariant());
yield return new KeyValuePair<string, string?>("capability.has_filesystem", HasFilesystem.ToString().ToLowerInvariant());
yield return new KeyValuePair<string, string?>("capability.has_network", HasNetwork.ToString().ToLowerInvariant());
yield return new KeyValuePair<string, string?>("capability.has_environment", HasEnvironment.ToString().ToLowerInvariant());
yield return new KeyValuePair<string, string?>("capability.has_serialization", HasSerialization.ToString().ToLowerInvariant());
yield return new KeyValuePair<string, string?>("capability.has_crypto", HasCrypto.ToString().ToLowerInvariant());
yield return new KeyValuePair<string, string?>("capability.has_database", HasDatabase.ToString().ToLowerInvariant());
yield return new KeyValuePair<string, string?>("capability.has_dynamic_code", HasDynamicCode.ToString().ToLowerInvariant());
yield return new KeyValuePair<string, string?>("capability.has_reflection", HasReflection.ToString().ToLowerInvariant());
yield return new KeyValuePair<string, string?>("capability.has_native_code", HasNativeCode.ToString().ToLowerInvariant());
yield return new KeyValuePair<string, string?>("capability.has_upload", HasUpload.ToString().ToLowerInvariant());
yield return new KeyValuePair<string, string?>("capability.has_session", HasSession.ToString().ToLowerInvariant());
}
}

View File

@@ -0,0 +1,164 @@
namespace StellaOps.Scanner.Analyzers.Lang;
/// <summary>
/// Interface for language-specific capability scanners.
/// Implementations detect security-relevant capabilities in source code files.
/// </summary>
public interface ICapabilityScanner
{
/// <summary>
/// Gets the language identifier (e.g., "go", "dotnet", "java", "node", "php").
/// </summary>
string LanguageId { get; }
/// <summary>
/// Gets the file extensions this scanner can process (e.g., ".go", ".cs", ".java", ".js").
/// </summary>
IReadOnlySet<string> SupportedExtensions { get; }
/// <summary>
/// Scans source code content for capability usage.
/// </summary>
/// <param name="content">The source code content.</param>
/// <param name="filePath">The path to the source file (for reporting).</param>
/// <returns>List of detected capability evidences.</returns>
IReadOnlyList<CapabilityEvidence> ScanContent(string content, string filePath);
/// <summary>
/// Determines if this scanner can process the given file.
/// </summary>
/// <param name="filePath">The file path to check.</param>
/// <returns>True if this scanner can process the file.</returns>
bool CanScan(string filePath)
{
var extension = Path.GetExtension(filePath);
return !string.IsNullOrEmpty(extension) &&
SupportedExtensions.Contains(extension.ToLowerInvariant());
}
}
/// <summary>
/// Defines a capability detection pattern with associated metadata.
/// Used by scanners to configure what patterns to look for.
/// </summary>
/// <param name="Pattern">The regex or literal pattern to match.</param>
/// <param name="Kind">The capability kind this pattern detects.</param>
/// <param name="Risk">The risk level associated with matches.</param>
/// <param name="Confidence">Base confidence for matches (0.0-1.0).</param>
/// <param name="Description">Human-readable description of what this detects.</param>
/// <param name="IsRegex">Whether Pattern is a regex (true) or literal match (false).</param>
public sealed record CapabilityPattern(
string Pattern,
CapabilityKind Kind,
CapabilityRisk Risk,
float Confidence = 1.0f,
string? Description = null,
bool IsRegex = true);
/// <summary>
/// Helper class for building capability patterns.
/// </summary>
public static class CapabilityPatterns
{
/// <summary>
/// Creates a critical risk exec pattern.
/// </summary>
public static CapabilityPattern CriticalExec(string pattern, string? description = null)
=> new(pattern, CapabilityKind.Exec, CapabilityRisk.Critical, 1.0f, description);
/// <summary>
/// Creates a high risk exec pattern.
/// </summary>
public static CapabilityPattern HighExec(string pattern, string? description = null)
=> new(pattern, CapabilityKind.Exec, CapabilityRisk.High, 1.0f, description);
/// <summary>
/// Creates a critical risk dynamic code pattern.
/// </summary>
public static CapabilityPattern CriticalDynamicCode(string pattern, string? description = null)
=> new(pattern, CapabilityKind.DynamicCode, CapabilityRisk.Critical, 1.0f, description);
/// <summary>
/// Creates a high risk native code pattern.
/// </summary>
public static CapabilityPattern HighNativeCode(string pattern, string? description = null)
=> new(pattern, CapabilityKind.NativeCode, CapabilityRisk.High, 1.0f, description);
/// <summary>
/// Creates a critical risk native code pattern (unsafe operations).
/// </summary>
public static CapabilityPattern CriticalNativeCode(string pattern, string? description = null)
=> new(pattern, CapabilityKind.NativeCode, CapabilityRisk.Critical, 1.0f, description);
/// <summary>
/// Creates a critical risk serialization pattern (unsafe deserialization).
/// </summary>
public static CapabilityPattern CriticalSerialization(string pattern, string? description = null)
=> new(pattern, CapabilityKind.Serialization, CapabilityRisk.Critical, 1.0f, description);
/// <summary>
/// Creates a medium risk serialization pattern.
/// </summary>
public static CapabilityPattern MediumSerialization(string pattern, string? description = null)
=> new(pattern, CapabilityKind.Serialization, CapabilityRisk.Medium, 0.9f, description);
/// <summary>
/// Creates a medium risk filesystem pattern.
/// </summary>
public static CapabilityPattern MediumFilesystem(string pattern, string? description = null)
=> new(pattern, CapabilityKind.Filesystem, CapabilityRisk.Medium, 0.9f, description);
/// <summary>
/// Creates a high risk filesystem pattern.
/// </summary>
public static CapabilityPattern HighFilesystem(string pattern, string? description = null)
=> new(pattern, CapabilityKind.Filesystem, CapabilityRisk.High, 1.0f, description);
/// <summary>
/// Creates a medium risk network pattern.
/// </summary>
public static CapabilityPattern MediumNetwork(string pattern, string? description = null)
=> new(pattern, CapabilityKind.Network, CapabilityRisk.Medium, 0.9f, description);
/// <summary>
/// Creates a medium risk database pattern.
/// </summary>
public static CapabilityPattern MediumDatabase(string pattern, string? description = null)
=> new(pattern, CapabilityKind.Database, CapabilityRisk.Medium, 0.9f, description);
/// <summary>
/// Creates a high risk database pattern (raw SQL).
/// </summary>
public static CapabilityPattern HighDatabase(string pattern, string? description = null)
=> new(pattern, CapabilityKind.Database, CapabilityRisk.High, 0.95f, description);
/// <summary>
/// Creates a medium risk environment pattern.
/// </summary>
public static CapabilityPattern MediumEnvironment(string pattern, string? description = null)
=> new(pattern, CapabilityKind.Environment, CapabilityRisk.Medium, 0.9f, description);
/// <summary>
/// Creates a low risk crypto pattern.
/// </summary>
public static CapabilityPattern LowCrypto(string pattern, string? description = null)
=> new(pattern, CapabilityKind.Crypto, CapabilityRisk.Low, 0.9f, description);
/// <summary>
/// Creates a medium risk reflection pattern.
/// </summary>
public static CapabilityPattern MediumReflection(string pattern, string? description = null)
=> new(pattern, CapabilityKind.Reflection, CapabilityRisk.Medium, 0.85f, description);
/// <summary>
/// Creates a high risk reflection pattern.
/// </summary>
public static CapabilityPattern HighReflection(string pattern, string? description = null)
=> new(pattern, CapabilityKind.Reflection, CapabilityRisk.High, 0.95f, description);
/// <summary>
/// Creates a high risk plugin loading pattern.
/// </summary>
public static CapabilityPattern HighPluginLoading(string pattern, string? description = null)
=> new(pattern, CapabilityKind.PluginLoading, CapabilityRisk.High, 1.0f, description);
}

View File

@@ -3,6 +3,7 @@ global using System.Collections.Concurrent;
global using System.Collections.Generic;
global using System.Collections.Immutable;
global using System.Diagnostics.CodeAnalysis;
global using System.Globalization;
global using System.IO;
global using System.Linq;
global using System.Text.Json;

View File

@@ -5,7 +5,7 @@
<LangVersion>preview</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>