This page contains answers to frequently asked questions about GrapheneOS. It's not an overview of the project or a list of interesting topics about GrapheneOS. Many of the answers would be nearly the same or identical for the latest release of the Android Open Source Project. The goal is to provide high quality answers to some of the most common questions about the project, so the developers and other community members can link to these and save lots of time while also providing higher quality answers.
GrapheneOS has official production support for the following devices:
- Pixel 7 Pro (cheetah)
- Pixel 7 (panther)
- Pixel 6a (bluejay)
- Pixel 6 Pro (raven)
- Pixel 6 (oriole)
- Pixel 5a (barbet)
- Pixel 5 (redfin)
- Pixel 4a (5G) (bramble)
- Pixel 4a (sunfish)
The following devices are end-of-life, no longer receive full security updates and are supported via extended support releases of GrapheneOS:
- Pixel 4 XL (coral)
- Pixel 4 (flame)
We provide extended support releases as a stopgap for users to transition to the far more secure current generation devices.
The release tags for these devices have official builds and updates available. These devices meet the stringent privacy and security standards and have substantial upstream and downstream hardening specific to the devices.
Many other devices are supported by GrapheneOS at a source level, and it can be built for them without modifications to the existing GrapheneOS source tree. Device support repositories for the Android Open Source Project can simply be dropped into the source tree, with at most minor modifications within them to support GrapheneOS. In most cases, substantial work beyond that will be needed to bring the support up to the same standards. For most devices, the hardware and firmware will prevent providing a reasonably secure device, regardless of the work put into device support.
GrapheneOS also supports generic targets, but these aren't suitable for production usage and are only intended for development and testing use. For mobile devices, the generic targets simply run on top of the underlying device support code (firmware, kernel, device trees, vendor code) rather than shipping it and keeping it updated. It would be possible to ship generic system images with separate updates for the device support code. However, it would be drastically more complicated to maintain and support due to combinations of different versions and it would cause complications for the hardening done by GrapheneOS. The motivation doesn't exist for GrapheneOS, since full updates with deltas to minimize bandwidth can be shipped for every device and GrapheneOS is the only party involved in providing the updates. For the same reason, it has little use for the ability to provide out-of-band updates to system image components including all the apps and many other components.
Some of the GrapheneOS sub-projects support other operating systems on a broader range of devices. Device support for Auditor and AttestationServer is documented in the overview of those projects. The hardened_malloc project supports nearly any Linux-based environment due to official support for musl, glibc and Bionic along with easily added support for other environments. It can easily run on non-Linux-based operating systems too, and supporting some like HardenedBSD is planned but depends on contributors from those communities.
We strongly recommend only purchasing one of the following devices for GrapheneOS due to better security and a minimum 5 year guarantee from launch for full security updates and other improvements:
- Pixel 7 Pro
- Pixel 7
- Pixel 6a
- Pixel 6 Pro
- Pixel 6
Newer devices have more of their 5 year minimum guarantee remaining but the actual support time may be longer than the minimum guarantee.
The Pixel 7 and Pixel 7 Pro are all around improvements over the Pixel 6 and Pixel 6 Pro with a significantly better GPU and cellular radio along with an incremental CPU upgrade. The 7th generation Pixels are far more similar to the previous generation than any prior Pixels.
The Pixel 6 and Pixel 6 Pro are flagship phones with much nicer hardware than previous generation devices (cameras, CPU, GPU, display, battery).
The cheaper Pixel 6 has extremely competitive pricing for the flagship level hardware especially with the guaranteed long term support. Pixel 6 Pro has 50% more memory (12GB instead of 8GB), a higher end screen, a 3rd rear camera with 4x optical zoom and a higher end front camera. Both devices have the same SoC (CPU, GPU, etc.) and the same main + ultrawide rear cameras. The Pixel 6 is quite large and the Pixel 6 Pro is larger.
The Pixel 6a is a budget device with the same 5 years of guaranteed full security support from launch as the flagship 6th generation Pixels. It also has the same flagship SoC as the higher end devices, the same main rear and front cameras as the Pixel 5 and a rear wide angle lens matching the flagship 6th generation Pixels. Compared to the 5th generation Pixels, it has 5 years of full security support remaining instead of less than 2 years and the CPU is 2x faster. We strongly recommend buying the Pixel 6a rather than trying to get a deal with older generation devices. You'll be able to use the Pixel 6a much longer before it needs to be replaced due to lack of support.
Devices are carefully chosen based on their merits rather than the project aiming to have broad device support. Broad device support is counter to the aims of the project, and the project will eventually be engaging in hardware and firmware level improvements rather than only offering suggestions and bug reports upstream for those areas. Much of the work on the project involves changes that are specific to different devices, and officially supported devices are the ones targeted by most of this ongoing work.
Devices need to be meeting the standards of the project in order to be considered as potential targets. In addition to support for installing other operating systems, standard hardware-based security features like the hardware-backed keystores, verified boot, attestation and various hardware-based exploit mitigations need to be available. Devices also need to have decent integration of IOMMUs for isolating components such as the GPU, radios (NFC, Wi-Fi, Bluetooth, Cellular), media decode / encode, image processor, etc., because if the hardware / firmware support is missing or broken, there's not much that the OS can do to provide an alternative. Devices with support for alternative operating systems as an afterthought will not be considered. Devices need to have proper ongoing support for their firmware and software specific to the hardware like drivers in order to provide proper full security updates too. Devices that are end-of-life and no longer receiving these updates will not be supported.
In order to support a device, the appropriate resources also need to be available and dedicated towards it. Releases for each supported device need to be robust and stable, with all standard functionality working properly and testing for each of the releases.
Hardware, firmware and software specific to devices like drivers play a huge role in the overall security of a device. The goal of the project is not to slightly improve some aspects of insecure devices and supporting a broad set of devices would be directly counter to the values of the project. A lot of the low-level work also ends up being fairly tied to the hardware.
Broader device support can only happen after the community (companies, organizations and individuals) steps up to make substantial, ongoing contributions to making the existing device support sustainable. Once the existing device support is more sustainable, early research and development work for other devices can begin. Once a device is deemed to be a worthwhile target, the project needs maintainers to develop and maintain support for it including addressing device-specific issues that are uncovered, which will include issues uncovered in the device support code by GrapheneOS hardening features.
It's not really a matter of time but rather a need for community support for the project increasing. As an open source project, the way to get something to happen in GrapheneOS is to contribute to it, and this is particularly true for device support since it's very self-contained and can be delegated to separate teams for each device. If you want to see more devices supported sooner, you should get to work on identifying good devices with full support for alternative operating systems with verified boot, etc. and then start working on integrating and testing support.
It should also be clear that the expectation is for people to buy a device to run GrapheneOS, rather than GrapheneOS supporting their existing devices. This will only become more true if GrapheneOS is successful enough to accomplish the goal of having devices produced based on an SoC reference design with minor improvements for privacy and security. Broad device support is the opposite of what the project wants to achieve in the long term.
GrapheneOS aims to provide reasonably private and secure devices. It cannot do that once device support code like firmware, kernel and vendor code is no longer actively maintained. Even if the community was prepared to take over maintenance of the open source code and to replace the rest, firmware would present a major issue, and the community has never been active or interested enough in device support to consider attempting this. Unlike many other platforms, GrapheneOS has a much higher minimum standard than simply having devices fully functional, as they also need to provide the expected level of security. It would start to become realistic to provide substantially longer device support once GrapheneOS controls the hardware and firmware via custom hardware manufactured for it. Until then, the lifetime of devices will remain based on manufacturer support. It's also important to keep in mind that phone vendors claiming to provide longer support often aren't actually doing it and some never even ship firmware updates when the hardware is still supported by the vendors...
GrapheneOS also has high standards for the privacy and security properties of the hardware and firmware, and these standards are regularly advancing. The rapid pace of improvement has been slowing down, but each hardware generation still brings major improvements. Over time, the older hardware starts to become a substantial liability and holds back the project. It becomes complex to simply make statements about the security of the project when exceptions for old devices need to be listed out. The project ends up wanting to drop devices for this reason but has always kept them going until the end-of-life date to provide more time for people to migrate.
The following devices are no longer supported:
- Pixel 3a XL (bonito)
- Pixel 3a (sargo)
- Pixel 3 XL (crosshatch)
- Pixel 3 (blueline)
- Pixel 2 XL (taimen)
- Pixel 2 (walleye)
- Pixel XL (marlin)
- Pixel (sailfish)
- Nexus 6P (angler)
- Nexus 5X (bullhead)
- Nexus 9 (flounder)
- Nexus 5 (hammerhead)
- Samsung Galaxy S4 (jflte)
GrapheneOS also used to provide official source-level support for the following development boards but dropped support due to lack of community interest and lack of hardware availability:
- HiKey 960 (hikey960)
- HiKey (hikey)
GrapheneOS can only fully provide security updates to a device provided that the OEM is releasing them. When an OEM is no longer providing security updates, GrapheneOS aims to provide harm reduction releases for devices which only have a minimum of 3 years support. Extended support updates at minimum will be done until the next Android version. It is likely that we will make a decision around harm reduction releases for other devices with longer lifetimes in Q4 2024. Harm reduction releases do not have complete security patches because it's not possible to provide full security updates for the device without OEM support and they are intended to buy users some limited time to migrate to a supported device.
|Device||OEM minimum support end||OEM minimum support length|
|Google Pixel 7 Pro||October 2027||5 years|
|Google Pixel 7||October 2027||5 years|
|Google Pixel 6a||July 2027||5 years|
|Google Pixel 6 Pro||October 2026||5 years|
|Google Pixel 6||October 2026||5 years|
|Google Pixel 5a||August 2024||3 years|
|Google Pixel 5||October 2023||3 years|
|Google Pixel 4a 5G||November 2023||3 years|
|Google Pixel 4a||August 2023||3 years|
|Google Pixel 4||October 2022||3 years|
|Google Pixel 4 XL||October 2022||3 years|
GrapheneOS uses an enhanced version of the modern filesystem-based disk encryption implementation in the Android Open Source Project. The officially supported devices have substantial hardware-based support for enhancing the security of the encryption implementation. GrapheneOS has full support for the hardware-based encryption features just as it does with other hardware-based security features.
Firmware and OS partitions are identical copies of the images published in the official releases. The authenticity and integrity of these partitions is verified from a root of trust on every boot. No data is read from any of these images without being cryptographically verified. Encryption is out of scope due to the images being publicly available. Verified boot offers much stronger security properties than disk encryption. Further details will be provided in another section on verified boot in the future.
The data partition stores all of the persistent state for the operating system. Full disk encryption is implemented via filesystem-based encryption with metadata encryption. All data, file names and other metadata is always stored encrypted. This is often referred to as file-based encryption but it makes more sense to call it filesystem-based encryption. It's implemented by the Linux kernel as part of the ext4 / f2fs implementation rather than running a block-based encryption layer. The advantage of filesystem-based encryption is the ability to use fine-grained keys rather than a single global key that's always in memory once the device is booted.
Disk encryption keys are randomly generated with a high quality CSPRNG and stored encrypted with a key encryption key. Key encryption keys are derived at runtime and are never stored anywhere.
Sensitive data is stored in user profiles. User profiles each have their own unique, randomly generated disk encryption key and their own unique key encryption key is used to encrypt it. The owner profile is special and is used to store sensitive system-wide operating system data. This is why the owner profile needs to be logged in after a reboot before other user profiles can be used. The owner profile does not have access to the data in other profiles. Filesystem-based encryption is designed so that files can be deleted without having the keys for their data and file names, which enables the owner profile to delete other profiles without them being active.
GrapheneOS enables support for ending secondary user profile sessions after logging into them. It adds an end session button to the lockscreen and in the global action menu accessed by holding the power button. This fully purges the encryption keys and puts the profiles back at rest. This can't be done for the owner profile without rebooting due to it encrypting the sensitive system-wide operating system data.
Using a secondary profile for regular usage allows you to make use of the device without decrypting the data in your regular usage profile. It also allows putting it at rest without rebooting the device. Even if you use the same passphrase for multiple profiles, each of those profiles still ends up with a unique key encryption key and a compromise of the OS while one of them is active won't leak the passphrase. The advantage to using separate passphrases is in case an attacker records you entering it.
File data is encrypted with AES-256-XTS and file names with AES-256-CTS. A unique key is derived using HKDF-SHA512 for each regular file, directory and symbolic link from the per-profile encryption keys, or the global encryption key for non-sensitive data stored outside of profiles. The directory key is used to encrypt the file names. GrapheneOS increases the file name padding from 16 bytes to 32 bytes. AES-256-XTS with the global encryption key is also used to encrypt filesystem metadata as a whole beyond the finer-grained file name encryption.
The OS derives a password token from the profile's lock method credential using scrypt. This is used as the main input for key derivation.
The OS stores a high entropy random value as the Weaver token on the secure element (Titan M on Pixels) and uses it as another input for key derivation. The Weaver token is stored alongside a Weaver key derived by the OS from the password token. In order to retrieve the Weaver token, the secure element requires the correct Weaver key. A secure internal timer is used to implement hardware-based delays for each attempt at key derivation. It quickly ramps up to 1 day delays before the next attempt. Weaver also provides reliable wiping of data since the secure element can reliably wipe a Weaver slot. Deleting a profile will wipe the corresponding Weaver slot and a factory reset of the device wipes all of the Weaver slots. The secure element also provides insider attack resistance preventing firmware updates before authenticating with the owner profile.
Standard delays for encryption key derivation enforced by the secure element:
- 0 to 4 failed attempts: no delay
- 5 failed attempts: 30 second delay
- 6 to 9 failed attempts: no delay
- 10 to 29 failed attempts: 30 second delay
- 30 to 139 failed attempts: 30 × 2⌊(n - 30) ÷ 10⌋ where n is the number of failed attempts. This means the delay doubles after every 10 attempts. There's a 30 second delay after 30 failed attempts, 60s after 40, 120s after 50, 240s after 60, 480s after 70, 960s after 80, 1920s after 90, 3840s after 100, 7680s after 110, 15360s after 120 and 30720s after 130
- 140 or more failed attempts: 86400 second delay (1 day)
Invalid input outside the minimum or maximum length limits of the UI won't trigger an attempt at authentication or key derivation.
GrapheneOS only officially supports devices with Weaver. The fallback implementation for devices without it is out-of-scope for this FAQ.
The password token, Weaver token and other values like the OS verified boot key are used by the TEE as inputs to a hardware-bound key derivation algorithm provided by the SoC. The general concept is having the SoC perform hardware accelerated key derivation using an algorithm like AES or HMAC keyed with a hard-wired hardware key inaccessible to software or firmware. This is meant to prevent offloading a brute force attack onto more powerful hardware without an expensive process of extracting the hardware key from the SoC.
Many apps use the hardware keystore, their own encryption implementation or a combination of those to provide an additional layer of encryption. As an example, an app can use the hardware keystore to encrypt their data with a key only available when the device is unlocked to keep their data at rest when the profile is locked but not logged out. This is beyond the scope of this FAQ section.
As of Android 10, only the configured default input method editor (your keyboard of choice) and the currently focused app can access the clipboard. Apps without focus cannot access the clipboard. This is a stricter restriction than preventing apps in the background from accessing it, since an app in the foreground or a foreground service cannot access it, only the foreground app that's currently focused. Clipboard managers need to be implemented by the keyboard chosen as the default by the user.
GrapheneOS previously restricted background clipboard access as a much earlier and slightly less strict implementation of this feature. It provided a toggle for users to whitelist clipboard managers, which is no longer needed now that keyboards are expected to provide it.
As of Android 12, the user is notified when an app reads clipboard content which was set by a different app. This notice is enabled by default and can be toggled under Settings ➔ Privacy ➔ Show clipboard access.
As of Android 10, apps cannot obtain permission to access non-resettable hardware identifiers such as the serial number, MAC addresses, IMEIs/MEIDs, SIM card serial numbers and subscriber IDs. Only privileged apps included in the base system with
READ_PRIVILEGED_PHONE_STATE whitelisted can access these hardware identifiers. Apps targeting Android 10 will receive a
SecurityException and older apps will receive an empty value for compatibility.
Since these restrictions became standard, GrapheneOS only makes a small change to remove a legacy form of access to the serial number by legacy apps, which was still around for compatibility. It used to need more extensive changes such as disallowing access to the serial number but those restrictions are now standard.
Apps can determine the model of the device (such as it being a Pixel 6) either directly or indirectly through the properties of the hardware and software. There isn't a way to avoid this short of the OS supporting running apps in a virtual machine with limited functionality and hardware acceleration. Hiding the CPU/SoC model would require not even using basic hardware virtualization support and these things could probably still be detected via performance measurements.
In addition to not having a way to identify the hardware, apps cannot directly identify the installation of the OS on the hardware. Apps only have a small portion of the OS configuration exposed to them and there is not much for device owners to change which could identify their installation. Apps can detect that they're being run on GrapheneOS via the privacy and security features placing further restrictions on them and hardening them against further exploitation. Apps can identify their own app installation via their app data and can directly (until that's removed) or indirectly identify a profile. Profiles should be used when separate identities are desired. Profiles can be used as temporary ephemeral identities by creating them for a specific need and then deleting them. The rest of this answer only provides more technical details, so you can stop reading here if you only want an overview and actionable advice (i.e. use profiles as identities not inherently tied to each other).
Examples of the global OS configuration available to apps are time zone, network country code and other similar global settings. Per-profile examples are dark mode and language. Similar to extension and browser configuration / state being fingerprinted by web sites, an app could use a combination of these things in an attempt to identify the installation. All of these things vary at runtime and can be changed, but some are fairly unlikely to change in practice after the initial setup of the device such as the ones listed above. GrapheneOS will likely add further restrictions in this area and a couple toggles for certain cases like time zones to use a standard value instead.
Apps can generate their own 128-bit or larger random value and use that as an identifier for the app installation. Apps can create data in their app-specific external storage directory by default without needing permission, and in the legacy storage model before API 29 that data persists after the app is uninstalled, so it can be used to store an ID that persists through the app being uninstalled and reinstalled. However, external storage is under control of the user and the user can delete this data at any time, including after uninstalling the app. In the modern storage model, this data is automatically removed when the app is uninstalled. GrapheneOS includes Seedvault as an OS backup service which must be explicitly enabled, and it has the option to automatically restore app data when an app is reinstalled, so it wouldn't lose track of it being the same profile.
The ANDROID_ID string is a 64-bit random number, unique to each combination of profile and app signing key. The 64-bit limitation means it isn't particularly useful due to the possibility of collisions. It's tied to the lifetime of profiles and does not persist through profile deletion or a factory reset. This is comparable to an app targeting the legacy storage model storing a 64-bit random value in the app-specific external storage directory. In the future, GrapheneOS will likely change this to be tied to the lifetime of app installations rather than profiles. An app could still track the identity of the profile through data you give it access to or via data another app chooses to share with them.
The advertising ID is a Google Play services feature not included in the baseline Android API, so it isn't an API included in GrapheneOS. The advertising ID is unique to each profile. It isn't unique to each app signing key like ANDROID_ID, but that makes little difference since apps within the same profile can communicate with each other with mutual consent. It's comparable to ANDROID_ID but provides an 128-bit value so it provides a strong cryptographic guarantee against collisions, although a device messing with apps could set it to the same value used in another profile. The advertising ID is exposed via the Settings app and can be reset to a new random value, unlike ANDROID_ID which remains the same for the lifetime of the profile, but apps can tie it to the previous ID since they can detect that it changed via their own ID in their app data. The advertising ID can also now be disabled (zeroed).
Apps do not have access to user data by default and cannot ever access the data of other apps without those apps going out of the way to share it with them. If apps are granted read access to user data like media or contacts, they could use it to identify the profile. If apps are granted write access to user data, they could tag it to keep track of the profile. Apps previously had little reason to do things like this because they were able to persist data through an uninstall and reinstallation by default. The modern storage model means they need to request access to user data to do this. The existence of ANDROID_ID means they don't yet need to bother with that but that will change on GrapheneOS and will likely change for baseline Android too. However, profiles are the only way to provide a strong assurance of separate identities since the application model of the OS is designed to support communication between apps within the same profile, but never between them.
GrapheneOS always considers networks to be hostile and avoids placing trust in them. It leaves out various carrier apps included in the stock OS granting carriers varying levels of administrative access beyond standard carrier configuration. GrapheneOS also avoids trust in the cellular network in other ways including providing a secure network time update implementation rather than trusting the cellular network for this. Time is sensitive and can be used to bypass security checks depending on certificate / key expiry.
Cellular networks use inherently insecure protocols and have many trusted parties. Even if interception of the connection or some other man-in-the-middle attack along the network is not currently occurring, the network is still untrustworthy and information should not be sent unencrypted.
Authenticated transport encryption such as HTTPS for web sites avoids trusting the cellular network. End-to-end encrypted protocols such as the Signal messaging protocol also avoid trusting the servers. GrapheneOS uses authenticated encryption with modern protocols, forward secrecy and strong cipher configurations for our services. We only recommend apps taking a decent approach in this area.
Legacy calls and texts should be avoided as they're not secure and trust the carrier / network along with having weak security against other parties. Trying to detect some forms of interception rather than dealing with the root of the problem (unencrypted communications / data transfer) would be foolish and doomed to failure.
GrapheneOS does not add gimmicks without a proper threat model and rationale. We won't include flawed heuristics to guess when the cellular network should be trusted. These kinds of features provide a false sense of security and encourage unwarranted trust in cellular protocols and carrier networks as the default. These also trigger false positives causing unnecessary concern and panic. The correct approach is avoiding trusting the network as explained above.
Connecting to your carrier's network inherently depends on you identifying yourself to it and anyone able to obtain administrative access. Activating airplane mode will fully disable the cellular radio transmit and receive capabilities, which will prevent your phone from being reached from the cellular network and stop your carrier (and anyone impersonating them to you) from tracking the device via the cellular radio. The baseband implements other functionality such as Wi-Fi and GPS functionality, but each of these components is separately sandboxed on the baseband and independent of each other. Enabling airplane mode disables the cellular radio, but Wi-Fi can be re-enabled and used without activating the cellular radio again. This allows using the device as a Wi-Fi only device.
The LTE-only mode added by GrapheneOS is solely intended for attack surface reduction. It should not be mistaken as a way to make the cellular network into something that can be trusted.
Receiving a silent SMS is not a good indicator of being targeted by your cell carrier, police or government because anyone on the cell network can send them including yourself. Cellular triangulation will happen regardless of whether or not SMS texts are being sent or received by the phone. Even if an SMS did serve a useful purpose for tracking, a silent SMS would be little different than receiving unsolicited spam. In fact, sending spam would be stealthier since it wouldn't trigger alerts for silent SMS but rather would be ignored with the rest of the spam. Regardless, sending texts or other data is not required or particularly useful to track devices connected to a network for an adversary with the appropriate access.
Airplane mode is the only way to avoid the cellular network tracking your device and works correctly on the devices we support.
See the usage guide section on Wi-Fi privacy.
GrapheneOS makes connections to the outside world to test connectivity, detect captive portals and download updates. No data varying per user / installation / device is sent in these connections. There aren't analytics / telemetry in GrapheneOS.
The expected default connections by GrapheneOS (including all base system apps) are the following:
The GrapheneOS Updater app fetches update metadata from https://releases.grapheneos.org/DEVICE-CHANNEL approximately once every four hours when connected to a permitted network for updates.
Once an update is available, it tries to download https://releases.grapheneos.org/DEVICE-incremental-OLD_VERSION-NEW_VERSION.zip for a delta update, and then falls back to https://releases.grapheneos.org/DEVICE-ota_update-NEW_VERSION.zip.
No query / data is sent to the server, so the only information leaked to it are the variables in these 3 URLs (device, channel, current version) which is necessary to obtain the update.
Users are in control of which types of networks the Updater app will use and can disable the Updater app in extreme cases. It's strongly recommended to leave it enabled to quickly receive security updates including updates outside the regular monthly schedule.
The update client avoids trusting the data obtained from the update server via signature verification with downgrade protection. Verified boot provides another layer of signature verification with downgrade protection. GrapheneOS servers do not have access to GrapheneOS signing keys.
See the usage guide's section on updates for more information.
An HTTPS connection is made to https://time.grapheneos.org/ to update the time from the date header field. This is a full replacement of Android's standard network time update implementation, which uses the cellular network when available with a fallback to SNTP when it's not available. Network time updates are security sensitive since certificate validation depends on having an accurate time, but the standard NTP / SNTP protocols used across most OSes have no authentication.
We plan to offer a toggle to use the standard functionality instead of HTTPS-based time updates in order to blend in with other devices.
Network time can be disabled with the toggle at Settings ➔ System ➔ Date & time ➔ Set time automatically. Unlike AOSP or the stock OS on the supported devices, GrapheneOS stops making network time connections when using network time is disabled rather than just not setting the clock based on it. The time zone is still obtained directly via the time zone provided by the mobile network (NITZ) when available which you can also disable by the "Set time zone automatically" toggle.
HTTPS connections are made to fetch PSDS information to assist with satellite based location. These are static files and are downloaded automatically to improve location resolution speed and accuracy. No query or data is sent to these servers. These contain orbits and statuses of satellites, Earth environmental data and time adjustment information.
On 4th and 5th generation Pixels (which use a Qualcomm baseband providing cellular, Wi-Fi, Bluetooth and GNSS in separate sandboxes), almanacs are downloaded from https://path1.xtracloud.net/xtra3grcej.bin https://path2.xtracloud.net/xtra3grcej.bin, https://path3.xtracloud.net/xtra3grcej.bin, https://path1.xtracloud.net/xtra3Mgrbeji.bin, https://path2.xtracloud.net/xtra3Mgrbeji.bin and https://path3.xtracloud.net/xtra3Mgrbeji.bin which currently (as of October 2022) are hosted via Amazon Web Services. We plan to offer the option to download these files from the GrapheneOS servers, but we'll retain the option to use the standard servers to blend in with other devices.
On 6th and 7th generation Pixels (which use a Broadcom GNSS chip), almanacs are downloaded from https://google.psds.grapheneos.org/lto2.dat, https://google.psds.grapheneos.org/rto.dat and https://google.psds.grapheneos.org/rtistatus.dat which are the GrapheneOS proxy servers for the standard servers. Alternatively, the standard servers can be enabled in the Settings app which are https://agnss.goog/lto2.dat, https://agnss.goog/rto.dat and https://agnss.goog/rtistatus.dat which are currently (as of October 2022) hosted via Google Cloud Platform.
Connectivity checks designed to mimic a web browser user agent are performed by using HTTP and HTTPS to fetch standard URLs generating an HTTP 204 status code. This is used to detect when internet connectivity is lost on a network, which triggers fallback to other available networks if possible. These checks are designed to detect and handle captive portals which substitute the expected empty 204 response with their own web page.
The connectivity checks are done by performing an empty GET request to a server returning an empty response with a 204 No Content response code. The request uses a standard, frozen value for the user agent matching the same value used by billions of other Android devices:
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.32 Safari/537.36
No query / data is sent to the servers and the response is unused beyond checking the response code.
Connectivity checks are performed for each network connection and for VPN connections on top of those. This allows the OS to choose the right underlying network for a VPN and to handle many types of captive portals without the user turning off their VPN.
You can change the connectivity check URLs via the Settings ➔ Network & Internet ➔ Internet connectivity check setting. At the moment, it can be toggled between the GrapheneOS servers (default), the standard Google servers used by billions of other Android devices or disabled.
By default, the GrapheneOS connectivity check servers are used via the following URLs:
- HTTPS: https://connectivitycheck.grapheneos.network/generate_204
- HTTP: http://connectivitycheck.grapheneos.network/generate_204
- HTTP fallback: http://grapheneos.online/gen_204
- HTTP other fallback: http://grapheneos.online/generate_204
Changing this to the Standard (Google) mode will use the same URLs used by AOSP and the stock OS along with the vast majority of other devices, blending in with billions of other Android devices both with and without Play services:
- HTTPS: https://www.google.com/generate_204
- HTTP: http://connectivitycheck.gstatic.com/generate_204
- HTTP fallback: http://www.google.com/gen_204
- HTTP other fallback: http://play.googleapis.com/generate_204
GrapheneOS also adds the ability to fully disable the connectivity checks. This results in the OS no longer handling captive portals itself, not falling back to other networks when some don't have internet access and not being able to delay scheduled jobs depending on internet access until it becomes available.
Connections are made to a server to provision attestation certificates for hardware-based attestation. GrapheneOS uses https://remoteprovisioning.grapheneos.org/ by default which is a reverse proxy to the https://remoteprovisioning.googleapis.com/ service. Their service splits up the implementation of provisioning to preserve privacy, and our reverse proxy adds to that since it's unable to decrypt the provisioned keys.
A setting is added at Settings ➔ Network & Internet ➔ Attestation key provisioning server for switching to directly using the Google service if you prefer.
DNS connectivity and functionality tests
DNS resolution for other connections
Vanadium does not make connections not requested by the app as part of providing the WebView implementation in the OS. If you choose to use it as your browser, it performs similar connections as the ones performed by the OS above. It does not send any identifying information to servers, etc. but rather fetches some static assets like dictionaries when triggered by usage of the app. We're working on eliminating everything unnecessary and making our servers the default for handling anything that cannot simply be shipped with Vanadium for one reason or another such as requiring quicker updates.
The OS uses the network-provided DNS servers by default. Typically, dynamic IP configuration is used to auto-configure the client on the network. IPv4 DNS servers are obtained via DHCP and IPv6 DNS servers are obtained via RDNSS. For a static IP configuration, the DNS servers are manually configured as part of the static configuration.
A VPN provides a network layered on top of the underlying networks and the OS uses the VPN-provided DNS servers for everything beyond resolving the IP address of the VPN and performing network connectivity checks on each of the underlying networks in addition to the VPN itself.
Using the network-provided DNS servers is the best way to blend in with other users. Network and web sites can fingerprint and track users based on a non-default DNS configuration. Our recommendation for general purpose usage is to use the network-provided DNS servers.
It isn't possible to directly override the DNS servers provided by the network via DHCP. Instead, use the Private DNS feature in Settings ➔ Network & Internet ➔ Private DNS to set the hostname of a DNS-over-TLS server. It needs to have a valid certificate such as a free certificate from Let's Encrypt. The OS will look up the Private DNS hostname via the network provided DNS servers and will then force all other DNS requests through the Private DNS server. Unlike an option to override the network-provided DNS servers, this prevents the network from monitoring or tampering with DNS requests/responses.
As an example, set the hostname to
one.one.one.one for Cloudflare DNS. There are various other mainstream DNS-over-TLS options available including Quad9, Google and AdGuard.
Configuring a static IP address for a network requires entering DNS servers manually, but you should still use the Private DNS feature with it, and you shouldn't misuse the static IP address option just to override the DNS servers.
VPN service apps can also provide their own DNS implementation and/or servers, including an alternate implementation of encrypted DNS. Private DNS takes precedence over VPN-provided DNS, since it's just the network-provided DNS.
Apps and web sites can detect the configured DNS servers by generating random subdomains resolved by querying their authoritative DNS server. This can be used as part of fingerprinting users. If you're using a VPN, you should consider using the standard DNS service provided by the VPN service to avoid standing out from other users.
By default, in the automatic mode, the Private DNS feature provides opportunistic encryption by using DNS-over-TLS when supported by the DNS server IP addresses provided by the network (DHCP) or the static IP configuration. Opportunistic encryption provides protection against a passive listener, not an active attacker, since they can force falling back to unencrypted DNS by blocking DNS-over-TLS. In the automatic mode, certificate validation is not enforced, as it would provide no additional security and would reduce the availability of opportunistic encryption.
When Private DNS is explicitly enabled, it uses authenticated encryption without a fallback. The authentication is performed based on the hostname of the server, so it isn't possible to provide an IP address. The OS will look up the hostname of the Private DNS server via unencrypted DNS and then force all other DNS lookups via DNS-over-TLS with the identity of the server authenticated as part of providing authenticated encryption.
No, it only provides privacy for DNS resolution. Even authenticating DNS results with DNSSEC does not protect other connections, unless the DNS records are part of the system used to provide authenticated encryption, and DNS-over-TLS is not a substitute for DNSSEC. If connections have authenticated encryption, they're secure even if DNS resolution is hijacked by an attacker. If connections do not have authenticated encryption, an attacker can listen in and tamper with them without hijacking DNS. There are other ways to perform a MITM attack than DNS hijacking and internet routing is fundamentally insecure. DNS-over-TLS may make a MITM harder for some attackers, but don't count on it at all.
Private DNS only encrypts DNS, and an adversary monitoring connections can still see the IP address at the other end of those connections. Many domains resolve to ambiguous IP addresses, so encrypted DNS is part of what's required to take away a lot of the information leaked to adversaries. However, TLS currently leaks domains via SNI, so encrypted DNS is not yet accomplishing much. It's a forward looking feature that will become more useful in the future. Using it is recommended, but it's not an alternative to using Tor or a VPN.
VPNs can be configured under Settings ➔ Network & Internet ➔ VPN. Support for the following protocols is included: IKEv2/IPSec MSCHAPv2, IKEv2/IPSec PSK and IKEv2/IPSec RSA. Apps can also provide userspace VPN implementations and the following open source apps are recommended: Orbot (Tor), WireGuard and OpenVPN for Android.
VPN configurations created with the built-in support can be set as the always-on VPN in the configuration panel. This will keep the VPN running, reconnecting as necessary and will force all connections through them. An app providing a VPN service can also be set as the always-on VPN via the entry in the Settings page. For app-based VPN implementations, there's also an additional "Block connections without VPN" toggle which is needed to prevent leaks when the app's VPN service isn't running.
Apps cannot monitor network connections unless they're made into the active VPN service by the user. Apps cannot normally access network stats and cannot directly request access to them. However, app-based stats can be explicitly granted by users as part of access to app usage stats in Settings ➔ Apps ➔ Special app access ➔ Usage access.
This was previously part of the GrapheneOS privacy improvements, but became a standard Android feature with Android 10.
Yes, GrapheneOS inherits the deeply integrated firewall from the Android Open Source Project, which is used to implement portions of the security model and various other features. The GrapheneOS project historically made various improvements to the firewall but over time most of these changes have been integrated upstream or became irrelevant.
GrapheneOS adds a user-facing Network permission toggle providing a robust way to deny both direct and indirect network access to applications. It builds upon the standard non-user-facing INTERNET permission, so it's already fully adopted by the app ecosystem. Revoking the permission denies indirect access via OS components and apps enforcing the INTERNET permission, such as DownloadManager. Direct access is denied by blocking low-level network socket access.
The recommended approach to system-wide ad-blocking is setting up domain-based ad-blocking as part of DNS resolution. You can do this by choosing a Private DNS (DNS-over-TLS) server with support for blocking ad domains. As an example, AdGuard DNS can be used by setting
dns.adguard-dns.com as the Private DNS domain. This feature used to be included by the project many years ago, but it needs to be reimplemented, and it's a low priority feature depending on contributors stepping up to work on it.
Apps and web sites can detect that ad-blocking is being used and can determine what's being blocked. This can be used as part of fingerprinting users. Using a widely used service like AdGuard with a standard block list is much less of an issue than a custom set of subscriptions / rules, but it still stands out compared to the default of not doing it.
Content filtering apps are fully compatible with GrapheneOS, but they have serious drawbacks and are not recommended. These apps use the VPN service feature to route traffic through themselves to perform filtering.
The approach of intercepting traffic is inherently incompatible with encryption from the client to the server. The AdGuard app works around encryption by supporting optional HTTPS interception by having the user trust a local certificate authority, which is a security risk and weakens HTTPS security even if their implementation is flawless (which they openly acknowledge in their documentation, although it understates the risks). It also can't intercept connections using certificate pinning, with the exception of browsers which go out of the way to allow overriding pinning with locally added certificate authorities. Many of these apps only provide domain-based filtering, unlike the deeper filtering by AdGuard, but they're still impacted by encryption due to Private DNS (DNS-over-TLS) and require disabling the feature. They could provide their own DNS-over-TLS resolver to avoid losing the feature, but few of the developers care enough to do that.
Using the VPN service to provide something other than a VPN also means that these apps need to provide an actual VPN implementation or a way to forward to apps providing one, and very few have bothered to implement this. NetGuard is an example of an app implementing SOCKS5 forwarding, which can be used to forward to apps like Orbot (Tor).
Yes, the baseband is isolated on all of the officially supported devices. Memory access is partitioned by the IOMMU and limited to internal memory and memory shared by the driver implementations. The baseband on the officially supported devices with a Qualcomm SoC implements Wi-Fi and Bluetooth as internal sandboxed processes rather than having a separate baseband for those like earlier devices.
Earlier generation devices we used to support prior to Pixels had Wi-Fi + Bluetooth implemented on a separate SoC. This was not properly contained by the stock OS and we put substantial work into addressing that problem. However, that work has been obsoleted now that Wi-Fi and Bluetooth are provided by the SoC on the officially supported devices.
A component being on a separate chip is orthogonal to whether it's isolated. In order to be isolated, the drivers need to treat it as untrusted. If it has DMA access that needs to be contained via IOMMU and the driver needs to treat the shared memory as untrusted, as it would data received another way. There's a lot of attack surface between the baseband and the kernel/userspace software stack connected to it. OS security is very relevant to containing hardware components including the radios and the vast majority of the attack surface is in software. The OS relies upon the hardware and firmware to be able to contain components but ends up being primarily responsible for it due to control over the configuration of shared memory and the complexity of the interface and the OS side implementation.
The mobile Atheros Wi-Fi driver/firmware is primarily a SoftMAC implementation with the vast majority of the complexity in the driver rather than the firmware. The fully functional driver is massive and the firmware is quite small. Unfortunately, since the Linux kernel is monolithic and has no internal security boundaries, the attack surface is problematic and a HardMAC implementation with most complexity in the isolated firmware could be better than the status quo. An isolated driver would be ideal.
Yes, the GrapheneOS code is reviewed by external security researchers, companies and organizations on a continuous basis. This is the main benefit of GrapheneOS being an open source project actively used by other organizations, but it is certainly not something to take for granted based on a project being open source. We put a lot of work into making our code well documented and easy to review. Auditing and code review cannot be done properly as a one time thing but rather need to be done continuously as the code changes. Most of the code review and auditing results for GrapheneOS can be seen from the public pull requests and issue trackers. For example, the French ANSSI organization uses a bunch of our work and has given us suggestions along with reporting issues including a couple issues in hardened_malloc where it could have a false positive detection of memory corruption and wrongly abort the process. We've built relationships with security researchers and organizations interested in GrapheneOS or using it which results in a lot of this kind of collaboration. This is not a one-time event but rather something that happens regularly as the code evolves, features are added and we ported to new release. The benefits of a group unfamiliar with the code spending a short time doing a shallow review are greatly overstated in marketing. We instead focus on having people very familiar with areas of the code regularly auditing all our changes. The large number of upstream Android security vulnerabilities discovered by GrapheneOS despite us not actively seeking them out speaks to the results of our review and testing.
Other AOSP-based OS projects including DivestOS and ProtonAOSP using lots of our code results in it getting additional review from outside our project. There have been multiple app compatibility issues fixed as a result of this collaboration. In another case, DivestOS using the GrapheneOS Camera app led to the discovery that we were using incorrect units for the auto-focus region used for QR scanning in our Camera and Auditor apps. This was only a very minor issue reducing the quality of the focus in our apps, but it uncovered a serious bug on certain older devices where memory corruption in the camera service can be triggered by setting an overly large focus region in an app. The devices are unmaintained by the vendors, so this was only reported to the CameraX developers.
GrapheneOS code is not just open source but well documented and organized in order to make it much easier to review. Every change we make to Android Open Source Project repositories is maintained as a clean patch set on top of the latest stable release of AOSP. We regularly clean up our changes by splitting up the commits in a more sensible way, providing better commit messages, stripping away everything but the essential changes, reordering the commits to group the related changes and improving the implementation. This makes sense because these are downstream changes ported between each stable release. Our approach also makes it easy to port our patches elsewhere including upstreaming them. Ease of porting helps us when we port to new quarterly and yearly major releases of AOSP. The best way to review our changes over time is the
git range-diff command by passing the old range of commits and the new range of commits. For example, you would pass
git range-diff OLD_AOSP_TAG..OLD_GRAPHENEOS_TAG NEW_AOSP_TAG..NEW_GRAPHENEOS_TAG to see how our changes on top of AOSP have changed between releases without looking at the upstream AOSP changes. This is a major part of our own regular review of our changes and porting work.
Our own standalone projects such as Auditor and AttestationServer also aim to keep the code very easy to audit/review. In those projects, we're writing all the code and choosing the dependencies ourselves, so we can take a minimalist and easy to understand approach to the overall codebase instead of only our changes to it.
We also get broad code review out of attempting to land changes in upstream projects. For example, our CONFIG_FORTIFY_SOURCE feature for the Linux kernel providing a modern take on that feature with support for detecting both read and write overflows was accepted in the Linux kernel in 2017. It has taken several years for all the extra bits of CONFIG_FORTIFY_SOURCE to be accepted upstream. Substantial improvements have been made as part of upstreaming it including upstream deciding to support detecting overflows within objects for the memory family of functions, going far beyond the traditional approach. Based on our issue reports and recommendations, multiple bugs were fixed in both GCC and Clang for FORTIFY_SOURCE support along with a new feature for more dynamic object size checks being added. Android also ended up shipping automatic array bounds checks in addition to FORTIFY_SOURCE for the kernel. We would not have been able to do the same level of testing to uncover the same number of upstream bugs, and we also couldn't have made the more aggressive changes on our own due to lack of resources to review/test the upstream code for compatibility issues.