Skip to main content
The Blink deposit UI is loaded live from https://pay.blink.cash every time it opens. Live loading is a security feature for a payments surface: when we ship a security or fraud fix, it reaches your users immediately, without waiting for you to upgrade the SDK. This page covers the controls available to you as an integrator, and how to verify what we serve.
The single most effective control is a Content-Security-Policy on your own page that restricts where the deposit iframe may load from. Set it in production — see Lock the iframe origin.

Lock the iframe origin

Add a frame-src directive to your page’s Content-Security-Policy so the browser will only ever load the deposit iframe from Blink — even if your page is compromised by an injected script:
Content-Security-Policy: frame-src https://pay.blink.cash; script-src 'self';
For testnet/sandbox integrations, also allow the sandbox host:
Content-Security-Policy: frame-src https://pay.blink.cash https://pay-sandbox.blink.cash; script-src 'self';
What you need — and what you don’t:
DirectiveWhat to allowWhy
frame-srchttps://pay.blink.cash (+ sandbox host)Restricts the deposit iframe to Blink’s origin.
script-src'self'The @swype-org/deposit SDK runs from your own bundle.
connect-srcyour own signer endpointThe SDK calls your signer from your page.
img-srcdata: (only if you use BlinkDepositButton)The button paints its USDC/USDT coin marks as inline data: SVGs in your DOM — see below.
style-src'unsafe-inline' (only if you use BlinkDepositButton)The button styles itself with inline style attributes — see below.
You do not need to allow-list Blink’s backend, Privy, Sentry, or any other Blink dependency in your CSP. All of that traffic originates inside the cross-origin pay.blink.cash iframe, which is governed by Blink’s own policy — not your page’s CSP.
The allow-list above covers the deposit flow only. If your own page independently connects wallets or calls other services outside the deposit iframe, those origins need their own connect-src/frame-src entries — that’s your application’s surface, separate from Blink’s.

If you use BlinkDepositButton

@swype-org/deposit/react exports a ready-made BlinkDepositButton you can drop onto your page. Unlike the deposit iframe, this button renders in your own DOM, so its assets are governed by your CSP — not Blink’s. The button is intentionally self-contained: it paints its USDC/USDT coin marks as inline data: SVGs and styles itself with inline style attributes. If your CSP restricts img-src or style-src — directly, or via a default-src fallback — allow these so the button renders correctly:
Content-Security-Policy: frame-src https://pay.blink.cash; script-src 'self'; connect-src 'self' https://signer.example.com; img-src 'self' data:; style-src 'self' 'unsafe-inline'
Prefer to keep img-src/style-src strict? Use the useBlinkDeposit hook and render your own button instead of BlinkDepositButton. The hook carries no markup, so it adds no CSP requirements beyond the table above.

Deliver the policy in each environment

The frame-src host changes per environment: production loads from https://pay.blink.cash, testnet/sandbox from https://pay-sandbox.blink.cash. Point each build at the host it actually loads.
Content-Security-Policy: frame-src https://pay.blink.cash; script-src 'self'; connect-src 'self' https://signer.example.com
A bundler dev server (Vite, webpack) needs script-src to also allow 'unsafe-inline' 'unsafe-eval' for hot-module reload, plus ws://localhost:* in connect-src for the HMR socket. Keep production strict at script-src 'self' — never ship the relaxed dev values.

Set it as a real response header

A response header from your server or CDN is the strongest delivery — it can carry directives that a <meta> tag cannot:
Content-Security-Policy: frame-src https://pay.blink.cash; script-src 'self'; connect-src 'self' https://signer.example.com
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin

Static-only hosting

If you ship a static SPA and can’t control response headers, inject a <meta> tag into your index.html:
<meta
  http-equiv="Content-Security-Policy"
  content="frame-src https://pay.blink.cash; script-src 'self'; connect-src 'self' https://signer.example.com"
/>
frame-ancestors, X-Content-Type-Options, and Referrer-Policy are ignored when delivered via <meta>. If you rely on those, set them as real response headers at your host or CDN.
  • Origin-validated messaging — every postMessage between the SDK and the iframe is checked on origin, source window, and message type before it is acted on. The parent-frame wallet bridge additionally enforces a JSON-RPC method allowlist.
  • Authentication is origin-gated — the embedded auth provider (Privy) only authenticates on origins you have registered with Blink (your merchant domain plus any additional domains). The deposit flow cannot authenticate when embedded on an unapproved origin.
  • TLS + HSTS on the hosted UI, served from a CDN.

Verify what we serve

The build manifest

Every deploy publishes a manifest of the exact bytes we serve:
curl -s https://pay.blink.cash/manifest.json | jq .
{
  "version": "1.0.0",
  "gitSha": "…",
  "builtAt": "…",
  "files": {
    "index.html": "sha256-…",
    "assets/index-XXXX.js": "sha256-…"
  }
}
You can fetch any referenced file and confirm its SHA-256 matches the manifest:
curl -s https://pay.blink.cash/index.html | shasum -a 256
# compare against manifest.files["index.html"] (strip the "sha256-" prefix)
A silent change to the served UI would no longer match the published manifest. (Sandbox: https://pay-sandbox.blink.cash/manifest.json.)

The SDK supply chain

The part of the integration that runs on your page — the @swype-org/deposit npm package — is pinned by your package-lock.json integrity hash. npm audit signatures verifies npm’s registry signature on the published tarball against that hash:
npm audit signatures

Why we don’t version-pin or SRI-pin the iframe

Subresource Integrity (integrity="sha384-…") only applies to <script> and <link> elements — it cannot be applied to an iframe document, which legitimately loads its own (content-hashed) subresources. Signature-based SRI is an emerging standard but is not yet broadly supported. Pinning a fixed version would also defeat the live-update model that lets us ship security fixes to your users immediately. The manifest above is the practical, verifiable equivalent for a whole-document iframe.

Checklist

1

frame-src CSP set on your production page, restricted to https://pay.blink.cash (sandbox builds use https://pay-sandbox.blink.cash).

2

connect-src allows your own signer endpoint.

3

Production ships strict script-src 'self' — the relaxed dev values ('unsafe-inline'/'unsafe-eval') are never deployed.

4

The policy is delivered as a real response header where possible; a <meta> tag is only a static-hosting fallback.

5

npm audit signatures passes for @swype-org/deposit.