Skip to content

feat: request body digest binding#300

Closed
brendanjryan wants to merge 1 commit intobrendan/binding-semantics-hardeningfrom
brendan/replayable-request-digest-binding
Closed

feat: request body digest binding#300
brendanjryan wants to merge 1 commit intobrendan/binding-semantics-hardeningfrom
brendan/replayable-request-digest-binding

Conversation

@brendanjryan
Copy link
Copy Markdown
Collaborator

@brendanjryan brendanjryan commented Apr 6, 2026

Summary

Binds the HTTP request body to the payment challenge via SHA-256 digest, preventing replay attacks where a credential issued for one request body is presented with a different body.

Changes

  • src/server/Transport.ts: HTTP transport's captureRequest now reads body bytes and computes a bodyDigest (sha-256=...). Added safeBodyBytes helper for graceful body extraction.
  • src/server/Mppx.ts: Passes capturedRequest.bodyDigest as the challenge's digest field (HMAC-bound via the 6-slot binding: realm|method|intent|request|expires|digest). After HMAC and scope verification pass, verifies the echoed challenge's digest matches the current request body digest.
  • Graceful degradation: GET/bodiless requests omit the digest entirely — no enforcement when both sides have no body.

Verification flow

1. Client sends POST with body → server computes sha-256 digest, includes in challenge HMAC
2. Client echoes challenge back with credential
3. Server recomputes digest from current body, compares to echoed challenge digest
4. Mismatch → 402 with "request body does not match challenge digest"

Tests added

  • Challenge includes sha-256=... digest when request has a body
  • Challenge omits digest when request has no body
  • Rejects credential when body changes between challenge and verification
  • Accepts credential when body matches between challenge and verification
  • GET request without body still works (no digest)

Stack

PR 3 of 3 in the mppx hardening stack (stacked on PR #299):

  1. feat: verified context API #298 Verified context API
  2. feat: binding semantics hardening #299 Binding semantics hardening
  3. → This PR: Request body digest binding

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 6, 2026

Open in StackBlitz

npm i https://pkg.pr.new/mppx@300

commit: 45a8016

HTTP transport now captures body bytes and computes SHA-256 digest
during captureRequest. The digest is included in the challenge HMAC
binding and verified against the current request body on credential
presentation.

This prevents replay attacks where a credential issued for one
request body is presented with a different body. GET/bodiless
requests omit the digest gracefully.
@brendanjryan brendanjryan force-pushed the brendan/binding-semantics-hardening branch from fa9a919 to 7e96ff5 Compare April 6, 2026 22:23
@brendanjryan brendanjryan force-pushed the brendan/replayable-request-digest-binding branch from bbaa7da to 45a8016 Compare April 6, 2026 22:23
@brendanjryan
Copy link
Copy Markdown
Collaborator Author

Closing as redundant and not worth the tradeoffs

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.

1 participant