Skip to content

Security: Ali-Mostaghimi/TapFlow

Security

docs/security.md

Security

TapFlow is a portfolio project that simulates card-present payments. This page states what it protects, what it deliberately leaves out, and what a production version would add. It is written to be honest about scope, not to claim compliance.

Scope

Real in TapFlow Simulated or out of scope
Payment state, idempotency, reconciliation, refunds, telemetry, flags The acquirer, which is a fake inside the backend
NFC reader mode and an ISO-DEP exchange with a test card Card data: no PAN, expiry, track data or EMV cryptogram is ever read
Bearer authentication of the terminal Per-device credentials, key rotation, device attestation
TLS-ready HTTP client Cleartext HTTP is allowed in debug builds only, for the local backend

Card data policy

  • The app never sees card data. The terminal contract returns an opaque PaymentMethodToken, and its toString() is redacted, so it cannot leak into logs by accident (ADR 0012).
  • The NFC reader sends one command: a SELECT of TapFlow's proprietary AID. It never selects a payment application and never reads records. A real bank card tapped on TapFlow only counts as "a card was presented" (ADR 0032).
  • The test card answers only its proprietary AID, in the other category, with a random token per tap. It cannot pose as a payment card.
  • Telemetry carries ids, state names, reasons and cohorts. Only an error's type is recorded, never its message, because messages can contain anything (ADR 0028).

Threat model

Threat Where Mitigation in TapFlow Production addition
Customer charged twice through retries or double taps App ↔ backend One active payment; idempotency keys generated before sending and enforced by the backend; unknown outcomes reconciled, never retried blindly (ADR 0014, 0015, 0021) Same design, plus acquirer-side idempotency
Replayed or altered request Network Key reuse with a different body is rejected (422); amounts and refund limits enforced on the backend TLS with certificate pinning, request signing
Refunding more than was paid Backend Limit checked under a row lock, pending refunds count; the device checks the same limit (ADR 0026) Refund authorization by role, e.g. a manager PIN
Stolen terminal token Device Static demo token from Gradle properties Per-device credentials from provisioning, stored in the Android Keystore, rotated and revocable
Debug features in production Build Developer panel and fault injection only in debug builds; backend debug endpoints on for the demo, off with TAPFLOW_DEBUG=false Separate backend deployment without debug routes; build checks that fail if they are present
Remote config abused Backend ↔ app Authenticated config; typed flags with safe defaults and range checks; versions never go backwards (ADR 0030) Signed configuration, audited back office with access control
A rollout harms payments Fleet Automatic rollback on the unknown-rate guardrail (ADR 0031) Alerting when the guard acts, significance testing
Lost or stolen device Device App sandbox; the database holds payment ids, amounts and idempotency keys, never card data Exclude the database from backups, full-disk encryption requirement, remote wipe through device management
Relay or tampered NFC exchange NFC Nothing valuable is exchanged: the test token cannot pay A certified reader component, EMV cryptograms verified by the issuer
Leaking data through logs App Redacted tokens, error types only Log scrubbing in CI, no payment logs in release builds

PCI

  • PCI DSS applies to systems that store, process or transmit cardholder data. TapFlow keeps card data out of the app entirely and works with tokens, which is the main way a merchant application stays out of most of that scope.
  • PCI MPoC (Mobile Payments on COTS) is the standard for accepting cards on commercial phones and tablets. It covers the software that reads the card, isolation of card data and PIN entry, attestation of the device and app, and back-end monitoring. A product would get this by integrating a certified Tap to Pay SDK from a payment provider, not by building it.
  • In that architecture the TapFlow app would be the merchant application: it starts payments, handles unknown outcomes, reconciles and refunds, using tokens from the certified SDK behind the same PaymentTerminal contract.

Production hardening checklist

  • Per-device credentials from provisioning, in the Android Keystore, with rotation.
  • TLS everywhere, certificate pinning for the payment backend, no cleartext configuration.
  • Play Integrity or equivalent attestation before a terminal may take payments.
  • Backups exclude the payment database; minimum data retention on the device.
  • Debug routes absent from production builds, verified in CI.
  • A certified Tap to Pay SDK as the terminal implementation.

There aren't any published security advisories