Security · S5
Secret handling in the SDK
Are secrets kept out of client bundles and are webhooks signed and verified?
Why it matters
Browser-shipped API keys and unsigned webhooks let an attacker impersonate the merchant or forge payment confirmations.
A score of 3 needs evidence naming the distributed package (name, version and integrity hash) or a network trace, not only source code in a repository.
The top score rewards the absence of a problem. It is only available when every required component in the request path is public, or a network trace covers the closed parts.
Scoring anchors
| No secrets in client bundles, webhook signatures verified in reference code, keys scoped and rotatable. | |
| Minor issues documented. | |
| Secrets in client with a disclosed mitigation. | |
| API keys shipped to the browser, or unsigned webhooks. | |
| No admissible evidence submitted yet. Counts as 0 in the pillar. |
Admissible evidence
- SDK and example code at a pinned commit verified
- Network trace documented (trace)
Common failures
- Publishable "app IDs" mistaken for secrets; check what they authorise.
Current ratings
| Provider | Score | Finding |
|---|---|---|
| Aleo (credits.aleo private transfers) | Private keys stay with the user; the protocol has no webhooks. The SDK supports an optional gateway API key or JWT, which an integrator could ship in a browser bundle; the SDK does not do so itself. Using the optional record-scanning service hands a view key to Provable. Judgment call: 2, since 3 needs a package or trace record and the optional services widen key exposure. | |
| AnomaPay | No admissible evidence yet. | |
| Avalanche Card | No admissible evidence yet. | |
| Avici Card | No admissible evidence yet. | |
| Aztec (Alpha mainnet private token transfers) | Account keys stay in the user's PXE, and the protocol has no webhooks. The limitations page warns that the PXE does not yet enforce which apps can read a user's private data. Judgment call: 2, since 3 needs a package or trace record and the PXE data-access caveat is documented. | |
| Bitget Wallet Card | No admissible evidence yet. | |
| Blanksquare (Shielder) | No secrets in the client and no webhooks; the bundled keys are publishable identifiers. Private Send hands a key to a TEE, which is opt-in. Scored 2 (3 needs a package or trace). | |
| COCA Card | No admissible evidence yet. | |
| Coinbase Commerce (Onchain Payment Protocol) | Merchant API keys stay on the server, and the reference code verifies webhooks. The SDK puts a CDP client key in the browser. That key is meant to be public, but it does authorise charge creation for productId checkouts. No repo describes key scoping or rotation, and the PHP client was last changed in 2021. | |
| Curvy | No admissible evidence yet. | |
| Daimo Pay | The client bundle contains no long-lived secrets. Webhooks are HMAC-signed, but the only verification reference code is on the hosted docs, not in the repo. Neither the repo nor the docs describe API-key scoping or rotation. Judgment call: we score 2 and not 3, because the reference verification is not in the repo and rotation is not shown. | |
| Deblock Card | No admissible evidence yet. | |
| Ethena Pay | No admissible evidence yet. | |
| ether.fi Cash | No admissible evidence yet. | |
| Exa Card | No issuing or KYC secrets are in the client, and webhooks are signature-verified with rotation support. The client ships publishable Alchemy and Segment keys, which authorise metered RPC use and analytics writes. Judgment call: minor, so 2. A 3 is not possible while required components are closed. | |
| Fluidkey | The app bundle is closed and not inspected. The docs say spending keys never leave the client, while a viewing-key node is shared with Fluidkey by design (P2). | |
| Fuse Card | No admissible evidence yet. | |
| Gnosis Pay | No secrets are shipped to the browser, and webhook signatures are asymmetric with verification code in the repo. Key scoping and rotation are not documented in any repo I read. Judgment call: missing scoping and rotation evidence keeps this at 2, not 3. | |
| HesabPay | No admissible evidence yet. | |
| Hinkal | No admissible evidence yet. | |
| Holyheld Card | The SDK is built for the browser and authenticates with a partner API key, so the key ships to the client; no scoping, rotation or webhook verification is documented in the repo. Judgment call: what the key authorises is not documented, so it may be a publishable ID; with no evidence that it is scoped, this takes the lower anchor. | |
| Houdini Swap | The reference code keeps the API secret server-side. The API has no webhooks (status comes by polling or WebSocket), so webhook signing does not arise. Minor issues are documented: credential rotation needs a support request. The agent client takes a raw wallet private key (x402) from env and, per its README, may store it in plaintext. The closed web app and widget were not inspected, so 3 is not available. Judgment call: 2. | |
| Hyperbeat Card | No admissible evidence yet. | |
| Jupiter Card | No admissible evidence yet. | |
| M-Pesa | Payment callbacks are unsigned per the Daraja docs, and the reference handlers accept them without verification, so a party who learns a merchant's callback URL can forge payment confirmations unless the merchant re-queries Transaction Status. Handling of API credentials (consumer key/secret, SecurityCredential) in client bundles was not assessed. | |
| MetaMask Card | A key labelled as a secret ships in every app bundle. What it authorises on Baanx's side is not visible. The code shows a mitigation: PKCE plus per-user credentials, so the key works as a public client identifier. There are no webhooks in the client. Judgment call: "secrets in client with a mitigation" (1). Whether the mitigation is disclosed beyond the code is unknown. | |
| Opera MiniPay | No admissible evidence yet. | |
| Monero | Spend and view keys stay in the user's wallet file. The protocol has no API keys or webhooks, and we found no bundled service keys. Judgment call: absence shown only in code is capped at 2, since 3 needs a distributed-package or trace record. | |
| Nullmask | No admissible evidence yet. | |
| Oobit Card | No admissible evidence yet. | |
| Payy Card | No admissible evidence yet. | |
| Phantom Cash | No admissible evidence yet. | |
| Plasma One | No admissible evidence yet. | |
| Privacy Pools (0xbow) | Account secrets come from a mnemonic generated and kept client-side. There are no webhooks or merchant API keys. The website bundles an Alchemy RPC key, which grants only RPC quota, and keeps the HyperSync and ASP keys server-side. Judgment call: 2 for the bundled RPC key. | |
| Railgun | No secrets ship in the SDK or the Railway source, and the protocol has no merchant keys or webhooks. User secrets stay client-side. The npm package 10.9.0 was published from the pinned commit (gitHead 5c9d04c8). Scored 3. | |
| Request Network | No merchant secret reaches the browser. The open SDK path has no API key or webhook. The hosted API uses domain-scoped, revocable Client IDs on the client and signed webhooks, and the reference app verifies the signatures. There are two minor issues. The SDK bundles a shared Infura project ID. The reference verification uses a non-constant-time comparison on re-serialised JSON. Judgment call: we score 2 and not 3 because of these two issues. | |
| Rizon Card | No admissible evidence yet. | |
| SafePal Card | No admissible evidence yet. | |
| Solayer Card (Emerald Card / Solayer Pay) | No admissible evidence yet. | |
| Tongo (confidential ERC-20 on Starknet) | Users' secrets are their Tongo keys, generated and used client-side. Relayed operations are signed with the Tongo key. The repo commits devnet-only test keys in packages/tongo-sdk/.env, a hygiene issue rather than a production secret. Judgment call: 2 (minor issues). | |
| Tornado Cash (Classic pools) | The user secret is the note (nullifier and secret), generated and kept client-side. The protocol has no API keys or webhooks. The UI embeds RPC provider keys in its bundle, a minor issue since they grant only RPC quota. Integrity of the served frontend depends on whoever controls tornadocash.eth (TORN governance, see S2). Judgment call: 2 for the bundled RPC keys. | |
| Tria | No admissible evidence yet. | |
| Tuyo Card | No admissible evidence yet. | |
| Umbra Cash | Spending and viewing keys are derived from a wallet signature in the browser and never sent anywhere. There are no webhooks or merchant keys. Explorer and RPC keys ship in the client bundle. Judgment call: 2 for the bundled read-only keys. | |
| Wirex One | A client secret ships in the browser bundle. What it authorises was not tested and nothing was called with it. Secrets in client, no mitigation found, so 0. | |
| Wise | Webhooks are signed, and Wise's reference code at a pinned commit verifies the signature. Credentials are documented as scoped and rotatable. Whether secrets ever reach client bundles was not checked, because the apps and API are closed and no trace was run, so 3 is not available. Judgment call: 2. The verification is verified in code; the gaps are that secret handling is not inspectable, the reference code dates from 2021 and uses only the sandbox key, and the docs leave payload verification optional ("where applicable"). | |
| WORM (BETH proof-of-burn) | The bundled keys grant only RPC quota. The user's secret, the burn key, is created and backed up client-side, but the one-page send flow sends it to the WORM prover (P2). That exposes the payment link, not the funds, because the recipient is fixed. Judgment call: 2 (minor issues). | |
| XPlace Card | No admissible evidence yet. | |
| Zcash (shielded transfers) | Spending keys stay on the user's device; the protocol has no API keys or webhooks. The mobile wallet ships a CoinMarketCap API key in its store build, a minor issue since it grants only price-quote quota. Judgment call: 2 for the shipped key. | |
| zERC20 (zBNB on BNB Chain) | The only secret seen in the client is an RPC provider key, which grants RPC quota. There are no webhooks or merchant API keys. Burn-address secrets stay with the user or are sent encrypted through ICP. Judgment call: this is a minor issue (2 in substance), but the evidence is a documented-tier read of a built bundle, so 1. |