interplains/Zero-Breach-Toolkit
Free, open-source, offline checks for traces of known mercenary spyware. Works on Windows, macOS and Linux, Android phones and iPhone backups.
About interplains/Zero-Breach-Toolkit
interplains/Zero-Breach-Toolkit is an open-source project on GitHub, mainly written in Python. Free, open-source, offline checks for traces of known mercenary spyware. Works on Windows, macOS and Linux, Android phones and iPhone backups. It currently holds 1,801 stars and 198 forks with 3 open issues, and was last pushed on 2026-10-28 (repository created 2026-10-25).
Project Overview
Git Homed tracks it on the Today's Trending board.
GitHub Repository Details
README
Zero Breach Toolkit
A free, open-source check for traces of known mercenary spyware (Pegasus, Predator, Graphite, Candiru and others) on computers, Android phones and iPhone backups.
- Read-only. It does not modify source evidence or system settings. It writes only
- No network requests during a scan. It never looks up spyware addresses and has no
- States its limits. Every report says what was found, how strong the evidence is, and
Made by archivegenocide. Built on Zero Breach.
If you think you are being targeted right now, get expert help first. You do not
need to run this tool before asking. Journalists, activists, human-rights defenders and
civil society can contact the
Access Now Digital Security Helpline (free, 24/7,
many languages) or Amnesty International's Security Lab.
---
Step-by-step guide (no technical experience needed)
You do not need a GitHub account or any technical knowledge. You need a Windows or Mac computer and about 20 minutes. Phones are checked by connecting them to the computer.
What do you want to check? This Windows computer · This Mac · An Android phone · An iPhone
Windows
Set up (only the first time)
1. Go to python.org/downloads and click the yellow Download Python button. Open the downloaded file. 2. On the first screen of the installer, tick "Add python.exe to PATH" at the bottom, then click Install Now. Wait until it says "Setup was successful". 3. On this page, click the green Code button near the top, then Download ZIP. 4. Open your Downloads folder, right-click Zero-Breach-Toolkit-main.zip and choose Extract All, then Extract.
Run the check
5. Close your web browsers and chat apps (Chrome, Edge, WhatsApp, Signal…).
6. Open the Zero-Breach-Toolkit-main folder (if there is another folder with the same name
inside, open that one too), then the scan folder, and double-click run-scan.cmd.
If Windows shows a warning, click Run (or More info, then Run anyway).
7. A menu appears. Type the number next to Update the indicator lists and press Enter,
then type y and press Enter. When it finishes, press Enter.
8. Press Enter again to start This computer - standard check. It takes about 15 minutes.
9. Read the result at the end (see What the result means). A copy
is saved in the findings folder inside Zero-Breach-Toolkit-main.
Mac
Set up (only the first time)
1. Go to python.org/downloads, click Download Python, open the downloaded file and follow the installer. 2. On this page, click the green Code button, then Download ZIP. It appears in your Downloads folder as Zero-Breach-Toolkit-main (if it is still a .zip file, double-click it). 3. Open System Settings → Privacy & Security → Full Disk Access, click +, choose Applications → Utilities → Terminal, and turn it on. Without this, macOS hides Safari's records from the check.
Run the check
4. Close your web browsers and chat apps.
5. Open Terminal (press Cmd+Space, type Terminal, press Enter). Copy this line, paste it
into Terminal and press Enter:
cd ~/Downloads/Zero-Breach-Toolkit-main && python3 -X utf8 scan/zero-breach-toolkit.py
6. A menu appears. Type the number next to Update the indicator lists and press Enter,
then type y and press Enter. When it finishes, press Enter.
7. Press Enter again to start This computer - standard check. It takes about 15 minutes.
8. To keep a copy of the result, type 3 and press Enter, type report.txt and press Enter.
It is saved in the Zero-Breach-Toolkit-main folder. Type 0 to finish.
On Linux, follow the Mac steps without step 3.
Android phone
First do the Set up steps for Windows or Mac above.
On the phone
1. Open Settings → About phone and tap Build number seven times, until it says you are a developer. (On Samsung: Settings → About phone → Software information → Build number.) 2. Go back to Settings, open Developer options (often under System) and turn on USB debugging. 3. Connect the phone to the computer with a USB cable that carries data (some cables only charge). Unlock the phone. When it asks Allow USB debugging?, tick Always allow and tap Allow.
On the computer
4. Start Zero Breach (Windows: double-click run-scan.cmd; Mac: step 5 of the Mac guide).
5. In the menu, type the number next to A phone and press Enter, then type 2 (Collect
from an Android phone connected by USB now) and press Enter.
6. Press Enter to save the collection on your Desktop, then type YES and press Enter.
7. The collector asks a few questions. Use the arrow keys and Enter to answer:
| It asks | Choose | |---|---| | Backup | Only SMS | | Download copies of apps | Only non-system packages | | Remove copies of apps signed with a trusted certificate | No | | Intrusion Logs | No | | Hash files | No | | Anything else | No |
8. If the phone shows Back up my data, tap it (leave the password empty). Keep the phone unlocked until the collection finishes. 9. The check starts by itself and shows the result. 10. When you are done, turn USB debugging off again on the phone.
iPhone
First do the Set up steps for Windows or Mac above.
1. Make a backup on the computer. Connect the iPhone with a cable and tap Trust on the phone.
- Windows: install Apple Devices from the Microsoft Store, open it and select the iPhone.
- Mac: open Finder and select the iPhone in the sidebar.
- Windows: press Windows key + R, paste
%USERPROFILE%\Apple\MobileSync\Backupand press
- Mac: in Finder, choose Go → Go to Folder, paste
~/Library/Application Support/MobileSync/Backup and press Enter.
Inside is a folder with a long name of letters and numbers: that is your backup.
4. Start Zero Breach. In the menu, type the number next to A phone, press Enter, type 1
and press Enter.
5. Drag the backup folder (the one with the long name) into the Zero Breach window and press
Enter.
6. When asked whether the backup is password-protected, type y and press Enter, then type the
backup password (nothing appears while you type) and press Enter.
If something goes wrong
| What you see | What to do |
|---|---|
| 'python' is not recognized or nothing happens on Windows | Run the Python installer again, choose Modify, and make sure Add Python to environment variables is ticked. Restart the computer. |
| No such file or directory on a Mac | The folder has a different name. In Terminal type cd (with a space), drag the Zero-Breach-Toolkit-main folder into Terminal, press Enter, then run python3 -X utf8 scan/zero-breach-toolkit.py. |
| command not found: python3 | Install Python from python.org (step 1), then close and reopen Terminal. |
| Android: the collector finds no phone | Unlock the phone, use a different cable or USB port, and check Allow USB debugging was accepted. Unplug and plug in again. |
| iPhone: "wrong password" | Use the password chosen when Encrypt local backup was first turned on. If it is forgotten, it can be reset on the iPhone (Settings → General → Transfer or Reset iPhone → Reset → Reset All Settings), then make a new backup. |
| Safari "could not be checked" on a Mac | Give Terminal Full Disk Access (Mac step 3), close Terminal, open it again and run the check again. |
Still stuck? Ask in the issues (do not post your report there; it contains private details).
What the result means
- "No known indicators found": nothing from the published spyware lists was found in
- "Something matched": this means look closer, not you are infected. Do not delete
- The report never leaves your computer unless you send it to someone yourself.
What it checks
Windows
No administrator rights are needed.
| Where | What it looks for | |---|---| | Browsers at their default locations: Chrome, Edge and Brave (including beta, dev, canary and nightly channels), Chromium, Vivaldi, Opera, Opera GX, Arc, Yandex; Firefox, LibreWolf, Waterfox, Floorp, Zen, Pale Moon, Tor Browser | indicator addresses in history, cookies, connection records, HSTS, bookmarks, downloads, site storage and caches, per profile | | Desktop apps with a built-in Chromium browser | supported history, cookie and storage records; raw app web caches are skipped and reported as a gap | | Downloaded files | the website each file came from (the "Mark of the Web" stamp) | | The Win+R box | commands people were tricked into pasting by fake "verify you are human" pages | | Antivirus status and Microsoft Defender history | registered antivirus products and their reported status; past Defender detections, protection-off events and added exclusions | | PowerShell log | scripts that named a spyware address, or downloaded and ran code | | Programs listed by Windows | existing files named in the shim cache and the Windows 11 launch list, compared with published sample fingerprints; not a complete execution history | | Prefetch and Amcache | supported Prefetch executable-name records and Amcache file inventory; the program files they name are never opened | | Selected user folders | fingerprints of candidate files, within size and directory limits | | DNS cache, DNS history, hosts file, COM and startup/task/service registrations | known indicators in supported network and persistence records; not a full persistence audit |
A Prefetch match (execution-record) does not identify the file's contents or full path;
an Amcache match (inventory-record) does not prove execution or that the file still
exists. Locked or unsupported records are gaps.
Antivirus status comes from Windows Security Center, including third-party products such as Bitdefender that register there. An active registered product puts an old Defender-off event in context; it does not mean protection is off now. Registration is not a health test, some enterprise products do not register, and unavailable status is a gap. A desktop app such as Slack is listed because its web records were checked, not because it is suspicious.
The default hash check covers .dll, .exe, .sys, .ocx, .cpl, .scr, .tmp,
.dat, .bin and .ax files up to 120 MiB in selected folders, skipping cache and
dependency directories. Computer checks can find published infrastructure or file traces;
they cannot tell whether a phone is infected.
macOS and Linux
The same browsers are checked at their default locations, plus common Snap and Flatpak
packages and Firefox's newer ~/.config/mozilla profile folder on Linux. On a Linux desktop
in another language, the translated Downloads, Desktop and Documents folders are found from
user-dirs.dirs. File fingerprints, separate browser cache locations and bounded saved-record
checks run without administrator access.
- Safari (macOS): history and profile databases, open and iCloud tabs, the URL cache,
- Startup configuration: on Linux, standard autostart
.desktopentries, systemd units
.conf overrides, cron configuration and scheduled script directories; on
macOS, standard LaunchAgent and LaunchDaemon property lists. A launch item's program is
compared as an executable path and, by its file name, as a process name.
- Shell and logs (both): standard shell startup files, saved Bash/Zsh/fish history
~/.zsh_sessions), the hosts file and
readable current text system logs. Paths inside $( ) and backticks are recognised. Large
history and log files are limited to recent records; the omitted part is a gap.
These read saved configuration, not which jobs are enabled or ran. Network strings are references; exact known executable paths in supported launch configuration can be findings, with activation and execution unverified.
File checks also cover extensionless files, executables, native libraries and scripts in selected application, user and temporary folders (120 MiB limit). Windows-only live checks do not run here; copied Prefetch and Amcache files can still be selected in targeted mode, though compressed Prefetch needs Windows.
Desktop apps
Apps with a built-in Chromium browser are found by their folder contents under AppData (Windows), Application Support (macOS) or the user and Flatpak configuration folders (Linux), including apps whose own folder is a Chromium profile, such as Signal on macOS. The search has no fixed depth limit; it is bounded by folder count and time, and reaching that bound is reported as a gap.
Android
The tool reads a collection made with AndroidQF; it never talks to the phone itself. It checks:
- installed and running apps, their fingerprints and signing certificates;
- the install history, so an app that was installed and later removed still shows;
- system records, logs and crash records;
- supported, already decrypted intrusion logs: DNS lookups, TCP connection attempts and
- links in SMS and MMS messages, from the SMS backup AndroidQF offers to take;
- apps installed outside an app store, with what they can do (read SMS, use the
- signs of a modified phone: unlocked bootloader, debug build, security protection off.
iPhone
Local Finder, Apple Devices or iTunes backups (encrypted or not), extracted file systems and sysdiagnose archives. See Checking local iPhone evidence.
Indicators
About 12,400 published indicators from 29 sources: Amnesty International's Security Lab,
the Mobile Verification Toolkit project,
the Citizen Lab and Echap's stalkerware research, and a hand-curated set from Citizen Lab
reports (Candiru / DevilsTongue and Paragon's Graphite) with every line cited. The curated
set works offline; --update downloads the rest from a fixed list of official sources.
---
Install and run
You need Python 3.8 or newer (python.org; on Windows,
tick "Add python.exe to PATH" when installing). No administrator rights and no extra
packages. On macOS and Linux type python3 instead of python.
1. Get the toolkit. On GitHub choose Code → Download ZIP and extract it, or:
git clone https://github.com/interplains/Zero-Breach-Toolkit.git
2. Open a terminal in the toolkit folder. Windows: open the extracted
folder (Zero-Breach-Toolkit, or Zero-Breach-Toolkit-main from a ZIP), click the address bar, type powershell and press
Enter. macOS: open Terminal, type cd (with a space), drag the folder into the window
and press Enter. Run every command below from this folder.
3. Recommended: download the latest indicator lists. This is optional and is the only
step that uses the internet; the checks themselves never do. Without it only a small
built-in set is used. Repeat it every few weeks.
python -X utf8 scan/zero-breach-toolkit.py --update
4. On a Mac, give Terminal Full Disk Access first (System Settings → Privacy & Security
→ Full Disk Access → add Terminal, then reopen it). Without it macOS blocks Safari's
records and some folders, and the report lists them as not checked.
5. Close your browsers and chat apps, then run the check. A menu opens; press Enter for
the standard check of this computer.
python -X utf8 scan/zero-breach-toolkit.py
On Windows you can instead double-click scan\run-scan.cmd. It saves the readable and
JSON reports in a findings folder next to the toolkit.
Reports contain private details from your computer; keep them out of shared and synced folders. Useful options:
python -X utf8 scan/zero-breach-toolkit.py --quick # faster: skips file fingerprints
python -X utf8 scan/zero-breach-toolkit.py --phone "FOLDER" # a phone collection or backup
python -X utf8 scan/zero-breach-toolkit.py --json report.json # machine-readable report
python -X utf8 scan/zero-breach-toolkit.py --share-json summary.json # minimal summary for sharing
Put folder paths in quotes, especially if they contain spaces. On Linux or macOS,
sh scan/run-scan.sh takes the same options.
Verify what you run
The project is anonymous, so do not take its word for anything. Verification rests on what you can reproduce.
Running from source, as above, means every line the tool executes is in the clone: nothing is compiled and nothing is fetched in order to run.
The single-file zero-breach-toolkit.py attached to a release is generated from the same
source. Rebuild it from the release's tag and compare:
git checkout v0.1.7
python build/bundle.py
python -c "import hashlib; print(hashlib.sha256(open('dist/zero-breach-toolkit.py','rb').read()).hexdigest())"
For v0.1.7 the file is 959,996 bytes, SHA-256
1fd1c8cf194f24a295005beb96836dd3bdec522134870c8b83f4b834b83c0cfd. The size and SHA-256
published with each release are authoritative. The build is deterministic, so a matching
rebuild means the published file contains that source and nothing else. Releases are also
GPG-signed; see docs/VERIFYING.md.
There is no signed Windows program, and none is planned while the project stays anonymous:
code-signing certificates require a named legal identity. An .exe you build yourself with
PyInstaller is unsigned, has no download reputation and is not byte-reproducible, so
SmartScreen will warn, some antivirus products will flag it, and the comparison above does
not apply. Running from source avoids all of that.
Checking an Android phone
1. On the phone, turn on Developer options (Settings → About phone → tap Build number seven times), then turn on USB debugging. 2. Connect the phone by USB and tap Allow when it asks about this computer. 3. Download and run AndroidQF on the computer. Answer its questions like this:
| AndroidQF asks | Answer | |---|---| | Take a backup of the device? | Only SMS | | Download copies of all apps or only non-system ones? | Only non-system packages | | Remove copies of apps signed with a trusted certificate? | No | | Take the Intrusion Logs? | No, unless you turned on Intrusion Logging | | Hash files on the device? | No (Yes also checks file fingerprints, but it is slow and can stop the collection on some phones) | | Browser history / Magisk modules? | No |
On the phone, confirm the backup with Back up my data.
4. AndroidQF saves a .zip next to itself. Extract it.
5. From the toolkit folder, check the extracted folder (keep the quotes):
python -X utf8 scan/zero-breach-toolkit.py --phone "PATH TO THE EXTRACTED FOLDER"
Or run the tool with no options, choose A phone, and drag the folder into the window.
6. Turn USB debugging off again.
The collection holds private information about the phone. Keep it on your computer.
Use --phone-guide android for preparation steps and --phone FOLDER --preview to list
which artifacts are available. For an AES-encrypted backup.ab, add --backup-password;
the password is asked for privately at the terminal and never appears as an argument or in
a report. Age-encrypted acquisition archives must first be decrypted with the owner's
identity using the separate age tool; this scanner does not launch it.
Guided acquisition (experimental). --collect-android LOCAL_OUTPUT_FOLDER downloads
official AndroidQF v1.8.3, checks its pinned SHA-256, asks for the device owner's explicit
consent and runs the collector's interactive prompts. After a successful plaintext
acquisition it extracts the archive locally and checks the collection. Acquisition changes
phone state and saves private records; it is separate from read-only scanning.
This is the only point at which the tool runs a program it did not ship:
- the asset name and expected digest are fixed in the source;
- the file is fetched over HTTPS from the publisher's release, with redirects limited to an
- if the digest does not match, acquisition is refused and nothing is executed;
- the collector is written to a temporary directory and run directly, not through a shell,
ADB_, ANDROID_ADB_, LD_ and DYLD_ variables removed and PATH reset to the
system directory, then deleted when the command finishes;
- nothing is downloaded or run unless you invoke the command and confirm consent.
--age-recipient-file PATH supplies public age1 recipients (private identity files are
refused). When encryption is requested, a plaintext result is refused. An encrypted result
must have a supported age envelope and no unexpected extra files, but these format checks
cannot authenticate it or verify the recipient. It is saved for separate decryption; the
command succeeds without producing a scan or an all-clear. After a failure, check the
reported folder: original or partial records are kept and may be unencrypted.
Checking local iPhone evidence
1. Make a local backup with Finder (Mac) or Apple Devices / iTunes (Windows). Tick
Encrypt local backup: encrypted backups include more of the records this tool checks.
2. Find the backup folder (one per device, with Manifest.plist inside): on a Mac
~/Library/Application Support/MobileSync/Backup/, on Windows
%USERPROFILE%\Apple\MobileSync\Backup\.
3. From the toolkit folder (keep the quotes; leave out --backup-password if the backup
is not encrypted, and the password is asked for privately):
python -X utf8 scan/zero-breach-toolkit.py --phone "PATH TO THE BACKUP FOLDER" --backup-password
--phone-guide ios and `--pho