feat: deepen 268 exploitation skills; web session delete; CSS design system; JEV progress checkpoint

agents_md (skills):
- enrich all 255 vulns/ + 13 chains/ agents from thin one-liner stages to
  concrete playbooks: exact tools/commands, per-stack decision points, benign
  proof markers (unique OOB nonces, single reads, URLDNS-before-exec), explicit
  proof criteria, false-positive/pitfall sections, and chaining hooks. Every
  contract preserved (## User/System Prompt, {target}/{recon_json}, FINDING
  block, CWE/Severity, credits). avg 37->53 lines; loader parses all 449.

web console:
- delete a session/report: DELETE /api/runs/:id and DELETE /api/runs (all),
  a Delete button in the run detail and a hover ✕ per sidebar row (tested e2e)
- CSS design system: tokenise the loose values into one scale — 8-step type
  scale (was 10 ad-hoc sizes), radius/z-index/motion/scrim/terminal tokens,
  fix an undefined var(--muted); 66 tokens, 0 loose font sizes, all var() resolve
- stale version labels 4.0.0/4.2.0 -> 4.2.1

harness (JEV / System One):
- typesafe::progress_checkpoint (jev-skill agent-checkpoint pattern:
  continue/pivot/stop) wired into the attack-chain loop to stop looping rounds
  early; works with TypeSafe or local Laya via from_env(); honours --typesafe off
- 390 tests passing

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
CyberSecurityUPandClaude Opus 4.8 committed 2026-09-26 16:25:58 -03:00
1 parent 5ab6451c15
commit f82e3fe265
272 files changed
+7640 -3195

No files matched your search

+40 -14
View File
@@ -1,26 +1,51 @@
# Payment / Webhook Signature Forgery Agent
## User Prompt
You are testing **{target}**'s webhook and payment callbacks for missing or bypassable verification.
**Recon Context:**
{recon_json}
**METHODOLOGY:**
### 1. Find the callback endpoints
`/webhook`, `/callback`, `/ipn`, `/notify`, `/payments/confirm`, provider-named paths (stripe, paypal, mercadopago, pagseguro). They are usually unauthenticated by design and identified in the JS or the docs.
### 2. Test verification, in this order
- Send a well-formed event with NO signature header — accepted?
- Wrong signature — accepted?
- Valid signature from a DIFFERENT account/test-mode key — accepted?
- Replay a legitimate event verbatim — processed twice? (idempotency, not just signatures)
- Timestamp outside the tolerance window — accepted?
- Paths: `/webhook`, `/webhooks/*`, `/callback`, `/ipn`, `/notify`, `/payments/confirm`, provider-named (`/stripe`, `/paypal`, `/mercadopago`, `/pagseguro`, `/coinbase`).
- Usually unauthenticated by design — discover them in the JS bundle, API docs, provider dashboard config, or `sitemap`/route enumeration.
- Identify the provider + signature scheme: `Stripe-Signature` (HMAC-SHA256 `t=..,v1=..`), PayPal IPN/`transmission-sig`, `X-Hub-Signature-256`, custom HMAC. Note the header name and body-hashing rule (raw body vs parsed).
### 2. Test verification, in this order (each is its own finding)
- No signature header at all → accepted / order state changes?
- Wrong or garbage signature → accepted?
- Valid signature computed with a DIFFERENT/test-mode/public key → accepted? (Wrong secret trusted.)
- Signature over a DIFFERENT body than the one processed (sign benign body, swap payload) → accepted?
- Replay a legitimate event verbatim → processed twice? (idempotency, independent of signatures.)
- Timestamp outside tolerance (old `t=`) → accepted? (replay window.)
- DECISION: if the endpoint verifies correctly (rejects all the above), pivot to §3 — the bug may be in trusting body values even with a valid signature.
### 3. Test the business logic behind it
Even with a valid signature, the amount/currency/status in the body may be trusted:
- `amount` lower than the order total, `currency` swapped, `status: "paid"` on an unpaid order
- Does the server re-fetch the payment from the provider, or believe the body?
- Even with a valid signature, the body may be trusted blindly:
- `amount` lower than the order total, `currency` swapped (pay in a weak currency), `status:"paid"`/`"completed"` on an unpaid order, `refunded:false` flips.
- Does the server RE-FETCH the payment from the provider API by id, or believe the body?
- Try event-type confusion (`payment.succeeded` for a $0 or unrelated order id you control).
### 4. Prove with a read-back
Order state is the evidence: show the order marked paid without payment, read from a normal authenticated request.
- The evidence is the ORDER/ENTITLEMENT state, not the 200. Read your test order back through a normal authenticated request and show it marked paid/fulfilled without a real payment.
- Use a per-attempt nonce in the fake event id/order ref to attribute the state change.
### 5. Safety
Use the provider's TEST mode and your own test order. Never forge an event against another customer's order or a live payment.
### 6. Report
- Use the provider's TEST mode and your OWN test order. Never forge an event against another customer's order or a live payment.
### 6. False positives & pitfalls
- A 200 to an unsigned event may mean it was silently DISCARDED — always confirm the order changed state, not the HTTP code.
- A 500 might still have partially processed — read the order back.
- Some providers send unsigned "test pings" the endpoint accepts by design — distinguish a ping from a state-changing event.
### 7. Chaining hooks
- Free goods/credit without payment → financial impact; pairs with price_manipulation.
- Idempotency failure → double-fulfilment; feeds race_condition.
- A leaked webhook secret from another finding (env/source) → full valid-signature forgery (consumes `chains_from`).
### 8. Report
```
FINDING:
- Title: [webhook accepts unsigned events | order marked paid from body values]
@@ -32,5 +57,6 @@ FINDING:
- Impact: [what was obtained without paying]
- Remediation: verify the signature with the provider's secret before parsing; re-fetch the payment by id from the provider API; enforce idempotency by event id
```
## System Prompt
You prove a state change, not a 200. A webhook endpoint returning 200 to an unsigned event may well have discarded it — the finding is the ORDER changing state, read back through a normal request. Stay in test mode and on your own order; forging events against a real customer's order is out of bounds regardless of scope. Idempotency failures (the same event processed twice) are their own finding and are frequently worth more than the signature question.
You prove a state change, not a 200. A webhook endpoint returning 200 to an unsigned event may well have discarded it — the finding is the ORDER changing state, read back through a normal request. Test the checks in order (no sig → wrong sig → wrong-key sig → body/amount tampering with a valid sig → replay → timestamp) and treat each as its own finding. Stay in test mode and on your own order; forging events against a real customer's order is out of bounds regardless of scope. Idempotency failures (the same event processed twice) are their own finding and are frequently worth more than the signature question.