No headings found on page

“None of these appear in a network vulnerability scan, and none are visible in a policy review. They are found only by analyzing the app itself.”

Aleksandr Temnov

Head of Product at Oversecured ex. Wallarm, Tinkoff, Yandex. 10 years in Product Management

“None of these appear in a network vulnerability scan, and none are visible in a policy review. They are found only by analyzing the app itself.”

Aleksandr Temnov

Head of Product at Oversecured ex. Wallarm, Tinkoff, Yandex. 10 years in Product Management

What is PCI DSS?

PCI DSS is the security standard for handling payment card data. It was created by the card brands (Visa, Mastercard, American Express, Discover, JCB) and is maintained by the PCI Security Standards Council.

PCI DSS is not a law but a contract. Your bank or payment provider requires it, and the consequences of failing are commercial: fines passed down through your acquirer, higher transaction fees, and in the worst case losing the ability to accept cards at all.

It covers cardholder data: the card number, the cardholder name and the expiry date. Sensitive authentication data (the CVV, the PIN, the full magnetic-stripe or chip data) is a stricter category that may never be stored after a transaction is authorized, under any circumstances.

The standard has 12 requirement groups covering network security, encryption of stored and transmitted data, secure software development, access control, logging, testing and policy. The current version is v4.0.1. Version 4.0 was retired at the end of 2024, and every requirement that was originally "future-dated" became mandatory on 31 March 2025.

How compliance is proven depends on your size and transaction volume: larger merchants and service providers undergo an annual assessment by a Qualified Security Assessor (QSA), smaller ones complete a Self-Assessment Questionnaire.

Do I need to comply?

If your organization stores, processes, or transmits cardholder data, PCI DSS applies to you, and so does anything that can affect the security of the systems that do.

For a mobile app the test is broader than "do we save the card number":

  • Does a customer type a card number into a screen your app renders? Then you are processing and transmitting cardholder data.

  • Does your app pass card data to a payment SDK or your own backend? Same answer: transmitting counts even when nothing is written to disk.

  • Does your app show a saved card, even masked? In scope, because masking is a control you have to prove works.

  • Does your app hold the session that logs a customer into an account where cards are stored? Then it can affect the security of the cardholder data environment, which puts it in scope without it ever seeing a card number.

Handing payment off entirely is what shrinks the scope: redirect to your provider's hosted page or an external wallet, and card data never enters your app's process. What stays in scope is the code. PCI DSS calls software you wrote, or had written for you, bespoke and custom software, and Requirement 6 covers it: secure development, code review before release, and an inventory of your components including every third-party SDK.

Are there mobile vulnerabilities that break PCI DSS?

Yes. Everything the standard protects exists on a phone, under different names. Storage is a preferences file, a local database, the keychain, or a device backup. The network is whatever wifi the user joined. An unauthorized user is an app they installed last week. Each of those is somewhere a requirement can break.

What PCI DSS does not do is tell you where to look. It states outcomes: cardholder data unreadable where it is stored, strong cryptography in transit, a defined access control model. It never says what puts those outcomes at risk inside an Android or iOS app. The table below fills that gap: what goes wrong in an app, the requirement it breaks, and why.

What goes wrong in the app

Requirement it breaks

Why

Card data or credentials end up in app storage, logs, or device backups

3.2.1, 3.3.1, 3.5.1

Storage on a phone is storage. Backups leave the device entirely

Traffic sent over plain HTTP, or TLS validation weakened

4.2.1

Every mobile session runs over an open public network by definition

Encryption keys or API tokens hardcoded in the binary

3.5.1, 3.6.1

Anyone can unpack an app, so a key compiled into it is public

Data readable by other apps on the same device

7.2.1

Access control covers more than your servers: a malicious app on the same phone is an unauthorized user

Test data or test accounts left in the shipped build

6.5.6

These must be removed before the system goes into production

Debug functionality enabled in a release build

2.2.1, 2.2.4

Builds must follow hardened configuration standards, with only necessary functions enabled

Unknown or outdated third-party SDKs in the app

6.3.2, 6.3.3

You must know what is in your software and patch its known vulnerabilities

Injection through deep links, WebViews, or inter-process communication

6.2.4

Common software attacks the standard requires you to prevent

Only an annual penetration test covers the app

11.4.2, 11.4.3, 6.3.1

You ship every two weeks. One test a year covers one build out of twenty-five

Real findings

These are finding types that come out of mobile scans, with the requirement each one puts at risk. No app names, since the classes matter more than who had them.

Data left where it should not be

  • Application backup is allowed: the app's private data can be pulled off the device over ADB or synced into a cloud backup you do not control. Anything sensitive in app storage leaves with it, unless backup rules exclude those files. (Req 3)

  • Logging sensitive data: request bodies and tokens written to logs that other software and crash-reporting SDKs can read. (Req 3)

  • Password storage on the device: credentials persisted locally in recoverable form. (Req 3)

Secrets shipped inside the binary

  • Hardcoded cryptographic key and Hardcoded password or token: an app is a file anyone can download and unpack, so a key compiled into it is public. (Req 3.5.1, 3.6.1)

  • Weak cryptographic algorithms: encryption that is present but does not meet the "strong cryptography" bar the standard requires. (Req 3.5.1, 4.2.1)

Traffic that is not protected

  • Use of insecure HTTP protocol: cleartext transmission, usually a legacy exception that was never scoped tightly. (Req 4.2.1)

  • Logical error during host validation and Internet service address substitution: the app can be pointed at an attacker's server, so encryption in transit protects a connection to the wrong endpoint. (Req 4.2.1)

