Most mobile app security tests either run an automated scanner and call it done, or hand a tester a release build that blocks interception and spend the budget fighting pinning and root detection instead of finding flaws. A useful mobile app penetration test is scoped against the OWASP MASVS, executed with the MASTG, reported in MASWE terms and repeated in the release pipeline. This guide goes deeper than the Mobile App Security Guide on testing: how to scope iOS and Android app testing, what static and dynamic testing and runtime analysis should each cover, how to test certificate pinning and its recovery path, how to evaluate root and jailbreak detection, and how to verify server-side app attestation with Apple App Attest and Play Integrity. It is written for application security engineers, mobile leads and testers, and for the people who commission and accept mobile pentests.
Key takeaways
- Test against a named standard and profile. MASVS v2.1.0 defines 24 controls in eight groups, the MASTG explains how to test them and MASWE names the weaknesses, so scope, findings and retests all use the same IDs.
- Ask for two builds and the source. The MASTG recommends white-box access and a release build to prove defences hold, plus a debug build with some controls off so testing time goes on real flaws.
- Pinning needs a recovery test, not only a bypass test. Verify the backup pin, the rotation runbook and forced update path, or a certificate change becomes an outage.
- On-device checks are signals; the server decides. Root and jailbreak detection can be bypassed with instrumentation, so the test that matters is whether your backend verifies App Attest and Play Integrity correctly and rejects replays.
- Split testing across the pipeline. Fast static checks on every commit, dynamic tests on nightly builds and full MASTG testing before major releases or when authentication, storage or network code changes.
MASVS, MASTG and MASWE: what each is for in a test
The OWASP Mobile Application Security (MAS) project links three resources. The MASVS says what to verify, MASWE describes how each requirement fails, and the OWASP MASTG (the Mobile Application Security Testing Guide, formerly the Mobile Security Testing Guide or MSTG) says how to test for it on Android and iOS. The current MASVS release is v2.1.0, which added the MASVS-PRIVACY group and publishes the standard in CycloneDX format for automation. The MASVS text notes that the profiles were revisited during the 2023 MASVS refactoring and the 2026 MASWE refactoring, so check IDs against the live site when you build a test plan.
| Resource | Role in testing | ID format and example | Use it for |
|---|---|---|---|
| MASVS | Requirements: "what good looks like" | MASVS-NETWORK-2: "The app performs identity pinning for all remote endpoints under the developer's control." | Scope, acceptance criteria, procurement baseline |
| MASWE | Weakness catalogue under the same eight groups | MASWE-0028 Insecure Identity Pinning; MASWE-0051 Root/Jailbreak Detection Not Implemented | Naming findings consistently across testers and years |
| MASTG tests | Test cases per platform and group | MASTG-TEST-0001 Testing Local Storage for Sensitive Data | Executing and evidencing the test |
| MASTG best practices | Fix guidance | MASTG-BEST-0001 Use Secure Random Number Generator APIs | Remediation advice in the report |
The eight MASVS groups are STORAGE, CRYPTO, AUTH, NETWORK, PLATFORM, CODE, RESILIENCE and PRIVACY. Two deserve explicit test plans because scanners handle them badly:
- MASVS-AUTH: AUTH-1 "secure authentication and authorization protocols", AUTH-2 local authentication "according to the platform best practices" and AUTH-3 "additional authentication" for sensitive operations. Test that biometric unlock releases a key store key the server checks rather than returning a boolean (MASWE-0020 Local Authentication Can Be Bypassed), that sensitive transactions cannot fall back to a passcode where policy forbids it (MASWE-0021), and that the API refuses what the UI hides.
- MASVS-CRYPTO: CRYPTO-1 requires "current strong cryptography" and CRYPTO-2 key management "according to industry best practices". Tests look for hard-coded keys and IVs, ECB mode, MD5 or SHA-1 used for security, weak random number generators (MASWE-0012) and keys held outside the Android Keystore or iOS Keychain.
MASVS compliance: the MASVS describes itself as a metric and "a baseline for mobile app security verification during procurement". Compliance means mapping evidence (test results, design documents, threat models) to each control in the chosen profile; the MASVS says applying profiles fully or partially is "a risk-based decision made in consultation with business owners" and that "any deviations from the recommended controls should be carefully justified and documented". For vendors, ask for the profile, the MASTG test IDs run and the deviation register, not a pass badge.
Scoping mobile app penetration testing
The MASTG describes black-box, white-box and grey-box testing and, for apps never tested before, says: "We strongly advise that you request the source code." A mobile app pentest that only sees the store build spends days on reverse engineering that code review would answer in hours.
| Scoping decision | Option | Trade-off |
|---|---|---|
| Knowledge level | White-box (source, design, threat model) or black-box (store build only) | White-box gives the best coverage per day; black-box is realistic for resilience (MAS-R) testing but poor at business logic |
| Builds supplied | Release build plus debug build with selected controls disabled | The MASTG warns pinning and root detection "may impede these tasks"; agree which controls are relaxed before testing starts |
| Profile | MAS-L1, MAS-L2, plus R where reverse engineering is a business threat | Decides how many RESILIENCE tests are in scope and how long the test takes |
| Backend | Include the APIs the app calls | Many serious mobile findings are server-side authorisation flaws; excluding the API leaves them untested |
In mobile penetration testing the MASTG phases are preparation, intelligence gathering, mapping the application, exploitation and reporting. Record the profile, sensitive data types, test accounts per role and rules of engagement for backend testing in preparation, and rate findings on damage potential, reproducibility, exploitability, affected users and discoverability. See the Penetration Testing Guide for rules of engagement and the Penetration Test Scoping Checklist.
Static, dynamic and runtime analysis
The MASVS says apps are analysed "statically by obtaining the app package, dynamically by running it on a potentially compromised device". Each technique finds different flaws; a scanner covers only part of the first.
| Technique | Android app testing focus | iOS app testing focus | Finds best |
|---|---|---|---|
| Static mobile app testing (package and source) | AndroidManifest.xml: android:exported, android:debuggable, android:allowBackup, permissions; network security config; hard-coded keys in code, resources and native libraries | Info.plist ATS exceptions, entitlements, URL schemes and associated domains, privacy manifest, embedded frameworks and their versions | Secrets, misconfiguration, known-vulnerable components (CODE-3), weak crypto calls |
| Dynamic mobile app testing (running app and traffic) | Traffic through an intercepting proxy with a test CA; app-private storage, logs and backups inspected after real use; intents and deep links sent from another app | Traffic interception; Keychain items and their accessibility class; files, caches and snapshots after backgrounding; universal link and URL scheme handling | Data leakage (STORAGE-2), token handling, cleartext traffic, IPC and WebView issues, server-side authorisation |
| Mobile app runtime analysis (instrumented app) | Hooking functions on a rooted test device to observe crypto inputs, key use and decision points | The same on a jailbroken test device | Whether security decisions are made client-side, whether local authentication can be bypassed, resilience effectiveness |
Runtime analysis uses dynamic instrumentation tooling, which attackers also use, so the app's anti-dynamic analysis controls (RESILIENCE-4) should detect instrumentation and report it to the server. The MASTG warns that automated tools "may produce many false positives, particularly if they are not configured for the target environment" and gives browser-centric issues such as CSRF and reflected XSS as examples that rarely apply to native apps. It advises testers not to "blindly trust your scanning tool's output". The Application Security Testing Buyer's Guide covers how to evaluate scanner categories.
Testing certificate pinning and pinning recovery
MASVS-NETWORK-2 requires pinning for endpoints under the developer's control; the related weaknesses are MASWE-0027 Insecure Certificate Validation and MASWE-0028 Insecure Identity Pinning. On Android, a pin set lists SHA-256 hashes of the SubjectPublicKeyInfo, and "a certificate chain is then valid only if the certificate chain contains at least one of the pinned public keys". Testing has two halves: does pinning hold, and can you recover when your own certificates change.
| Test | Pass condition | Common finding |
|---|---|---|
| Interception with a user-installed CA on the release build | Connection fails for every pinned host, including SDK and analytics endpoints you control | Only the login host is pinned; token refresh goes to an unpinned host |
| Debug trust anchors | Test CAs only inside <debug-overrides>, which Android ignores when android:debuggable is false | Test CA left in base-config or overridePins="true" in release |
| Backup pin present | At least one spare key not in current use | Single pin; Android says without a backup "you must push out an update to the app to restore connectivity" |
| Pin expiry | Expiry chosen deliberately or absent, with forced update instead | Expired pin set silently disabling pinning, which Android warns "may enable attackers to bypass your pinned certificates" |
| Failure behaviour | Fails closed, user sees a clear error, event reported | App falls back to an unpinned client or retries over HTTP |
Certificate pinning recovery is an operational test. Walk the runbook: which apps pin which keys, how a backup key is promoted, how long old versions take to age out, and whether MASVS-CODE-2 ("a mechanism for enforcing app updates") can block versions with obsolete pins. Rehearse it on staging by rotating to the backup key. The key and certificate side is covered in the Machine Identity, PKI and Certificate Lifecycle Guide.
Root detection, jailbreak detection and anti-tampering
MASVS-RESILIENCE has four controls: RESILIENCE-1 "validates the integrity of the platform" (root detection and jailbreak detection), RESILIENCE-2 anti-tampering, RESILIENCE-3 anti-static analysis and RESILIENCE-4 anti-dynamic analysis. The MASTG's jailbreak detection knowledge page lists file-based checks, attempts to write outside the sandbox and probes for well-known URL schemes, and states plainly that "these checks can often be circumvented using dynamic instrumentation tools or manual reverse engineering" and that jailbreak detection "is not very effective by itself".
So the test question is not "can the check be bypassed" (it can) but "what does bypassing it gain":
- Placement: checks scattered through the code and repeated, which the MASTG says improves effectiveness, rather than one function with a boolean result.
- Response: the app reports the signal to the server, which degrades high-risk features. Hard blocking on-device punishes legitimate users and stops nobody determined.
- Tamper evidence: a repackaged build re-signed with another key should fail server-side attestation (Play Integrity
UNRECOGNIZED_VERSION, App Attest validation failure), whatever the local checks say. - Instrumentation detection: RESILIENCE-4 checks should notice hooking frameworks and debuggers and feed telemetry, so the security team sees bypass attempts in aggregate.
- Effort recorded: for MAS-R apps, the resilience result is the time and skill needed to defeat the controls, not pass or fail.
Overlay and accessibility abuse by on-device malware is covered in the Mobile Malware Guide.
Server-side app attestation: what to test
Apple puts the principle directly: "You can't rely on your app's logic to perform security checks on itself because a compromised app can falsify the results." App attestation moves the decision to the server, so the server-side verifier is the thing to test. MASWE lists the absence as MASWE-0054 Device Attestation Not Implemented and MASWE-0056 App Attestation Not Implemented.
Apple App Attest
App Attest creates a Secure Enclave key that Apple certifies as belonging to a valid instance of your app. Confirm each server check in Apple's validation procedure:
- Attestation: certificate chain to Apple's App Attest root; nonce in extension OID
1.2.840.113635.100.8.2equals SHA-256 of the authenticator data plus the hash of the one-time server challenge; key identifier equals the SHA-256 of the public key; RP ID hash equals the hash of your App ID; counter equals 0; productionaaguidis "appattest" followed by seven zero bytes; and the validation category and bundle version extensions are checked. - Assertions: signature valid for the stored public key, RP ID matches, counter strictly greater than the previous assertion, and the embedded challenge matches the one issued.
- Binding: a public key must not already be associated with another user; test by replaying an attestation under a second account.
- Fraud metric: store the receipt; Apple's fraud assessment metric counts attested keys per device.
- Lifecycle: keys "don't survive app reinstallation, device migration, or restoration of a device from a backup", so test re-attestation and the fallback for devices where
isSupportedis false.
Play Integrity
| Verdict field | Values | What the server test checks |
|---|---|---|
requestDetails | requestPackageName, requestHash or nonce, timestampMillis | Checked first; replayed or stale tokens rejected; request data hashed before being passed in |
appIntegrity.appRecognitionVerdict | PLAY_RECOGNIZED, UNRECOGNIZED_VERSION, UNEVALUATED | Repackaged build rejected or limited; certificate digest matches your signing key |
deviceIntegrity.deviceRecognitionVerdict | MEETS_BASIC_INTEGRITY, MEETS_DEVICE_INTEGRITY, MEETS_STRONG_INTEGRITY, MEETS_VIRTUAL_INTEGRITY, or empty | Tiered policy per action; empty label (signs of hooking or root) handled; Android 12 and lower strong verdicts not treated as proof of recent patches |
accountDetails.appLicensingVerdict | LICENSED, UNLICENSED, UNEVALUATED | Sideloaded copies handled as policy says |
environmentDetails | appAccessRiskVerdict (capturing, controlling, overlays), playProtectVerdict | High-value actions stepped up when screen capture or control apps are present |
Google says to use it "not as your sole anti-abuse mechanism". Standard requests include replay mitigation; classic requests leave nonce handling to you. The default quota is 10,000 requests per day across all installs, so test behaviour when the quota or the service is unavailable.
Mobile app security testing in the pipeline
The MASTG notes a commit phase "should usually be complete within five minutes, and it shouldn't take longer than ten", which rules out full dynamic testing on every commit. Split the work by speed and by what changed.
- Every commit: static checks for secrets, exported components, debuggable and backup flags, ATS and cleartext exceptions and vulnerable dependencies. Fail the build on new secrets or exported components.
- Nightly: automated dynamic tests on emulators and one physical device per platform, checking traffic for cleartext and unpinned hosts and storage and logs after scripted journeys.
- Change-triggered: manual MASTG tests for the affected group whenever authentication, storage, crypto or networking code changes, and a pinning recovery rehearsal whenever server certificates or CAs change.
- Before major releases: full MASTG testing for the profile, including backend authorisation and attestation verifier tests.
- After release: test the production version and track attestation failure rates by app version to spot repackaged builds.
When adding attestation, start in observe mode and ramp gradually: Apple suggests "no more than 10 million users per day per app" when first enabling App Attest and fewer than 100 attestation requests per second across all installs. Keep enforcement behind a server-side flag so you can roll back without shipping a build. Pipeline controls are covered in the CI/CD Security Guide.
Decision guidance: who tests what
- In-house versus external: in-house teams own pipeline and change-triggered tests; external testers add independence for MAS-L2 and MAS-R apps and for regulator or customer assurance.
- Small organisations: one static scan in CI, a scripted dynamic check before each release and an annual white-box external test cover most risk for MAS-L1 apps. Spend on removing secrets from the app and server-side authorisation before resilience.
- Large or regulated estates: a test plan per app tied to its profile, attestation enforced on high-value endpoints and resilience testing for banking, payments and gaming apps.
- Apps you did not build: enterprises approving third-party apps for managed devices can follow NIST SP 800-163 Rev. 1, which outlines a vetting process to check apps "conform to an organization's security requirements and are reasonably free from vulnerabilities". Device-side policy is in the Mobile Device Security Guide.
Measuring the testing programme
- Coverage: percentage of production apps with a recorded MAS profile and a full MASTG test within the last 12 months.
- Pipeline gate rate: builds blocked by static checks for secrets or exported components, trending down as habits change.
- Time to remediate: median days from finding to fix for high-severity MASWE findings, by app.
- Recurrence: share of findings whose MASWE ID appeared in the same app's previous test.
- Attestation health: percentage of sensitive API calls carrying a verified App Attest assertion or Play Integrity verdict, and failure rate by app version.
Common failure patterns
- Scanner-only testing: a report full of browser-style false positives and none of the API authorisation flaws.
- Secrets found and only removed: testers keep finding cloud keys in packages, as in the Mobile Apps Hard-Coded AWS Keys 2022 research and the iOS Apps Leaking Hard-Coded Secrets 2025 analysis. Every key in a shipped build is exposed: rotate it and move the call behind your backend. See the API Key Management Guide.
- Attestation called but never verified: the app requests a token and the server logs it, or verifies the signature but not the challenge, counter or package, so a captured token replays indefinitely.
- Debug trust left in release: a test CA or
overridePinsin the release configuration quietly disables pinning for anyone who installs that CA. - Pinning with no recovery: a single pinned leaf key, then an emergency certificate replacement that breaks every installed version until users update.
- Resilience as the only defence: root and jailbreak detection presented as the control for fraud, while the backend trusts whatever the client sends.
Framework mapping
| Framework | Reference | How mobile app testing supports it |
|---|---|---|
| NIST SP 800-53 Rev. 5 | SA-11 Developer Testing and Evaluation, SA-11(1) Static Code Analysis, SA-11(8) Dynamic Code Analysis, CA-8 Penetration Testing | Pipeline static and dynamic tests; periodic mobile pentests |
| NIST CSF 2.0 | PR.PS-06 secure software development practices; ID.RA-01 vulnerabilities identified | Testing integrated into the build and release process |
| CIS Controls v8.1 | 16.12 Implement Code-Level Security Checks; 16.13 Conduct Application Penetration Testing | CI checks and authenticated app pentests |
| ISO/IEC 27001:2022 | A.8.25 Secure development life cycle; A.8.29 Security testing in development and acceptance | Test plan per release and acceptance criteria from the MASVS |
Practitioner checklist
- Record a MAS profile (L1, L2, plus R where needed) for every production app, with a deviation register signed by the business owner.
- Scope pentests as white-box or grey-box with release and debug builds, test accounts per role and the backend APIs in scope.
- Require findings in MASVS control and MASWE IDs, with MASTG test references, so retests and trends are comparable.
- Run static checks for secrets, exported components, debuggable and backup flags and ATS or cleartext exceptions on every commit.
- Test every pinned host with a user-installed CA, confirm a backup pin exists and rehearse rotation to it.
- Confirm root, jailbreak and instrumentation detection reports to the server and that high-risk features degrade server-side.
- Test the App Attest verifier for challenge, counter, RP ID, key-to-user binding and receipt storage, and the Play Integrity verifier for request binding, freshness and tiered device policy.
- Rotate and remove any credential a test finds in a shipped build, then add a pipeline rule so it cannot return.
Standards and references
- OWASP: Mobile Application Security Verification Standard (MASVS)
- OWASP: Mobile Application Security Testing Guide (MASTG)
- OWASP: Mobile Application Security Weakness Enumeration (MASWE)
- Apple Developer: Validating apps that connect to your server (App Attest)
- Apple Developer: Establishing your app's integrity
- Android Developers: Play Integrity API integrity verdicts
- Android Developers: Network security configuration
- NIST: SP 800-163 Rev. 1, Vetting the Security of Mobile Applications
Related NHI Mgmt Group resources: Mobile App Security Guide · Penetration Testing Guide · Mobile Device Security Guide · API Security Guide · Application Security Testing Buyer's Guide