# Pentest

> Penetration-testing discipline for authorized security assessment. Load to audit a codebase or system you own (or are explicitly authorized to test) for vulnerabilities - then fix them with secure. Also covers scoped engagements: red-team exercises, CTFs, bug-bounty targets. Covers confirming authorization and scope first, mapping the attack surface, testing methodically against a threat model, proving findings with safe repro, controlling blast radius, reporting for the defender, and closing the find-fix-confirm loop with secure and verify. This is offensive testing to make systems safer; it is the counterpart to secure (writing safe code).

- Skill: `angad-kandhari/pentest` (Agent Skill)
- Install (CLI): `npx skillmds@latest add angad-kandhari/pentest`
- Raw SKILL.md: https://api.skillmd.com/api/skills/angad-kandhari/pentest/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: angad-kandhari (https://skillmd.com/u/angad-kandhari)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/angad-kandhari/pentest

---


# Pentest

Penetration-testing skill for LLM coding agents doing *authorized* security assessment.

The common case: point it at **your own project's codebase** to find vulnerabilities, then fix each one with [`secure`](../secure/SKILL.md) and confirm the hole is closed with [`verify`](../verify/SKILL.md). The same discipline scales to scoped engagements — red-team exercises, CTFs, bug-bounty targets, or a running system you have written permission to test.

Where [`secure`](../secure/SKILL.md) keeps the code you *write* safe, this skill *hunts* for the holes that got in anyway — proves they're real, and hands each one to `secure` to fix. Think of them as a loop: **pentest finds, secure fixes, verify confirms.** Counters the failure modes of undisciplined testing — probing without authorization, thrashing without a model, "findings" that don't reproduce, and testing that damages the system it was meant to protect.

---

## 0. Authorization Is the Precondition, Not a Formality

**Authorized targets only. The gate scales with the target — but it's always a gate.**

- **Your own code or system:** authorization is satisfied by ownership. Audit freely — this is the everyday case, and the rest of this skill is written for it.
- **Anything you don't own** — a third-party service, a shared or production environment with real users' data, a client's system, a bug-bounty target: you need explicit, current, written authorization that names *this* target, plus the rules of engagement (in-scope hosts/accounts, allowed techniques, testing window, contact). Get it before the first probe. "Probably fine" is not authorization.
- When in doubt about whether a target is yours to test, treat it as out of scope until you've confirmed otherwise.

**Test:** Do I own this target, or can I point to the authorization that covers it?

---

## 1. Map the Surface Before You Probe It

**Understand the terrain first — whether that terrain is a codebase or a live host.**

When auditing your own code (the common case), the source *is* the recon:

- Trace every place untrusted data enters: request handlers, form fields, query params, headers, file uploads, webhooks, message queues, CLI args.
- Follow each input to where it lands — the injection sinks: SQL/query builders, shell/`exec` calls, file-path construction, HTML/template rendering, deserializers, `eval`-equivalents.
- Inventory the trust boundaries: where does auth get checked, where do roles get enforced, where does the client hand off to the server?
- Grep for the usual suspects: hardcoded secrets, disabled TLS verification, permissive CORS, `admin`/service credentials, `TODO: security`.

When testing a running system, enumerate the live surface too — hosts, ports, endpoints, versions, third-party components — reading public intel before any loud probing.

**Test:** Can I list this system's entry points, injection sinks, and trust boundaries before I attempt the first exploit?

---

## 2. Test Against a Threat Model, Not a Checklist

**Aim testing at what actually matters for this system.**

- State what you're trying to reach: the crown-jewel data, the privilege you want to escalate to, the boundary you want to cross.
- Prioritize by impact × likelihood, not by tool output volume. A scanner's 200 "info" findings are noise next to one real auth bypass.
- Work the categories that fit the surface — access control, injection, auth/session, business logic, misconfiguration, secrets exposure — and skip the ones that don't apply.
- Follow the chain: a low-severity foothold that leads to a high-severity pivot is the finding, not either half alone.

**Test:** For each thing I'm testing, can I name the asset or privilege at risk if it fails?

---

## 3. Prove It — A Finding Reproduces or It Isn't One

**A vulnerability you can't demonstrate on demand is a hypothesis.**

- Establish a reliable repro: exact request, payload, preconditions, and observed result. The same standard as [`debug`](../debug/SKILL.md) §1.
- Capture evidence as you go: the request/response, the returned data, the screenshot, the timestamp. You'll need it for the report and you may not get a second window.
- Prove impact with the *minimum* necessary action. Demonstrate read access with one benign record, not a full dump. Prove code execution with a harmless marker, not a payload that persists.
- Distinguish confirmed from suspected. "This endpoint reflects input unsanitized (confirmed); it may be exploitable for stored XSS (unverified)" is an honest finding.

**Test:** Could the defender reproduce this from my write-up alone, and did I prove it with the least intrusive action that works?

---

## 4. Control the Blast Radius

**The system under test is still someone's system. Don't be the incident.**

