This is interesting.

I thought granting internet access to apps is not avoidable on Android.

When an app does not request internet, is it really guaranteed that it cannot talk to the outside world? Or is it having other avenues like opening a browser or some other component with a custom url or something?

Update: I just asked Gemini, and it does not look good:

An Android app without the INTERNET permission is not guaranteed to be isolated from the outside world. While it cannot make direct network connections itself, it can use several other mechanisms to transmit data externally:

Intent-Based Communication (The Browser) An app can launch an explicit or implicit Intent to hand data over to another app that does have internet access.

That means the app can open a system browser using a URL containing the data it wants to transmit.

It can also load a Chrome Custom Tab inside its own UI task, passing data through the URL string.

There is also Inter-Process Communication: If two apps from the same developer share a User ID (sharedUserId), they run in the same process and share all permissions, including internet access.

There is also the concept of Content Providers: Content Providers allow apps to share data. An offline app can write data into a shared database or a public Content Provider. A secondary, online-enabled app can then read that database and upload the contents.

> That means the app can open a system browser using a URL containing the data it wants to transmit.

This can be mitigated by using an app like URLCheck [1], which you set as your default browser, and it shows and lets you edit the URL being opened before handing it off to your real browser. It also has neat features like choosing to open in incognito (if you use Firefox) and automatically removing tracking parameters.

[1] https://f-droid.org/packages/com.trianguloy.urlchecker

This is all very true, unfortunately. Google designed Android as a an OS for internet appliances. They're not interested in local-only apps working on local files.

But I think the OP is to be complimented for what they've built and their intention in making it local-only. I've long felt that apps that *genuinely" respect privacy are one of the few areas of opportunity still left in the mobile space. I wish there were more develpers building things like this.

You're aware that the only really secure computing device has no way to connect to a network and is under armed guard?

Edit: also that LLMs are tuned for "engagement" not for answers like "it's secure enough, move along"?

AOSP allows the internet permission to be denied per app (hence LineageOS and Graphene exposing it), it's just most OEMs ROMs don't expose it, you can draw your own conclusions from that.

I guess that makes sense. Since most non-privacy-focused Android distributions don't let users turn off the internet permission, keeping the permission secure likely ceased to be a priority.

The full list of bypasses is likely much larger because it doesn't fall in the scope of bug bounties.

permission.INTERNET has _never_ been a dangerous permission on android.

GrapheneOS asks for internet permission when you install any app.

Can you deny it and is the situation the same as on Android?

You can on graphene. It's not uncommon to use Google keyboard this way for example.

Even an app that does not want internet?

No, it only asks if the app requests the internet permission.

I don't see that as an option, but I'm not a GrapheneOS power user.

Why post AI-generated answers? Anyone reading your comment could do the same.

"I just asked Gemini, and it turns out that Mossad can steal my data anyways".

- An app without the INTERNET permission will crash the moment you try to access the internet. It's like a rite of passage of every android developer with every new project, you forgot the permission.

- Launching an Intent is EXTREMELY visible. It opens a full on browser. It's limited to a GET with a dedicated URL, so what are they going to do, stuff your data in query params ?

- Even in the case of another app being installed that would silently receive this intent and not pop an activity, you need a different app. It cannot be an activity added by the same package.

- Loading a Chrome Custom Tab opens a whole ass browser in front of you, think you're going to miss it ?

- Shared user IDs also require two different app installations and you cannot declare multiple. You also cannot have sharedUserId if you do not sign the apps with the same key. you cannot sharedUserId with Facebook, you need once again a dedicated app installation.

- A ContentProvider needs a dedicated permission on the writing app AND on the reading app, which is once again very visible.

I'll add more to your list: an app can request to write a file inside your downloads folder, and another one can show a popup asking you to open it! And if someone shows up with a hammer at your door, he can also hit your fingers really hard to make you tell him the data.

Android apps are, by default, very well isolated. INTERNET is a permission like any other, just not surfaced as a dangerous one (like permanent access to your background location would be), or a runtime one (like access to your current location while the app is in foreground)

It's insane that after four years of these tools being ubiquitous people still defer to them for their own critical thinking

I use a rooted phone and afwall+ which uses the underlying Linux firewall. There's also the mobile and WiFi data permissions you can change manually.

How is the rooted experience these days? Do you deal with broken (banking) apps all the time?

I don't use banking apps, my banks have websites that work. Last time I tried to add my bank card to the Google wallet, it worked for a few days and then stopped. I've had a few apps that refuse to run but then worked fine with magisk.

For me, root on my own devices is a matter of principle. If an app doesn't work, then I don't want it. In the future I might carry a gimped android device for essential things like train apps if I have to, but then it won't be the device I actually carry in my pocket, it'll be in my bag. Mobile computing is for me.

Christ that's depressing.

I'm assuming that all works even with application sandboxing (1) or am I mis-reading how that is applied to applications.

Man I need to move my movement to GrapheneOS up to be sooner.

(1) https://source.android.com/docs/security/app-sandbox

Yeah, Android's sandbox deals with low-level file access and socket APIs and stuff. But Android also, intentionally, allows apps to expose their data and functionality to other apps via the higher-level "intent" system.

Apps get to choose what permissions are needed to access their intents, so under Android's security model, really it's Chrome's fault (or whatever browser the user has installed) for exposing an intent that allows apps that don't have the INTERNET permission to exfoltrate data.

Similarly, apps are also allowed to collude to share data with each other if they want; that's how stuff like Google Play Services works.

> Apps get to choose what permissions are needed to access their intents, so under Android's security model, really it's Chrome's fault (or whatever browser the user has installed) for exposing an intent that allows apps that don't have the INTERNET permission to exfoltrate data.

You might as well blame the phone for not being encased in concrete and thrown into a well. You might not want your text message application to have the internet permission, but you'd certainly want to be able to open links from it.

As I understand it, this "Application Sandbox" is to prevent app A seeing what app B is doing.

The problem here is a different one: The user granting an app access to their files and then having no way to prevent that app from sending that data to the developer of the app.

> If two apps from the same developer share a User ID (sharedUserId), they run in the same process and share all permissions

Good grief. What a huge vulnerability. Is there some benefit that justifies this?

First, `sharedUserId` is opt-in.

You need something like that for plugin / extension like system.

Third, it is being deprecated. and people are screaming "bad google" "android is no longer free!"

> First, `sharedUserId` is opt-in.

By the user?

> You need something like that for plugin / extension like system.

Plugin/extension != app.

Literally there for more protection. Split your app into different apps, each handling a component. Want a banking app, without access to registering your card for NFC payments ? Split the app.

sharedUserIds cannot be applied blindly, they need the app to be signed with the same key, both need to declare their sharedUserId to be the same, etc.

Yeah fair I was too flat in the post... No INTERNET means my process can't reach the network. It doesn't stop an app passing data to something that can, so your list is right.

It's not a guarantee then, it's just a lot less to check. There's no silent route out so all that's left is what the app chooses to send via intents and Gander sends two, both when you tap something ("Share" and "Show in file manager")

Nothing anywhere builds a URL out of the file contents. No browser launch, no Custom Tabs and no shared user ID. The only content provider is closed to other apps. The one time a file goes anywhere is when you hit Share and pick the app, and what it gets is read access to that one file.

In case you grep it there's an https:// in ViewerActivity.kt. That's the local virtual host WebViewAssetLoader serves the bundled renderers from, it never leaves the process.