diff --git a/capabilities/dotnet-reversing/skills/dotnet-reversing/SKILL.md b/capabilities/dotnet-reversing/skills/dotnet-reversing/SKILL.md index 208de2e..9767a33 100644 --- a/capabilities/dotnet-reversing/skills/dotnet-reversing/SKILL.md +++ b/capabilities/dotnet-reversing/skills/dotnet-reversing/SKILL.md @@ -5,6 +5,9 @@ description: Use when reverse engineering .NET assemblies, decompiling DLLs/EXEs # .NET Reverse Engineering +Load the `vuln-assessment-methodology` skill alongside this one for severity +calibration, disprove-first discipline, and reporting standards. + ## Quick Start ``` @@ -61,17 +64,27 @@ Use `dotnet_search_by_name` for name-based searches and `dotnet_search_reference - **XML (XXE):** `XmlReader`, `XmlDocument`, `XDocument`, `XmlTextReader` - **LDAP:** `DirectorySearcher`, `DirectoryEntry`, `System.DirectoryServices` -### Phase 3: Decompile Suspicious Code +### Phase 3: Decompile and Verify ``` dotnet_decompile_type(path="App.dll", type_name="App.Services.AuthenticationService") ``` -Read the actual C# source. Look for: +Read the actual C# source. When you find a dangerous pattern, **read the full +function and its callers** before drawing conclusions. Check for: - Hardcoded credentials - Weak crypto (MD5, SHA1, DES, static IVs/keys) -- SQL string concatenation +- SQL string concatenation — **but check if the concatenated value comes from + user input (HTTP param) vs config/env var. Only HTTP-sourced values are high severity.** - Unsanitized user input in file paths - Dangerous deserialization -- Command injection +- Command injection — **but check if the calling function has validation/filtering. + If validation exists, look for bypasses rather than reporting "no sanitization."** + +#### .NET-specific: JWT ReadToken is not always a finding + +`ReadToken`/`ReadJwtToken` without `ValidateToken` is NOT a vulnerability when +the token is validated by a downstream service (Azure AD, ARM) or used only for +metadata extraction (expiry, caching). Only report it when unvalidated claims +drive authorization decisions. ### Phase 4: Trace Attack Paths ``` @@ -83,13 +96,32 @@ dotnet_get_call_flows( ``` Find how vulnerable methods are reached from entry points (controllers, handlers, public APIs). -### Phase 5: Report Findings +### Phase 5: Assess Severity and Report + +Assign severity based on actual exploitability — not the vulnerability class +name. The `vuln-assessment-methodology` skill has the full guidance; the +essentials: + +| Source of dangerous input | Access required | Severity | +|---|---|---| +| HTTP request parameter | Unauthenticated, internet-facing | Critical/High | +| HTTP request parameter | Authenticated user | High/Medium | +| HTTP request parameter | Internal network only | Medium | +| Config file / env var | Container or host access | Low | +| Hardcoded value (as sink input) | N/A | Not a finding (but hardcoded credentials are — see methodology skill) | + +**Before reporting every finding:** +- Trace the data flow from attacker-controlled source to sink +- Actively try to disprove it — look for validation, encoding, authorization +- If defensive code exists, demonstrate a specific bypass or retract +- Verify severity reflects exploitability, not vulnerability class name + ``` report_finding( file="App.dll", method="AuthService.ValidateToken", - criticality="high", - content="Hardcoded JWT secret found:\n```csharp\nprivate static string Secret = \"supersecret123\";\n```" + criticality="critical", + content="Hardcoded JWT signing secret in source code:\n```csharp\nprivate static string Secret = \"supersecret123\";\n```" ) report_auth(auth_material="API key in config: `sk-1234567890abcdef`") @@ -100,53 +132,112 @@ finish_task(success=True, markdown_summary="Found 2 high-severity issues...") ``` Always report findings to persist them to the Dreadnode platform. -## Common Vulnerability Patterns +## .NET Vulnerability Patterns: Vulnerable vs Safe + +For each pattern, both vulnerable AND safe versions are shown. You must +check which one the code matches before reporting. ### Hardcoded Credentials ```csharp -// Look for string literals in auth code +// VULNERABLE — real secret in source code private static string ApiKey = "sk-1234567890abcdef"; connectionString = "Server=db;User=admin;Password=P@ssw0rd"; + +// NOT A FINDING — loaded from config/env +var apiKey = Configuration["ApiKey"]; +var connStr = Environment.GetEnvironmentVariable("DB_CONNECTION"); + +// NOT A FINDING — misleading error message (not a real credential) +throw new Exception("Api Key is invalid. Subscription validation failed."); ``` ### Insecure Deserialization ```csharp -// BinaryFormatter = RCE +// VULNERABLE — BinaryFormatter with untrusted input BinaryFormatter formatter = new BinaryFormatter(); -object obj = formatter.Deserialize(stream); // VULNERABLE +object obj = formatter.Deserialize(untrustedStream); -// Type-controlling JSON deserialization +// VULNERABLE — TypeNameHandling enables type control JsonConvert.DeserializeObject(json, new JsonSerializerSettings { - TypeNameHandling = TypeNameHandling.All // VULNERABLE + TypeNameHandling = TypeNameHandling.All }); + +// SAFE — System.Text.Json (no type handling by default) +var obj = JsonSerializer.Deserialize(json); + +// SAFE — TypeNameHandling.None (default) +JsonConvert.DeserializeObject(json); ``` ### Command Injection ```csharp -// User input in process arguments -Process.Start("cmd.exe", "/c " + userInput); // VULNERABLE +// VULNERABLE — direct interpolation +Process.Start("cmd.exe", "/c " + userInput); +Arguments = $"-c \"{command} {string.Join(" ", args)}\""; + +// PARTIALLY SAFE — has validation, but check for bypasses +var error = ValidateCommand(command); // blocks ; && || | etc. +if (error != null) return error; +// If ValidateCommand misses characters like " or ${ }, it's +// an incomplete validation bypass (Medium), not "no sanitization" (High) + +// SAFE — no shell, direct exec with argument array +Process.Start("myapp", new[] { "--flag", sanitizedValue }); ``` -### Path Traversal +### SQL Injection ```csharp -// Unsanitized path concatenation -string path = Path.Combine(baseDir, userFileName); // VULNERABLE if userFileName = "../../../etc/passwd" -File.ReadAllText(path); +// VULNERABLE — user input concatenated into SQL +string query = "SELECT * FROM users WHERE id = " + request.UserId; + +// LOW RISK — env var / config value concatenated (defense-in-depth issue) +// Attacker needs container access to control env var +string proc = "[" + schemaFromEnvVar + "].[MyProcedure]"; + +// SAFE — parameterized query +cmd.CommandText = "SELECT * FROM users WHERE id = @id"; +cmd.Parameters.AddWithValue("@id", userId); ``` -### SQL Injection +### Blazor XSS (MarkupString) +```csharp +// VULNERABLE — user input directly cast to MarkupString +builder.AddContent(0, (MarkupString)userInput); + +// SAFE — HtmlEncoded BEFORE MarkupString cast +var encoded = WebUtility.HtmlEncode(userInput); +var colored = AnsiParser.ConvertToHtml(encoded, state); // adds tags +builder.AddContent(0, (MarkupString)colored); // MarkupString needed for spans + +// SAFE — Markdown pipeline with HTML disabled +pipeline.DisableHtml(); +var html = Markdown.ToHtml(input, pipeline); +builder.AddContent(0, (MarkupString)html); +``` + +### JWT Validation ```csharp -// String concatenation in queries -string query = "SELECT * FROM users WHERE id = " + userId; // VULNERABLE -cmd.CommandText = query; +// VULNERABLE — claims trusted for local authorization +var token = new JwtSecurityTokenHandler().ReadJwtToken(jwt); +if (token.Claims.First(c => c.Type == "role").Value == "admin") + GrantAdminAccess(); // No signature verification! + +// SAFE — token read for metadata, validated by downstream service +var token = handler.ReadJwtToken(jwt); +var expiry = token.ValidTo; // Just extracting expiry for caching +return DelegatedTokenCredential.Create(jwt); // Azure AD validates the sig ``` -### Weak Cryptography +### Path Traversal ```csharp -// Deprecated algorithms -MD5.Create().ComputeHash(data); // Weak hash -DES.Create(); // Weak cipher -new RijndaelManaged { Mode = CipherMode.ECB }; // Weak mode +// VULNERABLE — user input in path without validation +string path = Path.Combine(baseDir, userFileName); +File.ReadAllText(path); + +// SAFE — canonicalization check with trailing separator +string normalizedBase = Path.GetFullPath(baseDir) + Path.DirectorySeparatorChar; +string full = Path.GetFullPath(Path.Combine(baseDir, userFileName)); +if (!full.StartsWith(normalizedBase)) throw new SecurityException(); ``` ## Critical Rules @@ -154,15 +245,14 @@ new RijndaelManaged { Mode = CipherMode.ECB }; // Weak mode **DO:** - Always start with `dotnet_scan_binaries` to find targets - Use `dotnet_decompile_type` for targeted analysis (not `dotnet_decompile_module`) -- Report ALL findings with `report_finding` — even low-severity ones -- Use `report_auth` immediately when you find credentials +- Report all verified findings with `report_finding` — even low-severity ones +- Use `report_auth` only for real credentials, not error messages or placeholders - Call `finish_task` when analysis is complete **DO NOT:** +- Report `ReadToken`/`ReadJwtToken` as "JWT bypass" when the token is validated server-side +- Report `MarkupString` as XSS when the content is `HtmlEncode`d upstream - Use `dotnet_decompile_module` on large assemblies — it will overflow context -- Skip reporting — findings must be persisted to the platform -- Analyze only one assembly — check ALL binaries in the target directory -- Ignore Microsoft/System assemblies completely — they can have vulnerabilities too ## Tips diff --git a/capabilities/dotnet-reversing/skills/mcr-analysis/SKILL.md b/capabilities/dotnet-reversing/skills/mcr-analysis/SKILL.md index d5ff938..9f09030 100644 --- a/capabilities/dotnet-reversing/skills/mcr-analysis/SKILL.md +++ b/capabilities/dotnet-reversing/skills/mcr-analysis/SKILL.md @@ -5,7 +5,11 @@ description: Use when analyzing .NET applications from Microsoft Container Regis # MCR Container Image Analysis -Extract and analyze .NET assemblies from Microsoft Container Registry images without executing any container code. Uses pure HTTP—no Docker required. +Extract and analyze .NET assemblies from Microsoft Container Registry images +without executing any container code. Uses pure HTTP—no Docker required. + +Load the `vuln-assessment-methodology` skill alongside this one for severity +calibration, disprove-first discipline, and reporting standards. ## When to Use MCR Tools @@ -44,6 +48,20 @@ dotnet_scan_binaries(path="~/workspace/mcr/dotnet_aspnet_8.0") # analyze | `azure-functions/*` | Azure Functions runtime | | `appsvc/*` | Azure App Service images | +Use `mcr_search_repositories` to discover repos beyond these — the catalog has +~3,200 entries across Azure services, infrastructure, and tooling. + +## Not All MCR Images Are .NET + +Many MCR images use Go, Python, TypeScript, or Rust. Extraction will return +"No .NET assemblies found" for these. This is common for infrastructure and +networking components (CNI plugins, proxies, tunnels, AI/ML runtimes). + +If extraction fails: +1. Try `dll_only=false` — some images use AOT compilation or non-standard layouts +2. Try a different platform (`linux/arm64` vs `linux/amd64`) +3. Accept that the image may not contain .NET code and move on + ## Workflow ### 1. Find the Target Image @@ -78,21 +96,71 @@ dotnet_search_references(path="~/workspace/mcr/.../TargetAssembly.dll", search=" For app images (`appsvc/*`, `azure-functions/*`), prioritize assemblies under `/app/` over runtime DLLs. For runtime images (`dotnet/runtime`, `dotnet/aspnet`), target `System.Private.CoreLib.dll` or `Microsoft.AspNetCore.dll` directly. +## MCR-Specific Attack Surface + +When analyzing assemblies extracted from MCR images, look for these in addition +to standard .NET vulnerability patterns: + +1. **ONNX/ML model loading** — Path traversal in model file paths +2. **ANSI/terminal parsers** — Escape sequence injection breaking HTML context +3. **Protobuf/gRPC handling** — Oversized message DoS, recursive depth bombs +4. **URL parsers** — Scheme bypass, authority confusion, attribute breakout + +## Prioritizing MCR Repos for Security Analysis + +Not all MCR repos are equally interesting. Prioritize: + +**Highest value:** +- New products/services (few tags, v0.x/v1.x — less mature, less audited) +- API gateways and reverse proxies (parse untrusted HTTP — smuggling, injection) +- Auth/identity services (JWT, certificate, token handling) +- Database access layers (SQL injection, query injection) +- AI/ML services (model loading, prompt handling, inference pipelines) + +**Medium value:** +- Emulators (often have weaker auth than production counterparts) +- Internal/SRE tools (may rely on network isolation instead of auth) +- Monitoring/observability dashboards (render untrusted telemetry data) + +**Lower value:** +- Mature Microsoft runtime images (dotnet/runtime, dotnet/aspnet — heavily audited) +- Helm charts and Bicep modules (infrastructure-as-code, not runtime code) +- Build tools and SDKs (not typically internet-facing) + +## Delegating Analysis to Subagents + +When dispatching subagents to analyze extracted assemblies: + +1. **Load the analysis guidance** — ensure subagents have both the + `dotnet-reversing` and `vuln-assessment-methodology` skills loaded +2. **Tell them what NOT to report** — share known false-positive patterns + from previous analysis of similar codebases +3. **Specify the application assemblies** — list the non-framework DLLs + explicitly so they don't waste time on Microsoft.AspNetCore.* etc. +4. **Set threat model context** — tell them if the target is public-facing, + internal, or a dev tool so they assign severity appropriately +5. **Require disproof attempts** — instruct subagents to try to disprove + each finding before reporting it + ## Critical Rules **DO:** - Always use `mcr_list_tags` before `mcr_pull_and_extract` to pick the right version - Use specific version tags (e.g., `8.0.25`) not floating tags (`8.0`, `latest`) - After extraction, immediately run `dotnet_scan_binaries` on the output directory -- Prioritize `/app/` assemblies over runtime assemblies when analyzing app images +- Prioritize `/app/` or `/emulator/` assemblies over runtime assemblies +- Check tag counts and version numbers to gauge maturity (few tags = newer = less audited) **DO NOT:** -- Skip the extraction step and try to analyze MCR URLs directly — you must extract first +- Skip the extraction step and try to analyze MCR URLs directly - Use `latest` tag for security analysis — it changes over time -- Forget to note the output directory path from `mcr_pull_and_extract` +- Assume extraction failure means the image is empty — it may not be .NET +- Dispatch subagents without the analysis guidance loaded ## Tips - **Version pinning**: Use specific tags like `8.0.25` instead of `8.0` or `latest` for reproducibility - **Cache reuse**: Repeated extractions of the same image skip the download - **Large images**: SDK images are huge (~800MB); prefer runtime/aspnet images when possible +- **Parallel extraction**: Extract multiple images simultaneously while waiting for results +- **Cross-reference tags**: Repos with very few tags or only `latest` are brand new — potentially less audited diff --git a/capabilities/vuln-assessment-methodology/capability.yaml b/capabilities/vuln-assessment-methodology/capability.yaml new file mode 100644 index 0000000..f99fe4a --- /dev/null +++ b/capabilities/vuln-assessment-methodology/capability.yaml @@ -0,0 +1,27 @@ +schema: 1 +name: vuln-assessment-methodology +version: "1.0.0" +description: > + Cross-cutting methodology for vulnerability assessment. Provides + source-to-sink tracing discipline, disprove-first analysis, + threat-model-aware severity assignment, three-tier confidence + classification, attack chain analysis, CWE mapping, remediation + quality standards, root-cause deduplication, scope documentation, + and opt-in proof-of-concept validation. Load alongside any + domain-specific security capability to reduce false positives + and severity inflation. + +author: + name: Dreadnode + url: https://dreadnode.io +license: MIT +repository: https://github.com/dreadnode/capabilities +keywords: + - vulnerability-assessment + - methodology + - security + - false-positive-prevention + - severity-calibration + - confidence-levels + - cwe + - remediation diff --git a/capabilities/vuln-assessment-methodology/skills/vuln-assessment-methodology/SKILL.md b/capabilities/vuln-assessment-methodology/skills/vuln-assessment-methodology/SKILL.md new file mode 100644 index 0000000..b25258b --- /dev/null +++ b/capabilities/vuln-assessment-methodology/skills/vuln-assessment-methodology/SKILL.md @@ -0,0 +1,149 @@ +--- +name: vuln-assessment-methodology +description: "Load when performing vulnerability assessment in any domain. Enforces source-to-sink tracing, disprove-first analysis, threat-model-aware severity, confidence classification, attack chain analysis, CWE mapping, remediation quality, root-cause deduplication, scope documentation, and opt-in PoC validation. Prevents false positives and severity inflation." +--- + +# Vulnerability Assessment Methodology + +**The goal is accurate, honest findings — not volume.** One correctly-assessed +finding is worth more than ten inflated ones. + +## Hard Rules + +### 1. NEVER report a sink without tracing the full data flow + +Seeing a dangerous function is NOT a finding. Trace from **attacker-controlled +source** through every transformation to the sink. If sanitization exists, the +finding is invalid unless you demonstrate a specific bypass. + +**Before reporting, answer:** +- What is the attacker-controlled input? +- What transformations does it undergo? +- Does any transformation neutralize the attack? +- Can you construct a concrete input that reaches the sink? + +### 2. Try to DISPROVE your finding before reporting it + +Actively look for evidence it is NOT exploitable. Read the FULL function. Look +for validation, input filtering, authorization checks, type constraints, +config gates. If you find defensive code, demonstrate a bypass or retract. + +### 3. Severity must reflect the ACTUAL threat model + +Assign severity by source, access, and context — not vulnerability class name. + +| Source of dangerous input | Access required | Severity | +|---|---|---| +| HTTP request param | Unauthenticated, internet-facing | Critical/High | +| HTTP request param | Authenticated user | High/Medium | +| HTTP request param | Internal network only | Medium | +| Config/env var | Container-level access | Low | +| Hardcoded value (as sink input) | N/A | Not a finding (but hardcoded credentials are — actual secrets, not placeholders or example values) | + +**What each level requires:** +- **Critical**: Unauth RCE, hardcoded prod credentials, full auth bypass. Attacker needs nothing beyond a network connection. +- **High**: Authed RCE, SQL injection via HTTP params, stored XSS, SSRF from internet-facing endpoint. +- **Medium**: Incomplete validation bypass, internal-only exposure, defense-in-depth gaps. +- **Low**: Defense-in-depth issues (env var in SQL), code quality that could become exploitable. +- **Not a finding**: Complete upstream sanitization, config-as-designed, token parsed for metadata only, framework defaults, attacker already needs higher privileges. + +### 4. Read the COMPLETE defensive code + +If validation exists but is incomplete (e.g., blocks `;` but not `"`), report +the **specific bypass**, not "no sanitization." Severity reflects the bypass +narrowness, not unrestricted injection impact. + +- BAD: "Command injection via bash -c with no sanitization" (HIGH) +- GOOD: "Incomplete validation in ValidateCommand() — misses `\"`, allowing + quote-escape from bash -c wrapping" (MEDIUM) + +### 5. Configuration options are not vulnerabilities + +Dev mode / unsecured mode is a design decision unless attacker-toggleable. + +### 6. Internal tools have different threat models + +Report missing auth on internal tools as a **dependency on network controls**, +not "missing security." Don't assign CRITICAL unless evidence shows internet +exposure. + +### 7. AI prompt injection is a design concern, not a code bug + +Not a code vulnerability unless AI output feeds a security-sensitive sink +(e.g., `eval()`, SQL, shell commands, file paths, unencoded HTML). + +### 8. Distinguish application code from framework code + +Don't report framework defaults as vulnerabilities. + +### 9. Flag obvious attack chains — do not force them + +When multiple findings converge on a single exploitable outcome, note the +chain. An IDOR + information disclosure + missing rate limiting may each be +Medium alone but chain to account takeover. Report the chain as an additional +compound finding with its own severity reflecting the combined impact — keep +the individual findings too, since each needs its own remediation. Do not +exhaustively search for chains — flag them when apparent from findings already +identified. + +## Confidence Levels + +Every finding must include a confidence level. When the full source-to-sink +trace is complete, mark it Confirmed. When it is not, classify the gap. + +| Level | Criteria | Documentation required | +|---|---|---| +| Confirmed | Full trace complete, concrete payload constructable | Complete data flow from source to sink with specific input | +| Probable | Most of trace complete, specific gap identified | State the exact gap (e.g., "dynamic dispatch at line 42 — two implementors exist, both pass input unsanitized") | +| Suspected | Pattern match or shallow trace only | State what additional analysis (dynamic testing, debug tracing, etc.) would confirm or refute | + +Common trace gaps: dynamic dispatch, reflection, external dependencies, plugin +systems, runtime-generated code. Always name the specific mechanism that +blocked the trace. + +## Reporting Standards + +Reports must: +- State access prerequisites explicitly +- Note existing defensive code and why it's insufficient +- Map each finding to the most specific applicable CWE ID (leaf-level variant, + not the pillar — e.g., CWE-89 not CWE-74) +- Include specific, actionable remediation referencing the technology in use + and the code location where the fix applies (not "add input validation" but + "use parameterized queries via `db.Query()` with placeholder args at + `handler.go:47`") +- When multiple findings share a root cause, report one root-cause finding + with a list of affected locations rather than separate findings per instance +- State what was analyzed and what was not — files, components, and entry + points covered, plus what could not be assessed (runtime behavior, + infrastructure config, third-party dependency internals) +- Be defensible under peer review by a senior security engineer + +## Proof-of-Concept Validation (Opt-in) + +Default behavior is to trace data flow and assess exploitability conceptually. +Do not construct payloads or simulate execution unless the user requests it. + +If the user requests proof-of-concept validation: +- Construct a concrete payload that demonstrates the vulnerability +- Document exact attacker-controlled input values +- Show the code path execution trace from source to sink +- State environmental prerequisites (auth state, config, timing) +- For web targets: provide the specific HTTP request that triggers the issue + +## Anti-patterns + +| Anti-pattern | Example | Why it's wrong | +|---|---|---| +| Sink-only analysis | "Dangerous function found → vuln" | Didn't check upstream defenses | +| Ignoring defensive code | "Injection, no sanitization" when validation exists | Didn't read the full function | +| Class-name severity | "SQL injection → HIGH" regardless of source | Env var source ≠ HTTP param source | +| Feature-as-vulnerability | "Unsecured mode exists" | Documented design decision | +| Framework noise | "Framework uses cookies" | Expected framework behavior | +| Theoretical-only | "If attacker could modify env vars..." | Attacker already has code exec | +| Quantity over quality | 10 low-confidence findings | 1 verified > 10 guesses | +| Context-free severity | "No auth → CRITICAL" on internal tool | Deployment model matters | +| Confirmation bias | Rationalizing why mitigations don't count | Try to disprove first | +| Forced chaining | "These 3 lows chain to Critical" without shared attack flow | Chain must converge on a single exploitable outcome, not just co-exist | +| Generic remediation | "Add input validation" | Must name specific fix and code location | +| Duplicate inflation | 15 separate XSS findings from one missing encoder | One root cause = one finding + affected locations | diff --git a/capabilities/web-security/agents/web-security.md b/capabilities/web-security/agents/web-security.md index 6916180..0065228 100644 --- a/capabilities/web-security/agents/web-security.md +++ b/capabilities/web-security/agents/web-security.md @@ -111,6 +111,9 @@ Do not use tools mechanically. Pick the smallest tool that can validate the next ## Evidence Standards +Load the `vuln-assessment-methodology` skill for the severity matrix, disprove-first +discipline, and reporting standards that apply across all vulnerability assessment. + When you find a vulnerability, your report will be reviewed by a senior pentester. Weak evidence leads to rejection. **Required evidence:** diff --git a/capabilities/web-security/skills/vuln-critic/SKILL.md b/capabilities/web-security/skills/vuln-critic/SKILL.md index 6efb712..1c1a8d1 100644 --- a/capabilities/web-security/skills/vuln-critic/SKILL.md +++ b/capabilities/web-security/skills/vuln-critic/SKILL.md @@ -5,7 +5,9 @@ description: Adversarial pre-filter for scanner and agent findings. Scores findi # Vulnerability Critic (Pre-Verification Filter) -Adversarial review agent inspired by Co-RedTeam's critic architecture. Runs BEFORE exploit-verifier to filter findings and save testing time. +Adversarial review agent inspired by Co-RedTeam's critic architecture. Runs BEFORE +exploit-verifier to filter findings and save testing time. Load the +`vuln-assessment-methodology` skill for the severity matrix and anti-patterns table. **This skill does NOT test vulnerabilities.** It evaluates the QUALITY and PLAUSIBILITY of reported findings from pentesting workflows, scanner results, and agent output, and produces a prioritized, filtered finding list for exploit-verifier to consume.