Date: 2026-06-17 Target: PHPNuxBill Paystack + Tripay gateways Verdict: forge REFUTED (defended); Paystack PII-log CONFIRMED.
the real bug is often the boring instrumentation beside it. Paystack's webhook correctly verifies signature +
server-bound amount + replay (forge blocked), but line 140 logs the raw webhook (PII + card metadata) to
pages/paystack-webhook.html - a WEB-ROOT file with no access control -> unauth PII disclosure. The fraud
was safe; the debug file_put_contents was the finding. Always check: where does the handler WRITE, and is
that path web-served?
body (Paystack: HMAC-sha512 of php://input with the secret) + bind amount/plan to a SERVER-created record, not client input. (b) IGNORE the callback body and RE-FETCH authoritative status from the gateway's API by reference (Tripay: transaction/detail -> recharge only if API says PAID). Both block forgery. The anti-patterns to hunt instead: trusting callback-body status/amount directly, taking recharge params (plan/user/amount) from the callback instead of the DB trx, missing replay-check, or an empty/optional signing secret (HMAC with '' key = forgeable - check for an empty-key guard).
pages/ had no .htaccess (only system/ +pages_template/ did). Any code writing attacker-or-PII data under a web-served dir = disclosure. Grep file_put_contents/fopen-w targets and cross-check against which dirs lack deny-all.
PAID plugin - but the handlers live in dedicated PUBLIC repos (hotspotbilling/phpnuxbill-tripay, Focuslinkstech/phpnuxbill-paystack-payment-gateway). When core security code is .gitignored, look for the dedicated plugin repos before concluding "not auditable."