A07
Bootloader setting: compromised, report, offValidated
The build-time bootloaderUnlocked setting changes only how bootloader_unlocked counts. Root keeps the device compromised whatever it's set to.
How to read this page
A scenario is one test case: prepare the environment, run the steps, then compare the expected result (written before the run) with the observed result (copied from the run, with screenshots).
- A07 · A
- Run on a real phone that's been attacked or modified — rooted, jailbroken, hooked or hidden.
- Validated
- Run, and the result matched what was expected.
Why it matters
Relaxing bootloader_unlocked for developer phones must not hide root. This proves the setting and the root checks are independent.
Environment
- App
- Example app, library 0.3.0, built once per setting through the Expo config plugin
- Device
- OnePlus Nord 3 (CPH2493), Android 15, bootloader unlocked (orange)
- Root
- Magisk 31.0, no hiding
Setup
Prepare the environment.Then run the steps.
- 01Set android.bootloaderUnlocked in the plugin options (none for the default, then report, then off), run expo prebuild and install each build.
- 02For the root-ignored cases, pass ignore: ['root_su_binary', 'root_management_apps', 'root_magisk_files'] so bootloader_unlocked is the only evidence left.
Steps
What to run.What to read.
- 01Default, nothing ignored (see A01).
- 02Default, root signals ignored.
- 03Default, ignore: ['bootloader_unlocked'].
- 04report, nothing ignored.
- 05report, root signals ignored.
- 06off, nothing ignored.
Expected result · written before the run
No single pass/fail status.4 signals.
compromised whenever root is active. With root ignored: compromised on the default (bootloader_unlocked counts), clean on report (it's listed but not counted). off removes the signal entirely.
Observed result · copied from the run
No single pass/fail status.Observed 2026-10-06.
Every result matched. The only setup that reads clean is report with the root signals ignored, which is the point of report: an unlocked phone without root evidence. The built manifest carried report / off / no entry as set.
Default: compromised, 4 signals (A01, 235 ms) · default, root ignored: compromised, Signals (1) bootloader_unlocked, Ignored 3 (298 ms) · default + ignore bootloader_unlocked: compromised, Signals (3) root, Ignored 1 (245 ms) · report: compromised, Signals (4) (232 ms) · report, root ignored: clean, Signals (1) bootloader_unlocked, Ignored 3 (251 ms) · off: compromised, Signals (3) root, no bootloader_unlocked (270 ms)
![Default build with ignore: ['bootloader_unlocked']: status COMPROMISED, three root signals; bootloader_unlocked moved to Ignored.](/_next/image?url=%2Fevidence%2Fa07-default-ignore-bootloader.jpg&w=3840&q=75)



Limitations
Root was active and visible in every run. With root hidden (A02) and the setting on report or off, a rooted phone whose Magisk app is also renamed would read clean — keep the default in production.
Emulators: on the Google Play image (S02) the boot properties are empty, so bootloader_unlocked can't fire; on a development image reporting orange (S11) the emulator skip keeps it out — both verified on 0.3.0.
Checks this scenario covers
Every check this test case touches — including ones that aren't expected to fire here. The expected and observed results above say which ones should and did. Each links to how the check works.