An APK is a ZIP file, and your HTML, CSS and JavaScript sit inside it in plain text, readable by anyone who renames and extracts it. That is the one security fact to organise everything else around: nothing in the bundle is secret. A bundled HTML app is otherwise in a reasonably safe position — it has no server to attack, its data is in a private directory other apps cannot read, and its permissions are only what you declared. The risks are the ones you ship yourself: an API key in a script, a password check in JavaScript, content that was meant to be paid for. Each has a standard answer.
Never put a secret in the bundle
This includes: API keys for paid services, database credentials, a "master password", private endpoints, unreleased content. If the app needs to call a service that requires a key, the key must live on a server you control and the app must call your server, which adds the key and forwards the request. A key in the JavaScript is a key on the internet within a day of the app being popular — automated scanners extract them from APKs routinely.
Public keys — a Firebase web config, a Google Maps browser key restricted to your package name, an analytics ID — are designed to ship in clients and are fine. The test: if the provider's documentation says to put it in front-end code and lets you restrict it, it is a public key.
Logins that live in JavaScript are not logins
if (password === 'letmein') in a bundled script is a suggestion, not a lock: the user can read the password, or edit the check out. The same goes for a hidden "premium" section toggled by a flag. If access control matters, it needs a server that checks credentials and returns the protected content only after; if it does not really matter — a family app, a classroom tool — a client-side gate is fine as long as you know that is what it is.
What the phone protects
- The app's data directory (localStorage, IndexedDB, cookies) is private to the app on an unrooted phone. Other apps cannot read it; a backup or a rooted device can. So: fine for the user's own notes and settings, wrong for anything that would hurt if extracted — tokens, card numbers, health data. Encrypt those in the app if you must store them, or better, do not.
- Permissions are enforced by Android. If you did not switch on the camera permission, no script in the app can use the camera. Declare the minimum: every unused permission is a question at Play review and a worry for the user.
- Sandboxing. The WebView cannot reach the file system, other apps or the network beyond what a browser could. An HTML app cannot become malware by accident.
Network calls, if any
If the app talks to your API, use HTTPS only. The builder's shell blocks mixed content by default — an http:// request from a bundled page fails — which is the right default; do not turn it off. Treat everything from the network as untrusted, the same as on the web: insert it into the page with textContent, not innerHTML, unless it is HTML you generated and trust.
User input inside the app
The classic web risk, cross-site scripting, is smaller in a bundled app — there is no site for a third party to inject into — but not zero if your app renders content from other users or from the network. Escape it. If the app lets users paste HTML on purpose (a notes app with formatting), render it in a sandboxed <iframe srcdoc> or strip scripts with a sanitiser you bundle.
The habits
- Before every build, search the folder for
key,secret,passwordandtoken. The minifier also strips comments, which is where "TODO remove this key" tends to live. - Keep the keystore and its password out of the project folder and out of any repository.
- Declare only the permissions the page uses.
- HTTPS for every request; mixed content stays blocked.
- Write the privacy policy from what the app really does, and keep it true as the app changes. App Privacy Policy GeneratorA privacy policy for an HTML app, written from what your app actually does Open the tool