
Monolithic kernel builds are currently impractical due to frequent compatibility issues when drivers are built into the kernel instead of as dynamic kernel modules. We also benefit from using GKIs too much to switch to using the device kernel tree for the kernel image for 6th gen Pixels.
937 lines
63 KiB
HTML
937 lines
63 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en" prefix="og: https://ogp.me/ns#">
|
|
<head>
|
|
<meta charset="utf-8"/>
|
|
<title>Features overview | GrapheneOS</title>
|
|
<meta name="description" content="Overview of GrapheneOS features differentiating it from the Android Open Source Project (AOSP)."/>
|
|
<meta name="theme-color" content="#212121"/>
|
|
<meta name="color-scheme" content="dark light"/>
|
|
<meta name="msapplication-TileColor" content="#ffffff"/>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
<meta name="twitter:site" content="@GrapheneOS"/>
|
|
<meta name="twitter:creator" content="@GrapheneOS"/>
|
|
<meta property="og:title" content="GrapheneOS features overview"/>
|
|
<meta property="og:description" content="Overview of GrapheneOS features differentiating it from the Android Open Source Project (AOSP)."/>
|
|
<meta property="og:type" content="website"/>
|
|
<meta property="og:image" content="https://grapheneos.org/opengraph.png"/>
|
|
<meta property="og:image:width" content="512"/>
|
|
<meta property="og:image:height" content="512"/>
|
|
<meta property="og:image:alt" content="GrapheneOS logo"/>
|
|
<meta property="og:site_name" content="GrapheneOS"/>
|
|
<meta property="og:url" content="https://grapheneos.org/features"/>
|
|
<link rel="canonical" href="https://grapheneos.org/features"/>
|
|
<link rel="icon" href="/favicon.ico"/>
|
|
<link rel="icon" sizes="any" type="image/svg+xml" href="/favicon.svg"/>
|
|
<link rel="mask-icon" href="{{path|/mask-icon.svg}}" color="#1a1a1a"/>
|
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png"/>
|
|
{{css|/main.css}}
|
|
<link rel="manifest" href="/manifest.webmanifest"/>
|
|
<link rel="license" href="/LICENSE.txt"/>
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<nav id="site-menu">
|
|
<ul>
|
|
<li><a href="/"><img src="{{path|/mask-icon.svg}}" alt=""/>GrapheneOS</a></li>
|
|
<li aria-current="page"><a href="/features">Features</a></li>
|
|
<li><a href="/install/">Install</a></li>
|
|
<li><a href="/build">Build</a></li>
|
|
<li><a href="/usage">Usage</a></li>
|
|
<li><a href="/faq">FAQ</a></li>
|
|
<li><a href="/releases">Releases</a></li>
|
|
<li><a href="/source">Source</a></li>
|
|
<li><a href="/history/">History</a></li>
|
|
<li><a href="/articles/">Articles</a></li>
|
|
<li><a href="/donate">Donate</a></li>
|
|
<li><a href="/contact">Contact</a></li>
|
|
</ul>
|
|
</nav>
|
|
</header>
|
|
<main id="features">
|
|
<h1><a href="#features">Features overview</a></h1>
|
|
|
|
<p>GrapheneOS is a private and secure mobile operating system with great functionality
|
|
and usability. It starts from the strong baseline of the
|
|
<a href="https://source.android.com/">Android Open Source Project (AOSP)</a> and
|
|
takes great care to avoid increasing attack surface or hurting the strong security
|
|
model. GrapheneOS makes substantial improvements to both privacy and security through
|
|
many carefully designed features built to function against real adversaries. The
|
|
project cares a lot about usability and app compatibility so those are taken into
|
|
account for all of our features.</p>
|
|
|
|
<p>GrapheneOS is focused on substance rather than branding and marketing. It doesn't
|
|
take the typical approach of piling on a bunch of insecure features depending on the
|
|
adversaries not knowing about them and regressing actual privacy/security. It's a very
|
|
technical project building privacy and security into the OS rather than including
|
|
assorted unhelpful frills or bundling subjective third party apps choices.</p>
|
|
|
|
<p>GrapheneOS is also hard at work on filling in gaps from not bundling Google apps
|
|
and services into the OS. We aren't against users using Google services but it doesn't
|
|
belong integrated into the OS in an invasive way. GrapheneOS won't take the shortcut
|
|
of simply bundling a very incomplete and poorly secured third party reimplementation
|
|
of Google services into the OS. That wouldn't ever be something users could rely upon.
|
|
It will also always be chasing a moving target while offering poorer security than the
|
|
real thing if the focus is on simply getting things working without great care for
|
|
doing it robustly and securely.</p>
|
|
|
|
<p>This page provides an overview of currently implemented features differentiating
|
|
GrapheneOS from AOSP. It doesn't document our many historical features that are no
|
|
longer included for one reason or another. Many of our features were implemented in
|
|
AOSP, Linux, <a href="https://llvm.org/">LLVM</a> and other projects GrapheneOS is
|
|
based on and those aren't listed here. In many cases, we've been involved in getting
|
|
those features implemented in core infrastructure projects.</p>
|
|
|
|
<nav id="table-of-contents">
|
|
<h2><a href="#table-of-contents">Table of contents</a></h2>
|
|
|
|
<ul>
|
|
<li>
|
|
<a href="#grapheneos">GrapheneOS</a>
|
|
<ul>
|
|
<li>
|
|
<a href="#exploit-protection">Defending against exploitation of
|
|
unknown vulnerabilities</a>
|
|
<ul>
|
|
<li><a href="#attack-surface-reduction">Attack surface
|
|
reduction</a></li>
|
|
<li><a href="#exploit-mitigations">Exploit
|
|
mitigations</a></li>
|
|
<li><a href="#improved-sandboxing">Improved
|
|
sandboxing</a></li>
|
|
<li><a href="#anti-persistence">Anti-persistence /
|
|
detection</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#more-complete-patching">More complete patching</a></li>
|
|
<li><a href="#sandboxed-google-play">Sandboxed Google Play</a></li>
|
|
<li><a href="#network-permission-toggle">Network permission toggle</a></li>
|
|
<li><a href="#sensors-permission-toggle">Sensors permission toggle</a></li>
|
|
<li><a href="#storage-scopes">Storage Scopes</a></li>
|
|
<li><a href="#broad-carrier-support">Broad carrier support without invasive carrier access</a></li>
|
|
<li><a href="#lte-only-mode">LTE-only mode</a></li>
|
|
<li><a href="#wifi-privacy">Wi-Fi privacy</a></li>
|
|
<li><a href="#private-screenshots">Private screenshots</a></li>
|
|
<li><a href="#closed-device-identifier-leaks">Closed device identifier leaks</a></li>
|
|
<li><a href="#pin-scrambling">PIN scrambling</a></li>
|
|
<li><a href="#privacy-by-default">Privacy by default</a></li>
|
|
<li><a href="#supports-longer-passwords">Supports longer
|
|
passwords</a></li>
|
|
<li><a href="#auto-reboot">Auto reboot</a></li>
|
|
<li><a href="#more-secure-fingerprint-unlock">More secure fingerprint
|
|
unlock</a></li>
|
|
<li>
|
|
<a href="#improved-user-profiles">Improved user profiles</a>
|
|
<ul>
|
|
<li><a href="#more-user-profiles">More user profiles</a></li>
|
|
<li><a href="#end-session">End session</a></li>
|
|
<li><a href="#disabling-app-installation">Disabling app installation</a></li>
|
|
<li><a href="#notification-forwarding">Notification forwarding</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#grapheneos-app-repository">GrapheneOS app
|
|
repository</a></li>
|
|
<li><a href="#vanadium">Vanadium: hardened WebView and default
|
|
browser</a></li>
|
|
<li><a href="#auditor">Auditor app and attestation service</a></li>
|
|
<li><a href="#grapheneos-camera">GrapheneOS Camera</a></li>
|
|
<li><a href="#grapheneos-pdf-viewer">GrapheneOS PDF Viewer</a></li>
|
|
<li><a href="#encrypted-backups">Encrypted backups</a></li>
|
|
<li><a href="#location-data-access-indicator">Location data access
|
|
indicator</a></li>
|
|
<li><a href="#user-installed-apps-can-be-disabled">User installed apps
|
|
can be disabled</a></li>
|
|
<li><a href="#other-features">Other features</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#services">Services</a></li>
|
|
<li><a href="#project">Project</a></li>
|
|
</ul>
|
|
</nav>
|
|
|
|
<section id="grapheneos">
|
|
<h2><a href="#grapheneos">GrapheneOS</a></h2>
|
|
|
|
<p>These are the features of GrapheneOS beyond what's provided by version 12.1
|
|
of the Android Open Source Project. It only covers our improvements to AOSP and
|
|
not baseline features. This section doesn't list features like the standard app
|
|
sandbox, verified boot, exploit mitigations (ASLR, SSP, Shadow Call Stack,
|
|
Control Flow Integrity, etc.), permission system (foreground-only and one-time
|
|
permission grants, scoped file access control, etc.) and so on but rather only
|
|
our improvements to modern Android. We plan on providing a separate page listing
|
|
the improvements we've contributed to Android since those features aren't listed
|
|
here despite being a substantial portion of our overall historical work.</p>
|
|
|
|
<section id="exploit-protection">
|
|
<h3><a href="#exploit-protection">Defending against exploitation of unknown
|
|
vulnerabilities</a></h3>
|
|
|
|
<p>GrapheneOS is heavily focused on protecting users against attackers
|
|
exploiting unknown (0 day) vulnerabilities. Patching vulnerabilities doesn't
|
|
protect users before the vulnerability is known to the vendor and has a patch
|
|
developed and shipped.</p>
|
|
|
|
<p>Unknown (0 day) vulnerabilities are much more widely used than most realize
|
|
to exploit users not just in targeted attacks but in broad deployments.
|
|
Project Zero maintains
|
|
<a href="https://docs.google.com/spreadsheets/d/1lkNJ0uQwbeC1ZTRrxdtuPLCIl7mlUreoKfSIgajnSyY/view#gid=0">a
|
|
spreadsheet</a> tracking zero day exploitation detected in the wild. This is
|
|
only a peek into what's happening since it only documents cases where the
|
|
attackers were caught exploiting users, often because the attacks are not
|
|
targeted but rather deployed on public websites, etc.</p>
|
|
|
|
<p>The first line of defense is attack surface reduction. Removing unnecessary
|
|
code or exposed attack surface eliminates many vulnerabilities completely.
|
|
GrapheneOS avoids removing any useful functionality for end users, but we can
|
|
still disable lots of functionality by default and require that users opt-in
|
|
to using it to eliminate it for most of them. An example we landed upstream in
|
|
Android is disallowing using the kernel's profiling support by default, since
|
|
it was and still is a major source of Linux kernel vulnerabilities. Profiling
|
|
is now only exposed to apps for developers who enable developer tools, enable
|
|
the Android Debug Bridge (ADB) and then use profiling tools via ADB. It's also
|
|
only enabled until the next boot. This isn't listed below since it's one of
|
|
the features we got implemented in Android itself.</p>
|
|
|
|
<p>The next line of defense is preventing an attacker from exploiting a
|
|
vulnerability, either by making it impossible, unreliable or at least
|
|
meaningfully harder to develop. The vast majority of vulnerabilities are well
|
|
understood classes of bugs and exploitation can be prevented by avoiding the
|
|
bugs via languages/tooling or preventing exploitation with strong exploit
|
|
mitigations. In many cases, vulnerability classes can be completely wiped out
|
|
while in many others they can at least be made meaningfully harder to exploit.
|
|
Android does a lot of work in this area and GrapheneOS has helped to advance
|
|
this in Android and the Linux kernel. It takes an enormous amount of resources
|
|
to develop fundamental fixes for these problems and there's often a high
|
|
performance, memory or compatibility cost to deploying them. Mainstream
|
|
operating systems usually don't prioritize security over other areas.
|
|
GrapheneOS is willing to go further and we offer toggles for users to choose
|
|
the compromises they prefer instead of forcing it on them. In the meantime,
|
|
weaker less complete exploit mitigations can still provide meaningful barriers
|
|
against attacks as long as they're developed with a clear threat model.
|
|
GrapheneOS is heavily invested in many areas of developing these protections:
|
|
developing/deploying memory safe languages / libraries, static/dynamic
|
|
analysis tooling and many kinds of mitigations.</p>
|
|
|
|
<p>The final line of defense is containment through sandboxing at various
|
|
levels: fine-grained sandboxes around a specific context like per site browser
|
|
renderers, sandboxes around a specific component like Android's media codec
|
|
sandbox and app / workspace sandboxes like the Android app sandbox used to
|
|
sandbox each app which is also the basis for user/work profiles. GrapheneOS
|
|
improves all of these sandboxes through fortifying the kernel and other base
|
|
OS components along with improving the sandboxing policies.</p>
|
|
|
|
<p>Preventing an attacker from persisting their control of a component or the
|
|
OS / firmware through verified boot and avoiding trust in persistent state
|
|
also helps to mitigate the damage after a compromise has occurred.</p>
|
|
|
|
<p>Remote code execution vulnerabilities are the most serious and allow an
|
|
attacker to gain a foothold on device or even substantial control over it
|
|
remotely. Local code execution vulnerabilities allow breaking out of a sandbox
|
|
including the app sandbox or browser renderer sandbox after either
|
|
compromising an app / browser renderer remotely, compromising an app's supply
|
|
chain or getting the user to install a malicious app. Many other kinds of
|
|
vulnerabilities exist but most of what we're protecting against falls into
|
|
these 2 broad categories.</p>
|
|
|
|
<p>The vast majority of local and remote code execution vulnerabilities are
|
|
memory corruption bugs caused by memory unsafe languages or rare low-level
|
|
unsafe code in an otherwise memory safe language. Most of the remaining issues
|
|
are caused by dynamic code execution/loading features. Our main focus is on
|
|
preventing or raising the difficult of exploiting memory corruption bugs
|
|
followed by restricting dynamic code execution both to make escalation from a
|
|
memory corruption bug harder and to directly mitigate bugs caused by dynamic
|
|
code loading/generation/execution such as a JIT compiler bug or a plugin
|
|
loading vulnerability.</p>
|
|
|
|
<section id="attack-surface-reduction">
|
|
<h4><a href="#attack-surface-reduction">Attack surface reduction</a></h4>
|
|
|
|
<ul>
|
|
<li>Greatly reduced remote, local and proximity-based attack surface by
|
|
stripping out unnecessary code, making more features optional and disabling
|
|
optional features by default (NFC, Bluetooth, etc.), when the screen is
|
|
locked (connecting new USB peripherals, camera access) and optionally after a
|
|
timeout (Bluetooth, Wi-Fi)</li>
|
|
<li>Option to disable native debugging (ptrace) to reduce local attack surface
|
|
(still enabled by default for compatibility)</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section id="exploit-mitigations">
|
|
<h4><a href="#exploit-mitigations">Exploit mitigations</a></h4>
|
|
|
|
<ul>
|
|
<li>Hardened app runtime</li>
|
|
<li><a href="/usage#exec-spawning">Secure application spawning
|
|
system</a> avoiding sharing address space layout and other secrets
|
|
across applications</li>
|
|
<li><a href="https://github.com/GrapheneOS/platform_bionic">Hardened libc</a>
|
|
providing defenses against the most common classes of vulnerabilities (memory
|
|
corruption)</li>
|
|
<li>
|
|
Our own <a href="https://github.com/GrapheneOS/hardened_malloc">hardened
|
|
malloc (memory allocator)</a> leveraging modern hardware capabilities
|
|
to provide substantial defenses against the most common classes of
|
|
vulnerabilities (heap memory corruption) along with reducing the lifetime
|
|
of sensitive data in memory. The <a
|
|
href="https://github.com/GrapheneOS/hardened_malloc/blob/main/README.md">hardened_malloc
|
|
README</a> has extensive documentation on it. The hardened_malloc
|
|
project is portable to other Linux-based operating systems and is being
|
|
adopted by other security-focused operating systems like Whonix. Our
|
|
allocator also heavily influenced the design of the <a
|
|
href="https://www.openwall.com/lists/musl/2020/05/13/1">next-generation
|
|
musl malloc implementation</a> which offers substantially better security than
|
|
musl's previous malloc while still having minimal memory usage and code size.
|
|
<ul>
|
|
<li>Fully out-of-line metadata with protection from corruption, ruling
|
|
out traditional allocator exploitation</li>
|
|
<li>Separate memory regions for metadata, large allocations and each
|
|
slab allocation size class with high entropy random bases and no
|
|
address space reuse between the different regions</li>
|
|
<li>Deterministic detection of any invalid free</li>
|
|
<li>Zero-on-free with detection of write-after-free via checking that
|
|
memory is still zeroed before handing it out again</li>
|
|
<li>Delayed reuse of address space and memory allocations through the
|
|
combination of deterministic and randomized quarantines to mitigate
|
|
use-after-free vulnerabilities</li>
|
|
<li>Fine-grained randomization</li>
|
|
<li>Aggressive consistency checks</li>
|
|
<li>Memory protected guard regions around allocations larger than 16k
|
|
with randomization of guard region sizes for 128k and above</li>
|
|
<li>Allocations smaller than 16k have guard regions around each of the
|
|
slabs containing allocations (for example, 16 byte allocations are in
|
|
4096 byte slabs with 4096 byte guard regions before and after)</li>
|
|
<li>Random canaries with a leading zero are added to these smaller
|
|
allocations to block C string overflows, absorb small overflows
|
|
and detect linear overflows or other heap corruption when the
|
|
canary value is checked (primarily on free)</li>
|
|
</ul>
|
|
</li>
|
|
<li>Hardened compiler toolchain</li>
|
|
<li>
|
|
Hardened kernel
|
|
<ul>
|
|
<li>Full LTO (Link Time Optimization) is used instead of
|
|
ThinLTO to provide improved Control Flow Integrity (CFI)
|
|
granularity.</li>
|
|
<li>4-level page tables are enabled on arm64 to provide a much larger
|
|
address space (48-bit instead of 39-bit) with significantly higher
|
|
entropy Address Space Layout Randomization (33-bit instead of
|
|
24-bit).</li>
|
|
<li>Random canaries with a leading zero are added to the kernel heap
|
|
(slub) to block C string overflows, absorb small overflows and detect
|
|
linear overflows or other heap corruption when the canary value is
|
|
checked (on free, copies to/from userspace, etc.).</li>
|
|
<li>Memory is wiped (zeroed) as soon as it's released in both the
|
|
low-level kernel page allocator and higher level kernel heap allocator
|
|
(slub). This substantially reduces the lifetime of sensitive data in
|
|
memory, mitigates use-after-free vulnerabilities and makes most
|
|
uninitialized data usage vulnerabilities harmless. Without our
|
|
changes, memory that's released retains data indefinitely until the
|
|
memory is handed out for other uses and gets partially or fully
|
|
overwritten by new data.</li>
|
|
<li>Kernel stack allocations are zeroed to make most uninitialized
|
|
data usage vulnerabilities harmless.</li>
|
|
<li>Assorted attack surface reduction through disabling features or
|
|
setting up infrastructure to dynamically enable/disable them only as
|
|
needed (perf, ptrace).</li>
|
|
<li>Assorted upstream hardening features are enabled, including many
|
|
which we played a part in developing and landing upstream as part of
|
|
our linux-hardened project (which we intend to revive as a more active
|
|
project again).</li>
|
|
</ul>
|
|
</li>
|
|
<li>Prevention of dynamic native code execution in-memory or via the filesystem
|
|
for the base OS without going via the package manager, etc.</li>
|
|
<li>Filesystem access hardening</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section id="improved-sandboxing">
|
|
<h4><a href="#improved-sandboxing">Improved sandboxing</a></h4>
|
|
|
|
<p>GrapheneOS improves the app sandbox through hardening SELinux policy
|
|
and seccomp-bpf policy along with all the hardening to components like
|
|
kernel implementing the app sandbox and providing a path for the attacker
|
|
to escape it if they can exploit those components. We primarily focus on
|
|
the app sandbox, but we also improve the other sandboxes including making
|
|
direct improvements to the web browser renderer sandbox used for both the
|
|
default browser and WebView rendering engine provided by the OS and used
|
|
by a huge number of other apps from dedicated browsers to messaging
|
|
apps.</p>
|
|
</section>
|
|
|
|
<section id="anti-persistence">
|
|
<h4><a href="#anti-persistence">Anti-persistence / detection</a></h4>
|
|
|
|
<ul>
|
|
<li>Enhanced <a href="https://source.android.com/security/verifiedboot">verified boot</a>
|
|
with better security properties and reduced attack surface</li>
|
|
<li>Enhanced hardware-based attestation with more precise version information</li>
|
|
<li>Hardware-based security verification and monitoring via our
|
|
<a href="#auditor">Auditor app and attestation service</a></li>
|
|
</ul>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="more-complete-patching">
|
|
<h3><a href="#more-complete-patching">More complete patching</a></h3>
|
|
|
|
<p>GrapheneOS includes fixes for many vulnerabilities not yet fixed in
|
|
Android. On modern devices with Generic Kernel Image (GKI) support, we
|
|
update the kernel to the latest stable GKI release many months before the stock OS
|
|
gets the update. This means we're shipping hundreds of fixes not included in
|
|
the stock OS including many security fixes. We also backport more fixes on top
|
|
of this for the kernel and for other components too.</p>
|
|
|
|
<p>We often find new vulnerabilities ourselves and report them upstream. We've
|
|
reported dozens of vulnerabilities for both the generic Android codebase and
|
|
also for Pixels specifically. We also often find missed patches which were
|
|
supposed to be included but were missed, especially when there are device
|
|
specific components with partially shared but separate codebases for different
|
|
devices.</p>
|
|
|
|
<p>Our overall approach is to focus on systemic privacy and security
|
|
improvements but fixing individual vulnerabilities is still very
|
|
important.</p>
|
|
</section>
|
|
|
|
<section id="sandboxed-google-play">
|
|
<h3><a href="#sandboxed-google-play">Sandboxed Google Play</a></h3>
|
|
|
|
<p>GrapheneOS has a compatibility layer providing the option to install and use
|
|
the official releases of Google Play in the standard app sandbox. Google Play
|
|
receives absolutely no special access or privileges on GrapheneOS as opposed to
|
|
bypassing the app sandbox and receiving a massive amount of highly privileged
|
|
access. Instead, the compatibility layer teaches it how to work within the full
|
|
app sandbox. It also isn't used as a backend for the OS services as it would be
|
|
elsewhere since GrapheneOS doesn't use Google Play even when it's installed.</p>
|
|
|
|
<p>Since the Google Play apps are simply regular apps on GrapheneOS, you install
|
|
them within a specific user or work profile and they're only available within that
|
|
profile. Only apps within the same profile can use it and they need to explicitly
|
|
choose to use it. It works the same way as any other app and has no special
|
|
capabilities. As with any other app, it can't access data of other apps and
|
|
requires explicit user consent to gain access to profile data or the standard
|
|
permissions. Apps within the same profile can communicate with mutual consent and
|
|
it's no different for sandboxed Google Play.</p>
|
|
|
|
<p>Sandboxed Google Play is close to being fully functional and provides near
|
|
complete compatibility with the app ecosystem depending on Google Play. Only a
|
|
small subset of privileged functionality which we haven't yet ported to
|
|
different approaches with our compatibility layer is unavailable. Some
|
|
functionality is inherently privileged and can't be provided as part of the
|
|
compatibility layer.</p>
|
|
|
|
<p>The vast majority of Play services functionality works perfectly including
|
|
dynamically downloaded / updated modules (dynamite modules) and functionality
|
|
provided by modular app components such as Google Play Games. By default,
|
|
location requests are rerouted to a partial implementation of the Play
|
|
geolocation service provided by GrapheneOS. You can disable rerouting and use
|
|
the full Play services geolocation service instead.</p>
|
|
|
|
<p>Our compatibility layer includes full support for the Play Store. Play
|
|
Store services are fully available including in-app purchases, Play Asset
|
|
Delivery, Play Feature Delivery and app / content license checks. It can
|
|
install, update and uninstall apps with the standard approach requiring that
|
|
the user authorizes it as an app source and consents to each action. It will
|
|
use the standard Android 12+ unattended update feature to do automatic updates
|
|
for apps where it was the last installer. Unattended updates by sandboxed apps
|
|
are throttled and it can hit the limit when installing batches of updates and
|
|
request consent. We plan to improve this in the future by teaching it to try
|
|
an unattended update again after a short wait.</p>
|
|
|
|
<p>See the <a href="/usage#sandboxed-google-play-installation">usage guide
|
|
section on sandboxed Google Play</a> for instructions.</p>
|
|
</section>
|
|
|
|
<section id="network-permission-toggle">
|
|
<h3><a href="#network-permission-toggle">Network permission toggle</a></h3>
|
|
|
|
<p>GrapheneOS adds a Network permission toggle for disallowing both direct and
|
|
indirect access to any of the available networks. The device-local network
|
|
(localhost) is also guarded by this permission, which is important for
|
|
preventing apps from using it to communicate between profiles. Unlike a
|
|
firewall-based implementation, the Network permission toggle prevents apps
|
|
from using the network via APIs provided by the OS or other apps in the same
|
|
profile as long as they're marked appropriately.</p>
|
|
|
|
<p>The standard INTERNET permission used as the basis for the Network
|
|
permission toggle is enhanced with a second layer of enforcement and proper
|
|
support for granting/revoking it on a per-profile basis.</p>
|
|
</section>
|
|
|
|
<section id="sensors-permission-toggle">
|
|
<h3><a href="#sensors-permission-toggle">Sensors permission toggle</a></h3>
|
|
|
|
<p>Sensors permission toggle: disallow access to all other sensors not covered
|
|
by existing Android permissions (Camera, Microphone, Body Sensors, Activity
|
|
Recognition) including an accelerometer, gyroscope, compass, barometer,
|
|
thermometer and any other sensors present on a given device. To avoid breaking
|
|
compatibility with Android apps, the added permission is enabled by
|
|
default.</p>
|
|
</section>
|
|
|
|
<section id="storage-scopes">
|
|
<h3><a href="#storage-scopes">Storage Scopes</a></h3>
|
|
|
|
<p>GrapheneOS provides Storage Scopes as a fully compatible alternative to the
|
|
standard Android storage permissions. Instead of granting storage permissions,
|
|
users can enable Storage Scopes to grant the requested permissions in a highly
|
|
restricted mode where the app can create files/directories in the user's home
|
|
directory but can only access the files it has created itself. Users can then
|
|
optionally add files and directories as storage scopes to permit the app to
|
|
access files created by other apps.</p>
|
|
|
|
<p>For more details, see the <a href="/usage#storage-access">usage guide
|
|
section on storage access</a>.</p>
|
|
</section>
|
|
|
|
<section id="broad-carrier-support">
|
|
<h3><a href="#broad-carrier-support">Broad carrier support without invasive carrier access</a></h3>
|
|
|
|
<p>GrapheneOS has much broader carrier support than AOSP and mostly matches
|
|
the stock OS on Pixels without making the same sacrifices. We convert their
|
|
APN, carrier configuration, MMS and visual voicemail databases to the formats
|
|
used by AOSP with our carriersettings project and other scripts. We strip out
|
|
anti-user configuration requiring provisioning for tethering, forbidding
|
|
disabling 2G, etc. We don't include the invasive carrier specific apps and
|
|
support for Open Mobile Alliance Device Management (OMA DM) so we also strip
|
|
out configuration depending on those.</p>
|
|
|
|
<p>See our <a href="/usage#carrier-functionality">usage guide section on
|
|
carrier functionality</a> for more details.</p>
|
|
</section>
|
|
|
|
<section id="lte-only-mode">
|
|
<h3><a href="#lte-only-mode">LTE-only mode</a></h3>
|
|
|
|
<p><a href="/usage#lte-only-mode">LTE-only mode</a> to reduce cellular radio
|
|
attack surface by disabling enormous amounts of both legacy code (2G, 3G) and
|
|
bleeding edge code (5G).</p>
|
|
</section>
|
|
|
|
<section id="wifi-privacy">
|
|
<h3><a href="#wifi-privacy">Wi-Fi privacy</a></h3>
|
|
|
|
<p>GrapheneOS supports per-connection MAC randomization and enables it by
|
|
default. This is a more private approach than the standard persistent
|
|
per-network random MAC used by modern Android.</p>
|
|
|
|
<p>When the per-connection MAC randomization added by GrapheneOS is being
|
|
used, DHCP client state is flushed before reconnecting to a network to avoid
|
|
revealing that it's likely the same device as before.</p>
|
|
|
|
<p>GrapheneOS also applies fixes for serious flaws with the Linux kernel IPv6
|
|
privacy address implementation which allow using it as an identifier not just
|
|
for connections to the same network but also across different networks. We
|
|
don't need to apply these changes for the Pixel 6 and later since this was
|
|
fixed in the Linux kernel upstream, but hasn't been backported to earlier
|
|
kernel LTS branches so we still need to take care of it there.</p>
|
|
|
|
<p>See our <a href="/usage#wifi-privacy">usage guide section on Wi-Fi privacy
|
|
for more general information</a> rather than only our improvements to the
|
|
standard Wi-Fi privacy approach.</p>
|
|
</section>
|
|
|
|
<section id="private-screenshots">
|
|
<h3><a href="#private-screenshots">Private screenshots</a></h3>
|
|
|
|
<p>GrapheneOS disables the inclusion of sensitive metadata in screenshots.</p>
|
|
|
|
<p>On Android, each screenshot includes an EXIF Software tag with detailed OS
|
|
build/version information (<code>android.os.Build.DISPLAY</code>). It's the
|
|
same value shown at Settings ➔ About device ➔ Build number. This leaks the OS,
|
|
OS version and also usually the device family/model since builds are usually
|
|
specific to a family of devices. GrapheneOS completely disables this tag.</p>
|
|
|
|
<p>On Android, each screenshot also includes EXIF tags with the local date,
|
|
time and timezone offset. GrapheneOS disables this by default in order to
|
|
avoid leaking the time and quasi-location information through metadata that
|
|
isn't visible to the user. The date and time are already included in the file
|
|
name of the screenshot which is fully visible to the user and can be easily
|
|
modified by them without a third party tool. GrapheneOS includes a toggle for
|
|
turning this metadata back on in Settings ➔ Privacy since some users may find
|
|
it to be useful.</p>
|
|
</section>
|
|
|
|
<section id="closed-device-identifier-leaks">
|
|
<h3><a href="#closed-device-identifier-leaks">Closed device identifier leaks</a></h3>
|
|
|
|
<p>GrapheneOS fixes several prominent device identifier leaks bypassing
|
|
Android's intention of apps not being able to uniquely identify a device. See
|
|
our FAQ sections on <a href="/faq#hardware-identifiers">hardware
|
|
identifiers</a> and <a href="/faq#non-hardware-identifiers">non-hardware
|
|
identifiers</a> for more general information.</p>
|
|
|
|
<p>Our <a href="/usage#exec-spawning">secure application spawning system</a>
|
|
primarily exists to significantly improve protection against exploitation.
|
|
However, it also improves privacy. On a device without our secure application
|
|
spawning system, the secrets used for probabilistic exploit mitigations such
|
|
as ASLR are usable as device identifiers persisting until reboot. This is an
|
|
easy way to identify the device from apps in different profiles. It's a minor
|
|
bonus of the feature and there are still plenty of side channels to identify
|
|
devices across apps, but it fixes most of the known direct identifier
|
|
leaks.</p>
|
|
|
|
<p>We also eliminate several holes in preventing apps from accessing hardware
|
|
identifiers including tightening up the restrictions for apps targeting legacy
|
|
Android platform versions.</p>
|
|
</section>
|
|
|
|
<section id="pin-scrambling">
|
|
<h3><a href="#pin-scrambling">PIN scrambling</a></h3>
|
|
|
|
<p>GrapheneOS adds a toggle for enabling PIN scrambling to raise the
|
|
difficulty of figuring out the PIN being entered by a user either due to
|
|
physical proximity or a side channel.</p>
|
|
</section>
|
|
|
|
<section id="privacy-by-default">
|
|
<h3><a href="#privacy-by-default">Privacy by default</a></h3>
|
|
|
|
<p>GrapheneOS doesn't include or use Google apps and services by default and
|
|
avoids including any other apps/services not aligned with our privacy and
|
|
security focus. Google apps and services can be used on GrapheneOS as regular
|
|
sandboxed apps without any special access or privileges through our <a
|
|
href="#sandboxed-google-play">sandboxed Google Play</a> feature, but we don't
|
|
include those apps by default to give users an explicit choice on whether they
|
|
want to use those apps and which profiles they want to use it in.</p>
|
|
|
|
<p>We change the default settings to prefer privacy over small conveniences:
|
|
personalized keyboard suggestions based on gathering input history are
|
|
disabled by default, sensitive notifications are hidden on the lockscreen by
|
|
default and passwords are hidden during entry by default.</p>
|
|
|
|
<p>Some of our changes for <a href="#attack-surface-reduction">attack surface
|
|
reduction</a> can also improve privacy by default by not exposing unnecessary
|
|
radios, etc. by default and avoiding the impact of potential privacy bugs with
|
|
the hardware.</p>
|
|
|
|
<p>By default, we also use GrapheneOS servers for the following services
|
|
instead of Google servers:</p>
|
|
|
|
<ul>
|
|
<li>Connectivity checks</li>
|
|
<li>Attestation key provisioning</li>
|
|
<li>GNSS almanac downloads (PSDS) on 6th generation Pixels</li>
|
|
<li>Network time</li>
|
|
</ul>
|
|
|
|
<p>We provide a toggle to switch back to Google's servers for connectivity
|
|
checks, attestation key provisioning and GNSS almanac downloads along with
|
|
adding proper support for disabling network time connections. This combines
|
|
with other toggles to allow making a GrapheneOS device appear to be an AOSP
|
|
device. This is only particularly important for connectivity checks since the
|
|
other connections get routed through a VPN which is needed to blend in on a
|
|
local network in practice.</p>
|
|
|
|
<p>See our <a href="/faq#default-connections">default connections FAQ entry
|
|
for much more detailed information</a>.</p>
|
|
</section>
|
|
|
|
<section id="supports-longer-passwords">
|
|
<h3><a href="#supports-longer-passwords">Supports longer passwords</a></h3>
|
|
|
|
<p>GrapheneOS supports setting longer passwords by default: 64 characters
|
|
instead of 16 characters. This avoids the need to use a device manager to
|
|
enable this functionality.</p>
|
|
|
|
<p>This feature allows users to make use of diceware passwords if they don't
|
|
want to depend on the security of the secure element which provides very
|
|
aggressive throttling and offers a high level of security even for a random 6
|
|
digit PIN.</p>
|
|
</section>
|
|
|
|
<section id="auto-reboot">
|
|
<h3><a href="#auto-reboot">Auto reboot</a></h3>
|
|
|
|
<p>Option to enable automatically rebooting the device when no profile has
|
|
been unlocked for the configured time period to put the device fully at rest
|
|
again.</p>
|
|
</section>
|
|
|
|
<section id="more-secure-fingerprint-unlock">
|
|
<h3><a href="#more-secure-fingerprint-unlock">More secure fingerprint unlock</a></h3>
|
|
|
|
<p>GrapheneOS improves the security of the fingerprint unlock feature by only
|
|
permitting 5 total attempts rather than implementing a 30 second delay between
|
|
every 5 failed attempts with a total of 20 attempts. This doesn't just reduce
|
|
the number of potential attempts but also makes it easy to disable fingerprint
|
|
unlock by intentionally failing to unlock 5 times with a different finger.</p>
|
|
|
|
<p>GrapheneOS also adds support for using the fingerprint scanner only for
|
|
authentication in apps and unlocking hardware keystore keys by toggling off
|
|
support for unlocking. This feature already existed for the standard Android
|
|
face unlock feature.</p>
|
|
</section>
|
|
|
|
<section id="improved-user-profiles">
|
|
<h3><a href="#improved-user-profiles">Improved user profiles</a></h3>
|
|
|
|
<p>Android's user profiles are isolated workspaces with their own instances of
|
|
apps, app data and profile data (contacts, media store, home directory, etc.).
|
|
Apps can't see the apps in other user profiles and can only communicate with
|
|
apps within the same user profile (with mutual consent with the other app).
|
|
Each user profile has their own encryption keys based on their lock method.
|
|
They're a great fit for GrapheneOS with a lot of room for improvement.</p>
|
|
|
|
<p>GrapheneOS provides improvements to user profile functionality and is
|
|
working on further improvements to make switching between them and monitoring
|
|
other profiles much more convenient.</p>
|
|
|
|
<section id="more-user-profiles">
|
|
<h4><a href="#more-user-profiles">More user profiles</a></h4>
|
|
|
|
<p>GrapheneOS raises the limit on the number of secondary user profiles to 16
|
|
(15 + guest) instead of only 4 (3 + guest) to make this feature much more
|
|
flexible.</p>
|
|
</section>
|
|
|
|
<section id="end-session">
|
|
<h4><a href="#end-session">End session</a></h4>
|
|
|
|
<p>GrapheneOS also enables support for logging out of user profiles without
|
|
needing a device manager controlling the device to use this feature. Logging
|
|
out makes profiles inactive so none of the apps installed in them can run. It
|
|
also purges the disk encryption keys from memory and hardware registers,
|
|
putting the user profile back at rest.</p>
|
|
</section>
|
|
|
|
<section id="disabling-app-installation">
|
|
<h4><a href="#disabling-app-installation">Disabling app installation</a></h4>
|
|
|
|
<p>GrapheneOS adds a toggle to the user management settings for disabling
|
|
secondary user app installation. You can install the apps you want to be
|
|
usable in a secondary user and then disable the ability to install more apps
|
|
as that user in the Owner profile. Android supports this as a standard device
|
|
management feature but doesn't make it available to a user who owns their own
|
|
device.</p>
|
|
</section>
|
|
|
|
<section id="notification-forwarding">
|
|
<h4><a href="#notification-forwarding">Notification forwarding</a></h4>
|
|
|
|
<p>GrapheneOS supports forwarding notifications from users running in the
|
|
background to the currently active user. Forwarding notifications to other
|
|
users is disabled by default and can be enabled within each user profile
|
|
where forwarding to the active profile is wanted. Notifications forwarded
|
|
from other profiles are displayed by default in a standard local
|
|
notification channel.</p>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="grapheneos-app-repository">
|
|
<h3><a href="#grapheneos-app-repository">GrapheneOS app repository</a></h3>
|
|
|
|
<p>GrapheneOS includes our own security, minimalism and usability focused app
|
|
repository client for using our first party app repository. Our app repository
|
|
is currently used to distribute our own apps and a mirror of Google Play for
|
|
the sandboxed Google Play feature. In the future, it will be used to
|
|
distribute first-party GrapheneOS builds of externally developed open source
|
|
apps with hardening applied.</p>
|
|
</section>
|
|
|
|
<section id="vanadium">
|
|
<h3><a href="#vanadium">Vanadium: hardened WebView and default browser</a></h3>
|
|
|
|
<p>GrapheneOS includes our Vanadium browser as WebView implementation provided
|
|
by the OS and our default browser. Vanadium is a hardened variant of Chromium
|
|
providing enhanced privacy and security, similar to how GrapheneOS compares to
|
|
AOSP. The Vanadium browser currently doesn't add many features but there are a
|
|
lot of enhancements planned in the long term.</p>
|
|
|
|
<p>More details are available in the <a href="/usage#web-browsing">web
|
|
browsing section of our usage guide</a>.</p>
|
|
</section>
|
|
|
|
<section id="auditor">
|
|
<h3><a href="#auditor">Auditor app and attestation service</a></h3>
|
|
|
|
<p>Our <a href="https://github.com/GrapheneOS/Auditor/releases">Auditor
|
|
app</a> and <a href="https://attestation.app/">attestation service</a>
|
|
provide strong hardware-based verification of the authenticity and integrity
|
|
of the firmware/software on the device. A strong pairing-based approach is
|
|
used which also provides verification of the device's identity based on the
|
|
hardware backed key generated for each pairing. Software-based checks are
|
|
layered on top with trust securely chained from the hardware. For more
|
|
details, see the <a href="https://attestation.app/about">about page</a> and
|
|
<a href="https://attestation.app/tutorial">tutorial</a>.</p>
|
|
</section>
|
|
|
|
<section id="grapheneos-camera">
|
|
<h3><a href="#grapheneos-camera">GrapheneOS Camera</a></h3>
|
|
|
|
<p><a href="/usage#grapheneos-camera-app">GrapheneOS Camera</a> is a modern
|
|
camera app with a great user interface and a focus on privacy and
|
|
security. More details are available the <a href="/usage#camera">camera
|
|
section of our usage guide</a>.</p>
|
|
</section>
|
|
|
|
<section id="grapheneos-pdf-viewer">
|
|
<h3><a href="#grapheneos-pdf-viewer">GrapheneOS PDF Viewer</a></h3>
|
|
|
|
<p><a href="https://github.com/GrapheneOS/PdfViewer">GrapheneOS PDF Viewer</a>
|
|
is sandboxed, hardened PDF viewer using HiDPI rendering with pinch to zoom,
|
|
text selection, etc.</p>
|
|
</section>
|
|
|
|
<section id="encrypted-backups">
|
|
<h3><a href="#encrypted-backups">Encrypted backups</a></h3>
|
|
|
|
<p>Encrypted backups via integration of the
|
|
<a href="https://github.com/seedvault-app/seedvault">Seedvault app</a> with
|
|
support for local backups and any cloud storage provider with a storage
|
|
provider app.</p>
|
|
|
|
<p>Seedvault was created by a GrapheneOS community member for inclusion in our
|
|
operating system. We plan on replacing it with a new implementation since the
|
|
project has been taken over by another group of people not sharing our goals
|
|
or approach. For now, this is the best available option so we're including it
|
|
to give people encrypted backup support. We've made several security fixes to
|
|
work around upstream issues with the project.</p>
|
|
</section>
|
|
|
|
<section id="location-data-access-indicator">
|
|
<h3><a href="#location-data-access-indicator">Location data access indicator</a></h3>
|
|
|
|
<p>GrapheneOS enables the privacy indicator for location data access in
|
|
addition to the standard Android camera and microphone indicators. This shows
|
|
an indicator when an app the user has granted permission to access location
|
|
requests location data. We also resolve various UX issues with this feature as
|
|
it currently exists in AOSP to get it into a highly usable state.</p>
|
|
|
|
<p>The indicator works the same way as the Camera and Microphone ones, showing
|
|
a bright green icon when location access occurs which then gets minimized to a
|
|
small bright green dot when the quick settings tray isn't currently opened.
|
|
Android 12 already includes Location with the other standard runtime
|
|
permissions in the privacy dashboard for viewing the history.</p>
|
|
|
|
<p>This will likely become a standard feature in Android 13 at which point it
|
|
will be removed from this page.</p>
|
|
</section>
|
|
|
|
<section id="user-installed-apps-can-be-disabled">
|
|
<h3><a href="#user-installed-apps-can-be-disabled">User installed apps can be disabled</a></h3>
|
|
|
|
<p>GrapheneOS adds support for disabling user installed apps instead of only
|
|
being able to disable system apps. This allows users to completely prevent one
|
|
of the apps they've installed from being able to run without being forced to
|
|
uninstall it and lose their app data. This is much stricter than the standard
|
|
force stop feature which only prevents an app from starting itself and the app
|
|
will start running again as soon as another app tries to open an activity or
|
|
service it provides.</p>
|
|
</section>
|
|
|
|
<section id="other-features">
|
|
<h3><a href="#other-features">Other features</a></h3>
|
|
|
|
<p>This is an incomplete list of other GrapheneOS features.</p>
|
|
|
|
<ul>
|
|
<li>Low-level improvements to the <a href="/faq#encryption">filesystem-based
|
|
full disk encryption</a> used on modern Android</li>
|
|
<li>Improved user visibility into persistent firmware security through version
|
|
and configuration verification with reporting of inconsistencies and debug
|
|
features being enabled.</li>
|
|
<li>Authenticated encryption for network time updates via a first party server to
|
|
prevent attackers from changing the time and enabling attacks based on bypassing
|
|
certificate / key expiry, etc.</li>
|
|
<li>Proper support for disabling network time updates rather than just not using
|
|
the results</li>
|
|
<li>Hardened local build / signing infrastructure</li>
|
|
<li><a href="/usage#updates">Seamless automatic OS update system</a> that just
|
|
works and stays out of the way in the background without disrupting device
|
|
usage, with full support for the standard automatic rollback if the first boot
|
|
of the updated OS fails</li>
|
|
<li>Require unlocking to access sensitive functionality via quick tiles</li>
|
|
<li><a href="/faq#bundled-apps">Minimal bundled apps and services</a>. Only
|
|
essential apps are integrated into the OS. We don't make partnerships with
|
|
apps and services to bundle them into the OS. An app may be the best choice
|
|
today and poor choice in the future. Our approach will be recommending certain
|
|
apps during the initial setup, not hard-wiring them into the OS.</li>
|
|
</ul>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="services">
|
|
<h2><a href="#services">Services</a></h2>
|
|
|
|
<p>Service infrastructure features:</p>
|
|
|
|
<ul>
|
|
<li>Strict privacy and security practices for our infrastructure</li>
|
|
<li>Unnecessary logging is avoided and logs are automatically purged after 10 days</li>
|
|
<li>Services are hosted entirely via our own dedicated servers and virtual
|
|
machines from OVH without involving any additional parties for CDNs, SaaS
|
|
platforms, mirrors or other services</li>
|
|
<li>Our services are built with open technology stacks to avoid being locked in to
|
|
any particular hosting provider or vendor</li>
|
|
<li>Open documentation on our infrastructure including listing out all of our
|
|
services, guides on making similar setups, published configurations for each
|
|
of our web services, etc.</li>
|
|
<li>No proprietary services</li>
|
|
<li>Authenticated encryption for all of our services</li>
|
|
<li>Strong cipher configurations for all of our services (SSH, TLS, etc.) with
|
|
only modern AEAD ciphers providing forward secrecy</li>
|
|
<li>Our web sites do not include any third party content and entirely forbid
|
|
it via strict Content Security Policy rules</li>
|
|
<li>Our web sites disable referrer headers to maximize privacy</li>
|
|
<li>Our web sites fully enable cross origin isolation and disable embedding in
|
|
other content</li>
|
|
<li><a href="https://internet.nl/faqs/dnssec/">DNSSEC</a> implemented for all
|
|
of our domains to provide a root of trust for encryption and authentication
|
|
for domain/server configuration</li>
|
|
<li>DNS Certification Authority Authorization (CAA) records for all of our
|
|
domains permitting only Let's Encrypt to issue certificates with fully
|
|
integrated support for the experimental <code>accounturi</code> and
|
|
<code>validationmethods</code> pinning our Let's Encrypt accounts as the only ones
|
|
allowed to issue certificates</li>
|
|
<li>DANE TLSA records for pinning keys for all our TLS services</li>
|
|
<li>Our mail server enforces DNSSEC/DANE to provide authenticated encryption
|
|
when sending mail including alert messages from the attestation service</li>
|
|
<li>SSHFP across all domains for pinning SSH keys</li>
|
|
<li>Static key pinning for our services in apps like Auditor</li>
|
|
<li>Our web services use robust OCSP stapling with Must-Staple</li>
|
|
<li>No persistent cookies or similar client-side state for anything other than
|
|
login sessions, which are set up via SameSite=strict cookies and have
|
|
server-side session tracking with the ability to log out of other
|
|
sessions</li>
|
|
<li>scrypt-based password hashing (likely Argon2 when the available implementations
|
|
are more mature)</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<section id="project">
|
|
<h2><a href="#project">Project</a></h2>
|
|
|
|
<p>Beyond the technical features of the OS:</p>
|
|
|
|
<ul>
|
|
<li>Collaborative, <a href="/source">open source project</a> with a
|
|
<a href="/contact#community">very active community</a> and contributors</li>
|
|
<li>Can make your own builds and make desired changes, so you aren't stuck with
|
|
the decisions made by the upstream project</li>
|
|
<li>Non-profit project avoiding conflicts of interest by keeping commercialization
|
|
at a distance. Companies support the project
|
|
<a href="/faq#company">rather than the project serving the needs of any
|
|
particular company</a></li>
|
|
<li><a href="/faq#privacy-policy">Strong privacy policies</a> across all our
|
|
software and services</li>
|
|
<li><a href="/history/">Proven track record</a> of the team standing up
|
|
against attempts to compromise the integrity of the project and placing it
|
|
above personal gain</li>
|
|
</ul>
|
|
</section>
|
|
</main>
|
|
<footer>
|
|
<a href="/"><img src="{{path|/mask-icon.svg}}" width="512" height="512" alt=""/>GrapheneOS</a>
|
|
<ul id="social">
|
|
<li><a href="https://twitter.com/GrapheneOS">Twitter</a></li>
|
|
<li><a href="https://github.com/GrapheneOS">GitHub</a></li>
|
|
<li><a href="https://reddit.com/r/GrapheneOS">Reddit</a></li>
|
|
<li><a href="https://www.linkedin.com/company/grapheneos/">LinkedIn</a></li>
|
|
</ul>
|
|
</footer>
|
|
</body>
|
|
</html>
|