# How the BitChat Emergency Wipe Triple-Tap Feature Securely Deletes Local Data

> Discover how the BitChat emergency wipe triple-tap feature securely deletes all local data by stopping networks, wiping files, clearing stores, and removing keys.

- Repository: [permissionlesstech/bitchat](https://github.com/permissionlesstech/bitchat)
- Tags: internals
- Published: 2026-07-27

---

**The BitChat emergency wipe triple-tap feature securely deletes all local data by first stopping the mesh networking stack to prevent in-flight messages, then synchronously wiping media files, clearing all persisted stores, and removing cryptographic keys from the iOS keychain before optionally restarting the services.**

BitChat is an open-source, permissionless messaging application that implements a "panic wipe" mechanism for emergency data destruction. When a user triple-taps the `bitchat/` logo in the header, the app executes a coordinated, multi-layer operation orchestrated through the view-model layer to eliminate every trace of persistent state while ensuring no data remnants survive in memory or on disk.

## How the Triple-Tap Gesture Triggers the Emergency Wipe

The emergency wipe begins in [`ContentHeaderView.swift`](https://github.com/permissionlesstech/bitchat/blob/main/ContentHeaderView.swift) where the logo `Text("bitchat/")` registers a **triple-tap gesture** handler. Lines 48-57 capture the user interaction and immediately dispatch to the application coordinator:

```swift
Text("bitchat/")
    .onTapGesture(count: 3) {
        appChromeModel.panicClearAllData()
    }

```

This gesture triggers `AppChromeModel.panicClearAllData()`, defined in [`bitchat/App/AppChromeModel.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/App/AppChromeModel.swift) at lines 13-17. This method serves as the application-level entry point, running any preparation hooks and invoking the optional `onPanicWipe` callback before forwarding the request to the main view-model.

## The Data Destruction Pipeline

The core implementation resides in `ChatViewModel.panicClearAllData(restartServices:)`, defined in [`bitchat/ViewModels/ChatViewModel.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchat/ViewModels/ChatViewModel.swift) at line 1551. This method executes three ordered actions that ensure complete data elimination.

### Step 1: Stopping the Network Stack

Before any data deletion occurs, the method invokes `panicNetworkLifecycle.stop`, which calls `GeohashPresenceService.stopForPanic()` and `NetworkActivationService.stopForPanic()`. This **atomic ordering** prevents in-flight messages from surviving the wipe. The `PanicNetworkLifecycle` struct (lines 92-109 in [`ChatViewModel.swift`](https://github.com/permissionlesstech/bitchat/blob/main/ChatViewModel.swift)) supplies the concrete stop closures that clear live presence advertising and suspend BLE transports, guaranteeing that no packets are sent while the wipe proceeds.

### Step 2: Wiping Media Files

Once the network is secured, `panicRecoveryOperations.wipeMedia()` removes every file under the app's *Application Support* media tree. This includes incoming voice notes, images, and other media payloads. The deletion executes **synchronously on the main actor** to avoid race conditions, and any pending transfer tasks are cancelled to prevent dangling file handles.

### Step 3: Clearing Persisted Stores

The method then invokes `wipe()` on every store implementing the `Wipeable` protocol. According to the privacy assessment documentation in [`docs/privacy-assessment.md`](https://github.com/permissionlesstech/bitchat/blob/main/docs/privacy-assessment.md) (lines 45-53), this includes:

- Outbox and courier mail stores
- Keychain secrets and deduplication state
- Active transport state and managed media directory
- Preferences, group metadata, and hand-added Nostr relays
- Snapshots and other cached data

Each store's `wipe()` method removes its on-disk files and clears in-memory caches, leaving no hidden storage locations.

### Step 4: Sanitizing the Keychain

`KeychainManager.clearAll()` executes `SecItemDelete` for every BitChat key class, removing identity keys, pre-keys, and group keys. These secrets are stored with **device-only accessibility**, and their deletion ensures cryptographic material cannot be recovered even with physical device access.

## Coordinated Restart and Completion

If `restartServices` is true (the default), `panicNetworkLifecycle.restart` re-initializes the BLE mesh and Nostr transports after the wipe completes. This deterministic restart ensures the app returns to a clean state, preventing attackers from reusing stale sessions.

The method returns a `Bool` indicating success, verified by unit tests in [`bitchatTests/ChatViewModelTests.swift`](https://github.com/permissionlesstech/bitchat/blob/main/bitchatTests/ChatViewModelTests.swift) such as `panicClearAllData_stopsNetworkBeforeWipeAndRestartsAfterCommit`, which confirms that stores are emptied and the network layer correctly stops and restarts.

## Security Guarantees of the Implementation

The BitChat emergency wipe triple-tap mechanism provides several security guarantees:

- **Atomic Ordering**: Network services stop before data removal, guaranteeing no in-flight packets survive.
- **Full-Disk Coverage**: Every persistent store explicitly registers a wipe hook, leaving no hidden caches.
- **Synchronous Media Deletion**: Files are removed immediately on the main actor, eliminating race conditions.
- **Keychain Destruction**: Cryptographic secrets are purged from iOS's strongest storage mechanism.
- **Deterministic Restart**: The networking stack re-initializes cleanly, preventing session reuse attacks.

## Summary

- The triple-tap gesture on the `bitchat/` logo in [`ContentHeaderView.swift`](https://github.com/permissionlesstech/bitchat/blob/main/ContentHeaderView.swift) triggers `AppChromeModel.panicClearAllData()`.
- The wipe orchestrates through `ChatViewModel.panicClearAllData()`, which stops the network stack before deleting data.
- Media files are synchronously wiped via `panicRecoveryOperations.wipeMedia()`.
- All stores implementing `Wipeable` execute their `wipe()` methods, clearing files listed in [`docs/privacy-assessment.md`](https://github.com/permissionlesstech/bitchat/blob/main/docs/privacy-assessment.md).
- `KeychainManager.clearAll()` removes all cryptographic secrets using `SecItemDelete`.
- Unit tests verify that data removal is complete and network shutdown/restart occurs in the correct order.

## Frequently Asked Questions

### What happens if I accidentally trigger the BitChat emergency wipe triple-tap?

The emergency wipe executes immediately upon triple-tapping the logo, with no confirmation dialog. Once initiated in `AppChromeModel.panicClearAllData()`, the process completes synchronously before returning control to the user. If `restartServices` is enabled (the default), the app will present a fresh state immediately after wipe completion.

### Does the emergency wipe delete data from other users' devices?

No. The `panicClearAllData()` method only affects local storage on your device. According to the implementation in [`ChatViewModel.swift`](https://github.com/permissionlesstech/bitchat/blob/main/ChatViewModel.swift), the wipe stops the network stack first to prevent outgoing messages, but it cannot retract messages already delivered to other users through the mesh network or Nostr relays.

### Can recovered data be reconstructed after triggering the triple-tap wipe?

No recoverable data should remain. The implementation deletes media files synchronously, clears all stores implementing the `Wipeable` protocol, and removes keychain entries using `SecItemDelete`. The privacy assessment documentation confirms that the wipe covers the outbox, courier mail, managed media, and all cryptographic keys, leaving no forensic traces in standard storage locations.

### How can developers test the emergency wipe functionality?

Developers can invoke `ChatViewModel.panicClearAllData(restartServices:)` programmatically or trigger the UI gesture in [`ContentHeaderView.swift`](https://github.com/permissionlesstech/bitchat/blob/main/ContentHeaderView.swift). The test suite in [`ChatViewModelTests.swift`](https://github.com/permissionlesstech/bitchat/blob/main/ChatViewModelTests.swift) provides verification methods like `panicClearAllData_stopsNetworkBeforeWipeAndRestartsAfterCommit`, which confirm that the network stops before data deletion and that all user-visible stores empty correctly after execution.