← Back to blog

How Zenobia keeps your payments secure

6/16/2025By Theodore Li

Security Overview

With payments, the margin for error is low. We've hardened the security at every step of the payments flow, from the initial bank connection to the webhook notification to merchant's payment configuration options to ensure that no malicious customer or merchant can receive unauthorized funds.

Below is an overview of the methods Zenobia Pay uses to be secure in payments.

Payment Flow

Payment Flow Diagram

Push vs Pull Based Payments

Credit card payments are pull-based. A merchant receives your credit card details and uses it to pull funds on behalf of you. Zenobia Pay is push-based. Our payments are always executed from the app, sending funds via authenticated OAuth calls. By reversing responsibilities and only allowing the customer themselves to authorize funds, we reduce fraud by 99%, preventing using stolen credit cards, merchants improperly handling credit card numbers, or misrepresenting the amount charged.

Bank Connection

We use Plaid to connect your bank account. Plaid uses 2 factor authentication to ensure that you own the bank account, ensuring attackers with stolen bank credentials cannot log in as you.
We then use Orum, a payments infrastructure provider, to transfer money from the customer's bank account to the merchant.

Device Signing

To further harden our security, each Zenobia app on install generates a unique device identifier and ECDSA public/private key pair. Any bank account linked also stores the device id and public certificate for verification. On payment, the app signs the request with the private key. The Zenobia backend then validates the signature against the public key stored.

Payment Display

When creating a transfer, the price is stored on Zenobia's backend service. The price is then shown again on the app for payment confirmation. Storing and redisplaying the price on the app prevents any misrepresentation of price or paying for an incorrect amount.

Secure Enclave

We use Secure Enclave to ensure that the data is accessible only from the Zenobia Pay app and no other installed apps can access it. We also ensure that this data is not synced to iCloud, meaning that breaches to iCloud will not compromise our security. This allows us to be confident that signed fulfillment requests only can come from the customer's device.

Biometric Authentication

Payments on the Zenobia Pay app are further locked down by biometric auth. We use FaceID to ensure that the phone's owner authorized the request. We also only accept the payment if the phone has been unlocked.

Continuous Pentesting

We partner with OneLeet for annual security reviews. Our last pen test was in May, with an Excellent score with no vulnerabilities found.

Encryption

Encryption is used throughout Zenobia Pay. Each database is encrypted with a distinct KMS key, and we follow least-privilege principles when granting our services access to Encrypt/Decrypt permissions. We use AWS API Gateway to process requests which uses TLS version 1.2, encrypting networking traffic. All requests are signed via JWT ensuring that only authorized users can call our endpoints successfully. All Zenobia's M2M credentials are stored in AWS Secrets Manager, which encrypts the data at rest.

Organizational Security

We enforce 2 factor authentication on all logins. All employees undergo security training on a regular basis. Employee devices are regularly updated.

We use role based access control (RBAC) when logging into the prod environment to prevent accidental disruption of services.

Merchant Security

We use Orum to securely store account and routing numbers. The data is never stored by us. In addition, these bank accounts are marked as receive only, meaning they cannot be used to fulfill payment requests. Configuration of these numbers is restricted and handled by a Zenobia employee, meaning that an attacker with merchant credentials still cannot reroute funds. Merchants also cannot modify their merchant account name without approval from a Zenobia employee, preventing phishing attacks from malicious actors. Merchant credentials can only request transfers, reducing area of impact if credentials are leaked. Our credentials are generated by Auth0 and are not stored by us.

Webhooks and Websockets

We use both webhooks to notify merchants of payments and a websocket status service to notify clients. To prevent impersonations, all events are signed with a private key. The public key hosted on our site is used to verify the signature. These events include transfer request id as well as a timestamp to prevent replay attacks.