Skip to main content

Security and compliance

The Android Secure Fields SDK is designed so that raw card data never passes through your application code. This page describes what Purse guarantees, what your application must do, and what is prohibited.

QSA review

Share this page with your qualified security assessor (QSA). Formal PCI DSS scope determination requires an independent assessment.

What Purse guarantees

Card data never reaches your application code

Card input fields are rendered as native views that are internal to the SDK module. There is no public API that returns a PAN, CVV, expiry date, or cardholder name. The only outputs your application receives are:

OutputWhat it contains
FieldStatePayloadField validity (Boolean), character count (Int), touched state (Boolean)
BrandDetectedPayloadDetected brand(s) — e.g. [Brand.VISA]
CardInfoBIN prefix (first 8 digits), detected brand(s), last four digits
SubmitResult.SuccessvaultFormToken — an opaque server-side token

SDK-level hardening

ProtectionDetail
No value eventsonChange, onFocus, and onBlur carry only validity and character count — never the raw card value
Keyboard learning blockedIME_FLAG_NO_PERSONALIZED_LEARNING on all fields — the keyboard never stores PAN or CVV digits for autocomplete
Autofill blockedIMPORTANT_FOR_AUTOFILL_NO on all fields — autofill providers cannot read or cache card values
Accessibility readout blockedIMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS on all fields — accessibility services cannot read field content
Card data not loggedThe SDK logger is disabled by default; enableDebugLogging() is a no-op on non-debuggable (release) APKs
Memory cleared on destroydestroy() clears all internal card state; field views are detached and nulled
TLS enforcedAll API calls use HTTPS; plain HTTP is rejected

Merchant obligations

Enable FLAG_SECURE on your checkout Activity

FLAG_SECURE prevents the checkout screen from appearing in the Android task switcher thumbnail and blocks MediaProjection-based screen recording apps. Set it in your checkout Activity's onCreate():

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
setContentView(R.layout.activity_checkout)
}

FLAG_SECURE can only be set on a window — the SDK owns individual field views, not your Activity's window, so it cannot set the flag itself. What the SDK does do is warn you if you forget: it checks your Activity window at render() time and, if FLAG_SECURE is missing, dispatches onSecurityWarning(payload) on your SecureFieldsListener (payload.code == "FLAG_SECURE_MISSING"). This is advisory only — it never blocks rendering. Setting the flag remains entirely your responsibility.

secureFields.addListener(object : SecureFieldsListener {
override fun onSecurityWarning(payload: SecurityWarningPayload) {
// payload.code == "FLAG_SECURE_MISSING" today; treat unknown codes as informational
Log.w("Checkout", "Security warning: ${payload.message}")
}
})

Disable Android backup for your checkout data

Set allowBackup="false" in your app manifest, or use a data_extraction_rules.xml that excludes any directories where the SDK might write temporary state:

<!-- AndroidManifest.xml -->
<application
android:allowBackup="false"
...>

This prevents card-related data from being included in device backups.

Keep the checkout Activity in the foreground

Do not background or minimize the Activity while the card form is visible. If your flow requires a context switch (for example, to open a camera for ID verification), call destroy() and re-initialize the SDK when the user returns.

Prohibited practices

The following actions undermine the card data isolation model and are prohibited:

PracticeWhy it is prohibited
Screen recording or screen casting while the form is visibleCaptures raw card input from the screen buffer, bypassing the SDK's field-level isolation
Extending or subclassing VaultFieldViewInternal field views are internal to the SDK module; attempting to subclass or wrap them to access their content violates the isolation boundary
Injecting views into the VaultFieldView containerThe SDK marks attachFieldView() as internal; you cannot insert overlay views that could intercept touch events or capture input
Using accessibility services to read field contentIMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS is set on all fields; building or enabling a service to bypass this is prohibited
Logging event payloads that include card dataSDK events never include card data, but do not log field events alongside card-identifying information you hold (e.g. a stored PAN) in a way that could reconstruct card data
Downgrading or intercepting TLSThe gateway endpoint is derived internally from VaultEnvironment and all calls use HTTPS (TLS 1.2/1.3); do not modify the build, proxy, or network security config to downgrade or intercept them
Reading memory from the SDK processAttaching a debugger or memory scanner to extract card data from the SDK's heap is prohibited and constitutes a PCI DSS violation

SAQ A-EP scope

The SDK architecture is designed to support SAQ A-EP eligibility:

  • Card data is captured by an embedded component (the SDK) provided by Purse
  • Your application code never directly processes, stores, or transmits raw card data
  • Tokenization is handled entirely within the SDK and the Purse gateway

For SAQ A-EP to apply, you must:

  1. Use VaultEnvironment.PRODUCTION in your release build
  2. Set FLAG_SECURE on your checkout Activity
  3. Set allowBackup="false" (or equivalent data extraction rules)
  4. Not implement any of the prohibited practices listed above
  5. Obtain a vault_form_token from the SDK and pass it to your backend — never handle raw card data server-side either

Your QSA will verify these controls during assessment. Purse can provide an attestation letter describing the SDK's PCI scope on request.