Skip to content

fix(parsing): reject Payment-Receipt with a non-success status - #30

Open
ygd58 wants to merge 1 commit into
stripe:mainfrom
ygd58:fix/receipt-status-validation
Open

ygd58 wants to merge 1 commit into
stripe:mainfrom
ygd58:fix/receipt-status-validation

Conversation

@ygd58

@ygd58 ygd58 commented Sep 4, 2026

Copy link
Copy Markdown

What

parsePaymentReceipt checked that the status field was present but never validated its value, so a receipt with status="failed" (or any other string) parsed successfully into a usable Receipt object. Canonical mppx defines receipt status as the literal value "success" and validates that during deserialization — this SDK's own Receipt class matches that design (the only constructor that sets status is Receipt.success(...), which hardcodes "success"), but the parser didn't enforce it on the read side, so a malicious or buggy server could return a protocol-invalid error-like receipt that this SDK would still hand back to the caller as if it were a valid successful payment.

Flagged by the cross-SDK audit as AGR-2026-086. /ag fix isn't available for this repo since it's outside Agricola's write scope.

Fix

Add a check right after the existing null check: reject with ParseException if status isn't exactly "success".

Testing

Adds receiptParseRejectsNonSuccessStatus, following the same pattern as the existing receiptParseRejectsMissingMethod/receiptParseRejectsInvalidMethodId tests in this file — an otherwise well-formed receipt with status="failed" must throw ParseException rather than parse.

As with my other PRs, I couldn't compile/run this against the real dependencies in my sandbox (no Maven Central access) — please double-check compilation before merge, happy to fix anything that doesn't match.

Fixes tempoxyz/mpp-tools#208

parsePaymentReceipt checked that the status field was present but
never validated its value, so a receipt with status="failed" (or any
other string) parsed successfully into a usable Receipt object.
Canonical mppx defines receipt status as the literal value "success"
and validates that during deserialization -- this SDK's own Receipt
class matches that design (the only constructor that sets status is
Receipt.success(...), which hardcodes "success"), but the parser
didn't enforce it on the read side, so a malicious or buggy server
could return a protocol-invalid error-like receipt that this SDK would
still hand back to the caller as if it were a valid successful
payment.

Add a check right after the existing null check: reject with
ParseException if status isn't exactly "success".

Adds receiptParseRejectsNonSuccessStatus, following the same pattern
as the existing receiptParseRejectsMissingMethod /
receiptParseRejectsInvalidMethodId tests in this file -- an otherwise
well-formed receipt with status="failed" must throw ParseException
rather than parse.

As with my other PRs, I could not compile/run this against the real
dependencies in my sandbox (no Maven Central access) -- please
double-check compilation before merge.

Fixes tempoxyz/mpp-tools#208 (AGR-2026-086)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Agricola] AGR-2026-086: Non-success receipts are accepted

1 participant