SECURE_NODE // ATHENS_GR
← BACK TO RESEARCH Technique · Payment Security · SCA

3DS Disabled in Payment SDK Configuration

10 JUN 2026| ≈ 3 MIN READ| 3DSSCAPaymentSecurity
SANITIZED ▸ Methodology only. All hostnames, API keys, and organizational details are lab placeholders. No client name, real API token, real card number, or production payment data appears here. Assessment was authorized and scoped in writing.

3D Secure is the primary mechanism for Strong Customer Authentication under PSD2. A cardholder initiates a payment, the card network triggers a challenge, the issuing bank authenticates the user with a second factor, and only then does the authorization proceed. When the merchant disables 3DS in the SDK configuration, none of that happens. The charge is submitted directly to the acquirer with no SCA challenge, no second factor, and no issuer verification. On the application assessed here, 3DS was disabled in both the client-side SDK bundle and confirmed off in the live API response.

3DS SEVERITY
Critical
SCA bypassed on all transactions
SCOPE
Grey-box
web app, partial source review
REGULATORY
PSD2 / SCA
non-compliant for EU payments

3DS disabled — two confirmations

The first confirmation came from the JavaScript bundle. The payment SDK was initialised with a client-side configuration object that included "threeDSecureEnabled": false. The second confirmation came from the API itself — the payment endpoint returned the same flag with no 3DS challenge objects:

# client-side SDK initialisation (extracted from JS bundle — lab)
paymentSDK.init({
  publishableKey: "<publishable-key>",
  environment: "production",
  threeDSecureEnabled: false,
  challengeMode: "NO_PREFERENCE"
});

# live API payment response (authenticated request — lab)
POST /api/v2/payments
{
  "id": "pay_lab_example_001",
  "amount": "<amount>",
  "currency": "eur",
  "status": "pending",
  "threeDSecureEnabled": false,
  "sca_enforcement": "off",
  "challenges": []
}

# both client config and API response confirm 3DS disabled
# "challenges": [] — no SCA challenge triggered for any transaction

The publishable key in the bundle is meant to be client-side — that is by design, and exposing it is not the finding. The finding is what it reveals: with the key, any visitor can read the payment SDK configuration straight from browser devtools and confirm that 3DS is switched off. The sensitive thing on display is not the key. It is the security posture of every transaction the platform processes.

Why a client-side flag is not the whole story

A disabled flag in a JavaScript bundle could, in isolation, be an incomplete picture — the frontend might request no challenge while the server still enforces one. That is why the API confirmation matters. The live payment response returned "sca_enforcement": "off" and an empty challenges array, proving the absence of SCA was server-side, not a cosmetic client setting. A control that is off in the config and off in the response is a control that does not exist.

The test timeline

DAY 1 — BUNDLE ANALYSIS

JavaScript bundle reviewed for payment SDK configuration. threeDSecureEnabled: false found in the SDK init object. challengeMode: "NO_PREFERENCE" — 3DS will not be requested for any transaction.

DAY 1 — API CONFIRMATION

Live API confirms 3DS disabled. Payment endpoint returns "threeDSecureEnabled": false and "challenges": []. Server-side enforcement absent — not just a UI configuration.

DAY 1 — IMPACT ASSESSED

SCA bypass confirmed across the payment flow. With no challenge triggered, every transaction submits straight to the acquirer with no second factor. PSD2 non-compliance for EU cardholders established.

DAY 2 — REPORT

Finding documented. 3DS configuration exposed client-side and confirmed off in the live response; remediation path confirmed with the SDK documentation.

Fixing the payment security model

  • Enable 3DS in the SDK configuration and at the processor level. Set threeDSecureEnabled: true and challengeMode: "CHALLENGE_REQUESTED" in the SDK. Verify with the payment processor that SCA enforcement is active server-side — a client-side flag alone is not sufficient. For EU cardholders, 3DS2 is required for PSD2 compliance.
  • Enforce SCA server-side, not just in the SDK. The authoritative check must live at the payment API and the processor. The client flag is a hint to the UI; the server must reject any authorization that should have carried an SCA challenge and did not.
  • Keep secret credentials out of the bundle. Publishable keys are expected on the client; secret keys must never be shipped in JavaScript sent to the browser. Review the bundle for any secret-prefixed keys and rotate any that are found — a secret key in client code is a separate, higher-severity finding.
  • Treat fraud rules as the last line, not the first. On a platform where SCA is the primary control, fraud rules must block rather than alert. If the risk engine only flags suspicious transactions, that configuration must be reviewed and moved to blocking.

The takeaway

3DS disabled is not a subtle misconfiguration — it is a single boolean that removes the primary EU payment authentication requirement. It was present in the JS bundle, in the API response, and readable by any user who opened devtools. The fix is the same place it was turned off.