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>
4.1 KiB
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
- 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-SHA256t=..,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 body may be trusted blindly:
amountlower than the order total,currencyswapped (pay in a weak currency),status:"paid"/"completed"on an unpaid order,refunded:falseflips.- Does the server RE-FETCH the payment from the provider API by id, or believe the body?
- Try event-type confusion (
payment.succeededfor a $0 or unrelated order id you control).
4. Prove with a read-back
- 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. 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]
- Severity: Critical when it produces goods/credit without payment
- CWE: CWE-345 / CWE-347
- Endpoint: [callback URL]
- Request: [the forged event]
- Read-back: [the order showing as paid]
- 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. 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.