Android Network Security Configuration Review
Android Network Security Configuration is XML policy consumed by supported Android networking stacks when application manifest references it with android:networkSecurityConfig. It can define cleartext behavior, trust anchors, domain-specific rules, certificate pinning, and debug-only trust anchors. It does not fix custom TrustManager, WebView behavior outside its scope, or server-side authorization. Verify installed release APK, because manifest merging and resource selection can differ from source review.
Start record with package name, version code, signing digest, flavor, min and target SDK, device API level, tested hostname, evaluator, and date. Extract manifest and effective XML from APK or app bundle output. Also enumerate every HTTP client, third-party SDK, WebView, and native library because policy coverage can vary by implementation.
Start closed, then make narrow exceptions
A release baseline can deny cleartext and use system trust anchors. Domain-specific configuration should express exceptional hosts only. This simplified example has no general HTTP exception:
<network-security-config>
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>
<domain-config>
<domain includeSubdomains="true">api.example.test</domain>
</domain-config>
</network-security-config>
A tester must attempt http:// against every in-scope hostname and verify it fails in release. usesCleartextTraffic is also relevant, but effective behavior depends on Android version, target SDK, client stack, and network security configuration. Treat source attribute alone as incomplete evidence.
Trust anchors deserve explicit test. A <certificates src="system" /> set relies on platform system CAs. Adding src="user" changes whether user-installed certificates are trusted for covered connections. Do not add it to make proxy testing convenient. If a private enterprise CA is required, scope it to exact domain, document ownership and expiry, test hostname and chain validation, and remove it when unnecessary. Acceptance is observed connection behavior on release build, not XML appearance.
Keep debug trust separate
<debug-overrides> permits extra trust anchors only while android:debuggable is true. It supports local interception without carrying test trust into production. Example:
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
<debug-overrides>
<trust-anchors>
<certificates src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>
Inspect both debug and release APK manifests. On release, attempt connection through a proxy using a user-installed test CA; expected result depends on approved release trust policy, but debug override must not be effective merely because a debug resource was merged. Record proxy certificate fingerprint, device setup, request hostname, and result. Never treat failed interception as proof of secure validation without testing expired, wrong-host, and untrusted chains where authorized.
Pinning is an availability commitment
A pin-set can constrain a domain to listed public-key pins and supports expiration. Include at least one backup pin for planned key rotation, protect source and release process for pins, and rehearse rotation before deploying. Example placeholders only:
<domain-config>
<domain>api.example.test</domain>
<pin-set expiration="2027-01-01">
<pin digest="SHA-256">PRIMARY_BASE64_PIN</pin>
<pin digest="SHA-256">BACKUP_BASE64_PIN</pin>
</pin-set>
</domain-config>
Pinning can cause outage when certificate or key changes unexpectedly; expiration also changes behavior. MASVS-NETWORK-2 should therefore be evaluated against threat model, operational ownership, and recovery ability, not adopted as decorative XML. Test primary pin, backup pin, wrong pin, expired policy, and rotation on representative clients. Do not hard-code pin values from this article.
Release acceptance and evidence
| Check | Completed artifact | Owner | Pass acceptance |
|---|---|---|---|
| Manifest linkage | Extracted release manifest and XML digest. | Build owner | Release references reviewed config. |
| Cleartext | HTTP test transcript for each hostname. | Network owner | Unapproved HTTP connection fails. |
| Trust anchors | System, user, and private-CA test matrix. | Android owner | Only approved anchors validate. |
| Debug policy | Debug/release APK comparison and proxy results. | Release owner | Debug override is ineffective in release. |
| Pinning | Pin inventory, rotation drill, expiry calendar. | Service owner | Required pins have tested backup and recovery. |
| Runtime coverage | Client/SDK inventory with coverage notes. | Engineering owner | Out-of-policy client is fixed or recorded as exception. |
Result is pass only with artifact and acceptance. Fail includes accepted cleartext, unintended user/debug CA trust, bypassed hostname validation, or unplanned pin outage. Not verified is not pass. Exception needs affected host and build, reason, data risk, compensating control, accountable owner, approval, expiry, and remediation date. Fix by removing broad trust, splitting resources by variant, narrowing domain scope, correcting client code, or planning pin rotation. Rebuild and rerun same matrix before closure.
OWASP MASVS and Android documentation are technical references, not certification. Mobile application testing can validate agreed release scope.
Worked transport test and closure
Inspect merged release manifest and resolved networkSecurityConfig, then test each permitted domain with a trusted and untrusted certificate. A command such as adb shell dumpsys package com.example.shop helps preserve installed package context; expected result is release build references intended policy and cleartext traffic is unavailable except for documented development-only scope. Capture proxy or server evidence with synthetic request, never production credentials.
Test negative cases: HTTP URL, hostname mismatch, expired certificate, user-installed CA, and redirect to unlisted host. Expected result is connection refusal or controlled application error before sensitive request data is sent. Certificate pinning needs special care: pin rotation overlap must be planned; a single old pin can turn ordinary certificate renewal into outage. Network policy cannot replace server identity checks or authorization.
Close with merged manifest hash, policy XML, device/API, tested hosts, observed denial output, documented exception expiry, and release owner. Reopen when domains, SDK networking stack, target SDK, certificate authority, or build variant changes.
Verify effective release policy
Extract installed release manifest and configuration resource, then test approved HTTPS endpoint and intentionally cleartext endpoint from same build. Expected HTTPS request succeeds with trusted certificate; expected HTTP request fails because cleartext is not permitted. Repeat with user-installed CA only where test policy permits, expired certificate, and hostname mismatch. Record URL class, device API level, network state, error class, build digest, owner, pass/fail, and exception expiry. A debug override present in release artifact is fail, not a test convenience.
Verify effective release policy
Extract installed release manifest and configuration resource, then test approved HTTPS endpoint and intentionally cleartext endpoint from same build. Expected HTTPS request succeeds with trusted certificate; expected HTTP request fails because cleartext is not permitted. Repeat with user-installed CA only where test policy permits, expired certificate, and hostname mismatch. Record URL class, device API level, network state, error class, build digest, owner, pass/fail, and exception expiry. A debug override present in release artifact is fail, not a test convenience.