August 6, 2026
Network Security Config Deep Dive (Android)
Part 2 of our Android security series. Part 1 covered the OWASP MASVS/MASTG checklist — this post zooms into one piece of it: the NETWORK…

By Khizar Khan
2 min read
Part 2 of our Android security series. Part 1 covered the OWASP MASVS/MASTG checklist — this post zooms into one piece of it: the NETWORK category.
What it is, in one line
Network Security Config (NSC) is a small XML file where you tell Android which domains your app can talk to, and how strictly, without touching a line of code.
Why it exists
Since Android 9 (API 28), Android blocks plain HTTP by default. That's good — but real apps still need exceptions sometimes (a debug server, a legacy API, a local dev IP). Instead of hacking this into your networking code, Android gives you one XML file to declare the rules. Security reviewers love this because they can read your entire network policy in 20 seconds, without reading your app's code.
The absolute basics
1. Create the file: res/xml/network_security_config.xml
2. Point to it from your manifest:
<application
android:networkSecurityConfig="@xml/network_security_config"
... ><application
android:networkSecurityConfig="@xml/network_security_config"
... >That's it — Android now enforces whatever you write in that file.
Example 1: Block HTTP everywhere (the default you want)
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
</network-security-config><?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
</network-security-config>This says: "no app-wide HTTP, full stop, HTTPS only." If you're not sure what to put in your config file, start here.
Example 2: Allow HTTP for one domain only
Say your production API is HTTPS, but your app also hits a legacy partner API that's still stuck on HTTP. Don't weaken security for the whole app — scope the exception to just that domain:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">legacy-partner.example.com</domain>
</domain-config>
</network-security-config><?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">legacy-partner.example.com</domain>
</domain-config>
</network-security-config>Everything is HTTPS-only except legacy-partner.example.com. That's the core idea of NSC: set a strict default, then carve out narrow, named exceptions — never the other way around.
Example 3: Allow HTTP for your local dev server (debug builds only)
This is the one almost every Android dev needs at some point — talking to 10.0.2.2 (the emulator's alias for your machine) or a local test server:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">10.0.2.2</domain>
</domain-config>
</network-security-config><?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">10.0.2.2</domain>
</domain-config>
</network-security-config>Important: keep this in a debug-only resource folder (src/debug/res/xml/), not your main one. You don't want this cleartext exception shipping in your release build. This is one of the most common findings in mobile security reviews — a "temporary" debug exception that quietly made it to production.
What else NSC can do (quick overview)
Beyond cleartext rules, the same file can also:
- Pin certificates for specific domains (we will cover this in Part 3 — Certificate Pinning in Production)
- Restrict which Certificate Authorities your app trusts, instead of trusting every CA on the device
- Set different rules per domain — strict for your API, relaxed for a CDN, etc.
The one-line takeaway
Default to cleartextTrafficPermitted="false" at the base level, and only ever add narrow, named, domain-specific exceptions — ideally scoped to debug builds when possible. If a security reviewer opens your network_security_config.xml and sees a blanket cleartextTrafficPermitted="true" in the base config, that's usually the first thing they'll flag.
Next up in the series: Certificate Pinning in Production.