Data reachable by other apps on the same phone

  • Access to arbitrary content providers via setResult and Theft of arbitrary files via ContentProviders: a malicious app with no special permissions reads files belonging to yours. It never touches your network perimeter, so nothing on the server side sees it. (Req 7, Req 3)

  • Implicit activity intent discloses sensitive data and Implicit broadcast intent discloses sensitive data: data sent to whichever app happens to be listening. (Req 7, Req 3)

  • Exported activity: internal functionality callable by any installed app. (Req 7)

Code execution and injection

  • Arbitrary code execution via third-party package contexts: code that arrives after your review, from a source you did not audit. (Req 6.2.4, 6.3.2)

  • Cross-site scripting in a WebView and File access from file URLs is enabled for WebView: untrusted content given reach into the app and its files. (Req 6.2.4)

  • Intent redirection and Insecure use of file paths in FileProviders: attacker-controlled input steering the app's own components. (Req 6.2.4)

Build hygiene

  • Debuggable attribute is set to true: a release build shipped with debugging enabled, which matters most for APKs distributed outside app stores, for example from a website. Memory can be dumped, behavior modified and secrets extracted. It is trivial to exploit and a direct hit on the requirement that release builds follow a hardened configuration with only necessary functionality enabled. (Req 2.2.1, 2.2.4)

Three cases worth looking at closely

The snippets below are anonymized: package names, library names, and key material are replaced. The patterns are exactly as found.

1. Cleartext endpoints compiled into a native library

Cleartext HTTP is one of the most common finding types in mobile scans, and it hides in unexpected places. In this case the http:// endpoints were not in Java code or in the network security configuration. They were string constants inside a native .so library bundled with the app:

lib/arm64-v8a/lib<vendor>.so → "posturl":"http://<redacted-host>/Home/PostalCode"

Nobody on the app team wrote that line, and no source-code review would surface it: the library ships as a compiled blob. It is still cleartext transmission from the app. And when the cleartext check is disabled at the configuration level, as it has to be for this traffic to flow, every request to that endpoint crosses the network unencrypted, cardholder data included.

Requirement 4.2.1 calls for strong cryptography and secure protocols whenever cardholder data crosses open, public networks, which covers every network a phone uses. The requirement says nothing about who wrote the transmitting code, so a vendor library speaking plain HTTP is still your finding. It is also the reason to test the artifact that ships rather than the source tree.

2. A hardcoded encryption key inside a third-party SDK

An encryption helper bundled with the app passed its key and IV as string literals straight into the cipher call:

String encrypted = CryptoUtils.encrypt(input, "<hardcoded-key>", "<hardcoded-iv>");

A variant of the same pattern used a hardcoded byte array as an HMAC secret:

mac.init(new SecretKeySpec(decode(new byte[]{ /* embedded key bytes */ }), mac.getAlgorithm()));

Both sit in vendor SDK code, analytics and payment libraries the app merely includes. The team's own code is clean. The app still ships a published key.

Three requirements bite here. 3.6.1 expects defined, implemented procedures for protecting cryptographic keys; a key printed in the source of a shipped app is the opposite of protected. 3.5.1 requires that PAN be unreadable wherever it is stored, a control that collapses when the key travels with the data. And 6.3.2 asks for a maintained inventory of bespoke and custom software plus the third-party components incorporated into it, specifically so vulnerabilities and patches can be managed. The flaw is in code your team did not write, and you cannot patch what you never listed.

3. Sensitive data handed to whichever app is listening

An implicit Intent (an action and a URI, with no target component) started directly:

Intent intent = new Intent(action, uri);

context.startActivity(intent);

Because no component is named, Android offers the Intent to every installed app that registered a matching filter. Whatever the URI and extras carry goes with it. Nothing crosses your network perimeter, so no server-side control sees this at all.

Requirement 7.2.1 expects a defined access control model that governs who, and what, may reach system components and cardholder data. On a phone, the population of potential requesters includes every other app the user has installed, and an implicit Intent grants them access by default. If the payload includes account data, Requirement 3 is in play as well, since the data has left your app's control entirely.

None of these appear in a network vulnerability scan, and none are visible in a policy review. They are found only by analyzing the app itself.

What this means in practice

PCI DSS compliance for a mobile app comes down to a few things being true at the same time. The inventory of components 6.3.2 asks for has to be current, and it changes with every release. New vulnerabilities in those components have to be identified and ranked, which is what 6.3.1 asks for. And what gets tested has to be the binary customers install, not a source snapshot or last year's build. None of that survives an annual cycle in an app that ships every two weeks. All requirement numbers above are from PCI DSS v4.0.1, available free from the PCI SSC document library.

Test Oversecured
on your mobile application

Oversecured analyzes Android and iOS builds for the finding types above and maps results to the standards assessors ask about.

Test Oversecured
on your mobile application

Oversecured analyzes Android and iOS builds for the finding types above and maps results to the standards assessors ask about.

Test Oversecured
on your mobile application

Oversecured analyzes Android and iOS builds for the finding types above and maps results to the standards assessors ask about.

Keep reading

Watch Oversecured find real vulnerabilities in your app

Start a free trial and see taint analysis, authenticated scanning, and exploit-backed checks in action.

Watch Oversecured find real vulnerabilities
in your app

Start a free trial and see taint analysis, authenticated scanning, and exploit-backed checks in action.

Watch Oversecured find real vulnerabilities in your app

Start a free trial and see taint analysis, authenticated scanning, and exploit-backed checks in action.