- Prefer the least destructive proof at every step. Never run a technique whose downside you can't predict on a live target.
- No denial-of-service, no data destruction, no mass or automated actions against real users, no lateral movement outside scope — unless the rules of engagement explicitly authorize it and you understand the consequence.
- Watch what you leave behind: test accounts, uploaded files, altered records, shells. Track every artifact so you can prove clean-up.
- On production, stay conservative — throttle, test off-peak where required, and stop the moment you see instability you didn't intend.

**Test:** If this action goes worse than expected, what's the maximum damage — and can I justify that risk against the rules of engagement?

---

## 5. Know When to Stop and Surface

**Some findings can't wait for the final report.**

- A critical, actively-exploitable issue (exposed customer data, remote code execution, leaked live credentials) gets reported to the engagement contact *immediately*, not saved for the deliverable. Same escalation instinct as [`incident`](../incident/SKILL.md) §6.
- If you find evidence the system is *already* compromised by someone else, stop and escalate — you're now next to a real incident.
- If a test starts causing unintended impact, stop first, report second. Don't dig the hole deeper trying to clean it up live.
- Don't chase rabbit holes past the point of value. Three failed approaches at the same boundary is a signal to move on or reassess ([`deliberate`](../deliberate/SKILL.md) §7).

**Test:** Have I found anything that's dangerous enough to report before the engagement ends?

---

## 6. Report for the Defender

**The deliverable isn't the exploit. It's the fix that ships because of it.**

A finding the team can act on includes:

- **What** — the vulnerability, in one clear sentence.
- **Where** — exact location: endpoint, parameter, component, version.
- **Proof** — the reproduction steps and evidence, minimal and exact.
- **Impact** — what an attacker gains, concretely. Not "possible security risk" — "an unauthenticated user can read any other user's records."
- **Severity** — rated by real impact and exploitability, calibrated ([`deliberate`](../deliberate/SKILL.md) §8), not inflated to pad the report.
- **Remediation** — a specific, actionable fix, and where the [`secure`](../secure/SKILL.md) principle it violates would have caught it.

Sort by severity, lead with what must be fixed now, and separate confirmed from suspected. A pile of unranked scanner output is not a pentest report.

**Test:** Could an engineer fix the highest-severity finding using only my write-up?

---

## 7. Close the Loop — Find, Fix, Confirm

**On your own codebase, the finding isn't done until the hole is closed and proven closed.**

When you're auditing code you own, don't stop at the report — run each finding through the loop:

1. **Fix with [`secure`](../secure/SKILL.md).** Every finding maps to a principle it violated: bypassed control, unvalidated boundary, leaked secret, over-broad permission. Apply that fix — at the root, and to the *class* of the bug, not just the one instance ([`debug`](../debug/SKILL.md) §6). If the SQL injection exists in one query, the same pattern is probably in three more.
2. **Confirm with [`verify`](../verify/SKILL.md).** Re-run the exact repro from §3 against the fixed code. The exploit that worked before must now fail. A fix you haven't re-tested is a hypothesis, not a fix.
3. **Leave a regression test.** Turn the repro into a test that fails on the vulnerable code and passes on the fixed code, so the hole can't silently reopen ([`test`](../test/SKILL.md)).

Fix in priority order — the highest-severity, most-exploitable finding first. Don't let a pile of low-severity nits delay the one auth bypass that matters.

**Test:** For each finding I fixed, does the original exploit now fail, and is there a test that will catch it if it comes back?

---

## 8. Handle Findings Responsibly

**What you discover is sensitive. Treat it that way.**

- Keep findings, evidence, and any accessed data within the engagement's agreed channels. Don't paste live vulnerabilities or real data into public tools, issues, or chats.
- Follow the program's disclosure terms and timeline. For bug bounties and coordinated disclosure, that means giving the owner time to fix before going public — never dropping a live exploit.
- Delete or securely hand over any sensitive data you accessed once the engagement is done.
- Findings are for making the system safer, not for leverage, resale, or unauthorized use. If a request pushes past authorized testing toward causing harm, stop.

**Test:** Is every vulnerability and piece of data I'm holding flowing only through the channels the engagement authorized?

---

## These Guidelines Are Working If

- Testing only ever runs against targets you own or are authorized to test.
- Findings reproduce on demand and are proven with the least intrusive action that works.
- On your own codebase, every finding gets fixed with `secure`, confirmed with `verify`, and locked in with a regression test.
- Nothing under test breaks, leaks, or persists because of the assessment.
- Critical issues get surfaced immediately, not buried in a final report.
- Findings lead with severity and hand back a fix, not just an exploit.

---

*Part of [Deliberate](https://github.com/angad-kandhari/deliberate). The offensive counterpart to [`secure`](../secure/SKILL.md) — pentest finds the holes, secure fixes them, [`verify`](../verify/SKILL.md) confirms them closed. Load alongside [`deliberate`](../deliberate/SKILL.md) for authorized security assessment only.*

