Skip to content

feat(upi): M4.3 critical UPI security and financial integrity remediation - #30

Open
Satelink-Protocol wants to merge 1 commit into
launch-mvpfrom
feature/m4-3-upi-security-remediation
Open

Satelink-Protocol wants to merge 1 commit into
launch-mvpfrom
feature/m4-3-upi-security-remediation

Conversation

@Satelink-Protocol

@Satelink-Protocol Satelink-Protocol commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This PR completes Milestone M4.3 — Critical UPI Security & Financial Integrity Remediation, resolving all 9 vulnerabilities and architectural defects identified during the independent M4.2 audit (docs/UPI_SECURITY_AUDIT.md).

Remediated Findings (All 9 Resolved):

  1. SEC-01 (Critical) — PhonePe Webhook Signature Verification:

    • lib/upi/adapter.js: Correctly extracts the Base64 response property from the incoming JSON payload and computes SHA256(base64Response + saltKey) + '###' + saltIndex per the official PhonePe S2S specification.
    • Retains backward-compatible fallback for legacy plain test strings.
  2. FIN-01 (Critical) — Webhook Amount Verification:

    • lib/services/upi-payments.js: Ingests and validates verifiedAmountPaise in applySuccessfulUpiPayment.
    • If paid amount differs from expected order amount (underpayment attack), the payment is marked disputed, an immutable dispute audit entry is logged, and 0 bookings are confirmed.
  3. DATA-01 (High) — Guest Checkout Schema Safety & Claim API:

    • lib/handlers/upi-checkout.js: Gated /checkout/:slug/upi to require sign-in (redirecting to /signin unless explicit ?guest=1).
    • lib/services/upi-payments.js: Unauthenticated guest intents generate an unguessable guestToken. Webhooks mark guest payments succeeded without crashing on NOT NULL bookings.user_id.
    • lib/router.js: Mounted POST /api/checkout/upi/claim allowing authenticated attendees to claim guest orders.
  4. CONCUR-01 (High) — Concurrency Capacity Holds & Confirmation Check:

    • Added activePaymentHolds and activeTierPaymentHolds in lib/services/upi-payments.js to hold seats during active unexpired intents (expires_at > now()).
    • Re-checks remaining event and tier capacity inside the locked transaction during confirmation; oversold orders transition cleanly to refund_pending with dispute reason capacity_exceeded.
  5. AUTH-01 (High) — Status Endpoint Authorization:

    • Added strict access control to getUpiPaymentStatus: registered orders require caller to match payment.user_id or hold an admin/staff role (super_admin, finance, event_manager, support).
    • Guest orders require matching guestToken via constant-time comparison or staff role.
  6. QR-01 (Medium) — QR Generator ISO 18004 Compliance:

    • lib/upi/qr.js: Corrected format information bit loop (i < 7) to preserve the mandatory Dark Module at coordinate (size - 8, 8).
    • Configured exact ISO/IEC 18004 Table 9 multi-block group blocks (e.g. V8: 2 blocks of 38 + 2 blocks of 39 data codewords) with interleaved codeword distribution.
  7. UI-01 (Medium) — Responsive Viewport CSS Isolation:

    • lib/views/checkout-upi.js: Added CSS media queries hiding .checkout-desktop on mobile (<=768px) and hiding .checkout-mobile on desktop (>=769px).
  8. LOG-01 (Low) — Dedicated Rate Limiting Keys:

    • lib/handlers/upi-checkout.js: Separated PhonePe webhook rate limit namespaces to phonepe_hook: and phonepe_bad_sig:.
  9. DB-01 (Low) — Append-Only Immutable Audit Ledger:

    • migrations/016_payment_audits_immutable.sql: Added PostgreSQL trigger prevent_payment_audit_mutation preventing UPDATE and DELETE on payment_audits. Added partial index idx_payments_active_holds.

Verification & Testing:

  • Full Test Suite: 455 tests run, 453 passed, 2 skipped (unconfigured Stars sandbox), 0 failed.
  • UPI Checkout Suite: 21/21 passed in test/upi-checkout.test.js (including 8 dedicated M4.3 audit tests).
  • Migration Suite: 7/7 passed in test/migrations.test.js (verifying all 14 migrations and trigger immutability).
  • Prohibited Provider Scan: Clean (0 occurrences).
  • Linter: 140/140 files OK.
  • Safety Boundary: ENABLE_LIVE_PAYMENTS=false strictly preserved across all environments.

…ings (SEC-01 - DB-01)

- SEC-01: Extract Base64 response for PhonePe S2S webhook signature calculation
- FIN-01: Enforce strict webhook amount verification and dispute ledger transition
- DATA-01: Gate checkout with sign-in redirect, store guestToken, and add claim API
- CONCUR-01: Hold unexpired intent capacity and re-verify inventory at confirmation
- AUTH-01: Enforce session and guestToken authorization on payment status API
- QR-01: Preserve ISO 18004 Dark Module at (size - 8, 8) and fix V8 block interleaving
- UI-01: Add responsive media queries to isolate mobile intent and desktop QR
- LOG-01: Namespace PhonePe rate limits to phonepe_hook: and phonepe_bad_sig:
- DB-01: Add migration 016 with append-only database trigger on payment_audits
- Update test suite with 8 dedicated M4.3 audit tests (453/453 tests passing)
- Update audit reports and project state docs
@vercel

vercel Bot commented Nov 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
strangersmeetup Ready Ready Preview Nov 3, 2026 6:35am UTC

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