A banking app runs on a device the customer, and sometimes an attacker, fully controls. MASVS v2 gives you eight control groups to check; here is what each means for a Saudi wallet or banking app.
Take a banking or wallet app apart on a test bench and the first thing that stands out is how much the build was trusted to decide. Spending limits, which accounts a user may see, whether a transfer is allowed, sometimes the business rules themselves, all sitting in code that runs on a phone the customer owns and that an attacker can own just as completely.
The OWASP Mobile Application Security Verification Standard, MASVS, is the structure we use to check that the trust was placed correctly. Version 2 organizes its requirements into eight control groups, and the older L1, L2 and R levels were moved out of the standard itself into the Mobile Application Security Testing Guide, the MASTG, where they now live as testing profiles (OWASP MASVS; OWASP MASTG). The groups are a good way to organize a test. What they mean for a Saudi banking, wallet or government services app is the part worth spelling out.
In short
Treat the device as hostile. Anything the app can read or decide, the owner of a rooted or jailbroken device can read or change too.
The server is the authority. Every check that matters, limits, entitlements, transaction rules, is enforced server-side, and the app only presents the result.
The findings that recur are mundane: secrets shipped in the bundle, sensitive data left in logs, caches, backups or screenshots, weak certificate validation, loose session handling.
MASVS v2 gives you eight control groups to structure a test; the L1, L2 and R levels now sit in the MASTG as testing profiles.
Resilience controls like root and tamper detection are defense in depth, never a replacement for server-side enforcement.
Test on the Android and iOS versions your customers actually run, and scope the app together with its API, because most of the real risk lives at that boundary.
The device belongs to the customer, and maybe to someone else
The founding assumption of mobile security testing is that the person holding the phone may be an adversary, and on a rooted or jailbroken device they can read the app’s files, inspect its memory, observe its traffic and change its behavior. Every weakness below follows from taking that seriously or from forgetting it.
The single most consequential mistake is placing a security decision on the device because it is convenient there. An app that computes a customer’s daily transfer limit locally and enforces it in the UI has made a suggestion rather than enforced a limit, because the check runs in code the attacker controls. The same goes for feature entitlements, fraud rules and which accounts appear in a list. All of it belongs on the server, which is the only side of the connection you actually control, and the app’s copy of any rule is a convenience for the user experience and nothing more.
For a Saudi audience this plays out across a few app types. A retail banking or wallet app moving mada and SARIE payments, a government services app that leans on national identity and Nafath-style sign-in, a fintech aggregating accounts under the open banking rules. All of them hold data a fraudster wants, and all of them run on the same wide spread of consumer devices. The threat model is the same in each case: assume the person holding the phone may be hostile, and assume a second attacker may sit on the network between that phone and your servers.
Storage, crypto, and the secrets you shipped
Two of the most common findings sit in storage and code. The app persists something sensitive in plaintext where another app or a curious owner can read it, or the build ships a secret that was never meant to leave your servers.
On storage, the MASVS-STORAGE group is about what the app leaves behind on disk. Session tokens, personal data, account details and keys belong in the platform’s protected store, the Android Keystore or the iOS Keychain, and should never sit in plaintext in shared preferences, a local database or a file. The leak is rarely in the obvious place. A value is handled correctly in the main store and then copied, without anyone deciding to, into a log line, a WebView cache, a device backup or a screenshot.
01Logswritten to logcat or a crash report and read by another app or a bundled SDK
02Cachesleft in a WebView cache, an image cache or a temp file after the screen closes
03Backupscopied to cloud backup because the data was never excluded from it
04Screenshotscaptured as the app-switcher thumbnail when the app moves to the background
05Keyboard and clipboardretained by a third-party keyboard, or left sitting on the clipboard
Where a sensitive value leaks on a device, long after the app finished using it
On crypto, MASVS-CRYPTO is less about choosing exotic algorithms and more about not undoing good ones. Use the platform’s cryptography, keep keys in the keystore rather than in the binary, and avoid home-grown schemes. Hardcoded secrets are the related finding we raise most, and the way to catch them is to inspect the build itself: API keys, signing material or backend credentials compiled into the app. Anything shipped in the bundle is readable by anyone with the app, so a secret in the build is a published secret. If a key must exist on the device, it should be scoped so tightly that its disclosure does not matter, and the real secrets should stay server-side.
What good evidence looks like here is concrete. Mark sensitive screens so the operating system blanks them in the app switcher and blocks screenshots, Android’s secure-window flag and the equivalent iOS privacy screen, and show in testing that the thumbnail captured when the app backgrounds is empty. Exclude the sensitive data stores from device and cloud backups, and demonstrate that a restored backup does not carry them. Confirm that pulling the app’s files off a test device yields nothing readable after a full session of real use, including the WebView and image caches that collect data without anyone asking them to.
Network and session handling
MASVS-NETWORK covers the connection, and the failure we see is weak certificate validation. TLS is almost always present, but the app accepts a certificate it should reject, or falls back to cleartext under some condition, or validates loosely enough that an attacker positioned on the network can sit in the middle. The connection should be modern TLS with correct validation and no cleartext path, and a test confirms that by watching the app refuse to connect when presented with an untrusted certificate rather than by trusting that the setting is on.
Certificate pinning is worth adding on top for a banking app, because it narrows the set of certificates the app will trust and raises the bar for interception. Treat it as the defense-in-depth measure it is, and plan for rotation, because a pin that is hard-coded and then expires becomes an outage that pushes a team toward shipping a hasty loosening of validation under pressure. Pinning complements correct validation and never replaces it; an app that pins but mishandles the base TLS checks is still exposed.
MASVS-AUTH is authentication and session handling, and here the recurring theme returns in a new form. Biometric sign-in on the device is a convenience that gates access to the local app, and it must never stand in for authentication to the server. The session the server issues has to be the real authority: it expires, it can be revoked, and a stolen or replayed token stops working. On a shared or compromised device, device-side biometric that opens a still-valid server session without re-checking anything is a weak link, so the server, not the fingerprint reader, decides whether the session lives.
Platform interactions and data that leaks sideways
MASVS-PLATFORM is about how the app talks to the operating system and to other apps, through inter-process communication, exported components, deep links, WebViews and permissions. A component exported without meaning to, a WebView configured to run with too much power, a deep link that performs an action without checking who sent it, each hands another app on the same device a way in. The checks are specific: which components are reachable from outside the app, what a WebView is allowed to load and execute, and whether a deep link triggers anything sensitive without authorization.
MASVS-PRIVACY, added in version 2.1, asks what data the app collects and where it goes. For a Saudi app this lands directly on PDPL expectations: collect the minimum, be clear about consent, and know exactly what leaves the device and to whom, including to the analytics and marketing SDKs that developers add without always tracking what those SDKs transmit. A data-flow map of what the app sends, to which third party, with what consent, is both a privacy control and the artifact a regulator will want to see.
Resilience is a speed bump, not a wall
MASVS-RESILIENCE covers root and jailbreak detection, tamper detection, anti-debugging and the rest of the hardening that makes an app harder to analyze and modify. These controls have value, and for a banking app they are worth having, because they raise the cost and slow down casual attempts. The mistake is believing they do more than that.
Watch out
Resilience controls are defense in depth. A determined attacker on a device they fully control can eventually get past client-side hardening, so none of it may be load-bearing. If bypassing your root detection lets someone reach data or an action the server would otherwise refuse, the real defect is that the server trusted the client, and the resilience control was hiding it.
The way to judge a resilience control is to ask what sits behind it. If the answer is a server that independently enforces every rule, then the hardening is a reasonable extra layer. If the answer is a security decision that only the device makes, then the hardening is the only thing protecting it, and that is the finding to write up, regardless of how good the obfuscation is.
The eight groups, and what good evidence looks like
Pulling it together, this is how we structure the test and what we expect a passing control to show. Evidence is the part teams underinvest in, because a control that works but cannot be demonstrated is hard to sign off and harder to put in front of a regulator.
MASVS group
What to check
What good evidence looks like
STORAGE
No sensitive data in plaintext on the device; protected store used; excluded from backups
Inspection showing data stores, backups and caches hold no readable secrets after use
CRYPTO
Modern algorithms, keys in the platform keystore, no hardcoded keys or custom crypto
Key management documented; review confirming keystore-backed keys and platform crypto
AUTH
Authentication and sessions enforced server-side; sessions expire and revoke; biometric gates local access only
Server-side session tests; proof that device biometric cannot bypass server authentication
NETWORK
TLS enforced, certificate validation correct, no cleartext fallback
Capture showing only validated TLS; connection refused on an untrusted certificate
PLATFORM
Safe IPC, WebViews, deep links and permissions; no data exposed to other apps
Review of exported components and WebView config; test that other apps cannot read the data
CODE
Up-to-date platform and dependencies, an enforced update path, validation of untrusted input, no debug code
Dependency inventory and scan; minimum OS and forced-update checks; build inspection confirming no debug endpoints
RESILIENCE
Root, jailbreak and tamper detection present as defense in depth, failing safe
Evidence the controls exist and that bypassing them grants nothing the server would refuse
PRIVACY
Data minimization, clear consent, limits on what goes to third parties and SDKs
Data-flow map of what leaves the device, to whom, with consent records
Test on the devices your customers actually use
A test on one modern flagship running the latest OS tells you about the easiest device to secure and the hardest for an attacker, which is the wrong end of your user base to worry about. In this region the installed base is wide. Plenty of customers run older Android versions on mid-range and budget hardware, and the behavior that matters, how backups work, how the keystore behaves, how the app switcher captures thumbnails, differs across those versions.
Pull the real distribution from your own analytics and build the device pool from it, weighted toward the older and lower-end Android versions a meaningful share of customers still run, plus the iOS versions in active use. Test on real devices rather than only emulators for anything touching storage, the keystore, biometrics or resilience, because those behave differently on physical hardware. And do the honest part of the work on a rooted and a jailbroken device, because that is the only way to assess storage and resilience the way a real attacker would.
Two testing details separate a real result from a reassuring one. Test the upgrade path, not only a fresh install, because data written by an older build in a less safe way can survive an update that would have stored it correctly from scratch, and your existing customers are all on the upgrade path. And account for OEM customization, because the Android running on the popular mid-range handsets in this region is often a manufacturer’s modified build with its own backup, keyboard and cache behavior, so a control verified on a stock image can behave differently on the device a customer actually holds.
Scope the app and its API as one system
The error that undermines more mobile tests than any other is scoping the app alone and leaving its backend out. Most of the serious risk lives at the boundary between them, in exactly the server-side checks the app was trusting the device to make. A test that stops at the app can tell you the token is stored correctly and never find that the API behind it fails to enforce who may call it.
This is also where device-side resilience earns a narrow, honest role. Platform attestation, Play Integrity on Android and App Attest on iOS, lets the server ask whether a request is coming from a genuine, unmodified app on a genuine device, and the server can weigh that answer when it decides how far to trust the request. Used that way, as one input to a server-side decision, it adds real value. Used the other way, as a gate the app alone enforces before proceeding on its own say-so, it collapses back into trusting the client, and a good test makes clear which of the two you actually built.
Both builds in scope: the Android APK or AAB and the iOS build, in a version matching production.
The backing API in scope as well, with test accounts and an environment that mirrors production behavior.
Test accounts at more than one privilege level, and in more than one tenant or customer where that applies.
A pool of real devices covering the Android and iOS versions your analytics show customers actually run.
Agreement to test on rooted and jailbroken devices, which storage and resilience assessment requires.
Clear rules of engagement and data handling, because the test will touch realistic personal and financial data.
Scoped that way, the mobile test and the API test reinforce each other. The app side shows what the device exposes and what it was trusted to decide, and the API side shows whether the server catches it when the device lies. Run them apart and each misses the half the other would have caught, which is usually the half that matters.