vuln-assessment-methodology · git:20260606.6e4aac6 · 2026-06-06 · sha256 11caf455ba4e3363
vuln-assessment-methodology git:20260606.6e4aac6A
Immutable. This exact content is served forever at /api/v1/blob/11caf455ba4e3363.
--- 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, and finding quality standards. 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 `eval()`, SQL, or 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 a separate compound finding with its own severity reflecting the combined impact. 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 share a target flow, 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 |