# Exploit Hunt

> Use when hunting for actually-exploitable vulnerabilities — reachable, user-controlled paths into a real sink (SSRF, SQLi, command injection, RCE, deserialization, path traversal, XSS), discarding theoretical or local-only noise. Offensive triage, the counterpart to security-bar's defensive checklist.

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

---


# exploit-hunt

## Overview

The offensive counterpart to `eskills:security-bar`. security-bar asks _"is this built
right?"_; this asks _"can an attacker actually reach a sink?"_. Use it for a deeper, on-demand
pass on a codebase — not as a per-task lens. It is **not** in the default `eskills:task-flow`
quality stage; reach for it when a change touches a real boundary, or when auditing an app
end-to-end.

## The principle

**Unreachable is not a finding.** A theoretically-unsafe call that no external input can
reach is a note, not a vulnerability. Prove that user-controlled input travels from a real
boundary to a meaningful sink — or drop it. Bias hard toward remotely reachable, user-driven
paths; throw away the rest.

## In scope — prove user control reaches the sink

| Pattern                                                       | CWE     | Impact                                    |
| ------------------------------------------------------------- | ------- | ----------------------------------------- |
| SSRF via user-controlled URL                                  | 918     | internal network, cloud metadata theft    |
| Auth bypass in middleware / API guards                        | 287     | unauthorized account or data access       |
| Remote deserialization / upload→RCE                           | 502     | code execution                            |
| SQL injection in a reachable endpoint                         | 89      | exfiltration, auth bypass, data loss      |
| Command injection in a request handler                        | 78      | code execution                            |
| Path traversal in file-serving paths                          | 22      | arbitrary file read/write                 |
| Auto-triggered XSS                                            | 79      | session/admin compromise                  |
| Open RLS / PostgREST direct write reachable with the anon key | 284/639 | read/overwrite any row, bypassing the app |

## Skip these — low signal, drop them

- Local-only `pickle.loads` / `torch.load` / equivalent with no remote path
- `eval()` / `exec()` in CLI-only tooling
- `shell=True` on a fully hardcoded command
- Missing security headers on their own
- Generic rate-limiting complaints with no exploit impact
- Self-XSS that needs the victim to paste code manually
- Demo, example, fixture, vendored, or test-only code

## My stack: where the real boundary is

The React/PWA UI is **not** the boundary. My apps ship the Supabase anon key, so the real
attack surface is **PostgREST + Edge Functions / RPCs** — anything reachable with that key is
a public API, regardless of what the UI exposes. So:

- Treat every table reachable via the anon key as a public, unauthenticated endpoint. A guard
  that lives only in front-end code does not exist for an attacker (see `eskills:security-bar`
  for the RLS / server-side-PIN rules this feeds).
- The sinks that matter are server-side: an RPC that builds dynamic SQL, an Edge Function that
  fetches a user-supplied URL (SSRF) or shells out, a storage path built from user input.

## Workflow

1. **Map entrypoints** — HTTP handlers, RPCs, Edge Functions, upload paths, webhooks,
   background jobs, parsers, any table exposed through PostgREST.
2. **Trace reachability** — follow user-controlled input from the boundary inward.
3. **Find the sink** — does that input reach SQL, a shell, a URL fetch, a deserializer, a
   file path, the DOM?
4. **Prove it** — confirm user control reaches the sink with the smallest safe PoC (a single
   request or `curl` against PostgREST is usually enough).
5. **Triage tooling as input only** — `semgrep --config=auto --severity=ERROR --severity=WARNING`
   to seed candidates, then manually drop the unreachable / test / vendored hits.

## Output

Per finding: `file:line → reachability (which boundary, which input) → what the attacker
achieves → the fix`, plus the minimal PoC. State the boundary explicitly — if you can't name
how it's reached, it goes in a separate "theoretical / needs-confirmation" list, not the
findings. Don't re-report an already-accepted, documented risk.

