$npx -y skills add hypnguyen1209/offensive-claude --skill finding-disciplineUse when about to record, claim, rate the severity of, or report any security finding — before marking anything [CONFIRMED] or writing it into the report
| 1 | # Finding Discipline |
| 2 | |
| 3 | ## Overview |
| 4 | |
| 5 | **The Iron Law: No `[CONFIRMED]` without proof.** A finding is a claim about real, demonstrated |
| 6 | impact — not a status code, a reflected string, or a hunch. This is the offensive equivalent of |
| 7 | test-driven development: the proof is the test, and the finding does not exist until it passes. |
| 8 | |
| 9 | **Violating the letter of this rule is violating its spirit.** |
| 10 | |
| 11 | ## The three tiers |
| 12 | |
| 13 | - **`[CONFIRMED]`** — impact demonstrated AND grounded in an evidence artifact that exists on disk. |
| 14 | - **`[POSSIBLE]`** — reachable but the class proof bar is not yet met. Keep digging; do not report as real. |
| 15 | - **`[INFO]`** — true but no security impact at the claimed severity. |
| 16 | |
| 17 | ## The proof bar (per class) |
| 18 | |
| 19 | A status code is not impact. See `skills/references/finding-evidence-standards.md`: |
| 20 | SSRF needs the internal response; IDOR needs *another principal's* data; RCE needs command output; |
| 21 | XSS needs script execution; open redirect needs an external destination. |
| 22 | |
| 23 | ## Required mechanical gate |
| 24 | |
| 25 | Before any finding is recorded or reported: |
| 26 | |
| 27 | 1. Set the structured proof signal and run |
| 28 | `python skills/vulnerability-analysis/scripts/validate_findings.py --findings f.json --evidence ./evidence` |
| 29 | — it rejects ungrounded findings and per-class false positives. |
| 30 | 2. Pass it through the **REQUIRED** `finding-validator` agent (PASS / KILL / DOWNGRADE). |
| 31 | 3. Only a `[CONFIRMED]` survivor goes in the report. Severity must match what was demonstrated (CVSS honest). |
| 32 | |
| 33 | See `skills/references/finding-validation-runtime.md` for the 7-question gate. |
| 34 | |
| 35 | ## Read-first, never name-guess |
| 36 | |
| 37 | If a function calls another, **read the callee** — do not infer what it does from its name. |
| 38 | `sanitize()`, `is_safe()`, `validate_input()` are exactly where vulnerabilities hide; a name is a |
| 39 | claim by the author, not evidence. The same applies to a config key, a decorator, or a CVE title: |
| 40 | open the thing before you reason about it. An unread dependency in a data-flow claim is a hole. |
| 41 | |
| 42 | ## Quote-grounded confidence tiers |
| 43 | |
| 44 | Every claim in a finding carries a confidence grounded in *what you can quote*, not in how it feels: |
| 45 | |
| 46 | - **High** — a **direct quote** from the artifact (the exact source line, the response body, the |
| 47 | decompiled instruction) supports the claim. |
| 48 | - **Medium** — an **explicitly stated assumption** bridges a gap you could not directly observe. |
| 49 | State the assumption; do not hide it. |
| 50 | - **Low** — an **inference** you are flagging as unverified. Acceptable to record, never to report as |
| 51 | fact. |
| 52 | |
| 53 | This is orthogonal to the `[CONFIRMED]/[POSSIBLE]/[INFO]` tier (which is about *impact*); confidence |
| 54 | is about *how well-grounded the claim is*. A High-confidence claim of a Low-impact bug is still Low. |
| 55 | |
| 56 | ## Red Flags — STOP, downgrade to `[POSSIBLE]` |
| 57 | |
| 58 | - "I'm sure it's exploitable" (but haven't shown impact) |
| 59 | - "The payload reflected, so it's XSS" / "I got a 200, so it works" |
| 60 | - "The DNS callback fired" (SSRF with no internal response) |
| 61 | - "I changed the id and got data" (but it was my own — self-IDOR) |
| 62 | - "It probably works on a real target" (default-deployment unproven) |
| 63 | |
| 64 | **All of these mean: it is `[POSSIBLE]`, not `[CONFIRMED]`. Get the evidence.** |
| 65 | |
| 66 | ## Rationalizations |
| 67 | |
| 68 | | Excuse | Reality | |
| 69 | |--------|---------| |
| 70 | | "Pattern-matched, clearly vulnerable" | Pattern ≠ exploit. Demonstrate impact or it's POSSIBLE. | |
| 71 | | "I'll attach evidence later" | No artifact on disk = ungrounded = REJECTED now. | |
| 72 | | "Blind RCE counts" | No output / no OOB confirmation = POSSIBLE, not CONFIRMED. | |
| 73 | | "Severity is obviously Critical" | CVSS must reflect demonstrated impact, not the worst case. | |
| 74 | | "The validator is overkill here" | Untested findings are how false positives ship. Run it. | |
| 75 | | "The function is called `sanitize`, so it's safe" | A name is the author's claim, not proof. Read the callee. | |
| 76 | | "The solver timed out, so it's not exploitable" | A tool limit is `feasibility:null` (manual), never `false`. | |
| 77 | |
| 78 | A short list of CONFIRMED findings beats a long list of POSSIBLEs. Killing a false positive is success. |