Signals of Contact: What Signal Desktop Keeps After You Delete a Chat

RESIDENT.NGO | 23 October 2026

Part I. What people at risk of device searches should know

What we found

While examining our own backup of a Signal Desktop database, we found something unexpected: it still contained dozens of highly sensitive contacts that we believed we had deleted long ago. Some were particularly concerning: merely revealing our association with these individuals could put activists, journalists and human rights defenders at risk.

Initially, we considered whether these records were remnants of years of backups, restores or migrations, or the result of a bug in an older Signal version that had since been fixed. 

We reproduced the behavior in a separate test, ruling out these explanations. On 5 October 2026, we exchanged messages with two test contacts using a newly created Signal account and a device on which Signal had never been installed. One contact was also a member of a Signal group; the other was not. That same day, we deleted the individual conversation with the contact who belonged to the group and confirmed that their identifying information remained in the Signal Desktop database. We reported our findings, including the results of this clean-device test, to Signal on 5 October 2026.

While preparing this report, we considered whether shared group membership might explain why the contact’s information had been retained. To test this hypothesis, on 21 October 2026, we deleted the individual conversation with the second contact, who was not a member of any shared group and with whom we had exchanged messages only on 5 October. Using Signal Desktop 8.32.0 (production, macOS 27.0.1, Apple silicon), we confirmed that both contacts’ identifying information remained in the database after their respective conversations had been deleted.

Figure 1. Deleting a contact in Signal Desktop.

The deleted conversations disappeared from Signal’s interface, and we found no remaining live message records associated with them. However, identifying information about both test contacts remained in Signal Desktop’s local database. The retained information included:

  • The contacts’ Signal profile names;
  • Locally assigned nicknames;
  • Stable Signal account identifiers;
  • Cryptographic records associated with their accounts.

The deleted contact was no longer visible in Signal Desktop’s chat list or in the Signal contact list on the primary phone. Phone address-book synchronization was disabled throughout the test.

Figure 2. Examining the Signal Desktop database with a database parser.

In other words, deleting a conversation does not necessarily erase information that could reveal whom you have communicated with.

Some timestamped metadata also remained in the database. For the second test contact, who was not a member of any shared group, we found a stored identity-key timestamp dated 5 October 2026, when the test messages were exchanged, and a last profile-fetch timestamp of 21 October 2026 at 09:07 UTC, within a minute of the conversation’s deletion. These are not message timestamps: they cannot establish exactly when the first or last message was exchanged. Yet they can still help an examiner build a timeline. The identity-key date suggests when the device first stored the account’s key, and the profile-fetch time may reveal roughly when a chat was last opened or deleted, for example that a chat was deleted shortly before a border crossing.

We value Signal and the privacy principles behind it. Its end-to-end encryption, efforts to minimize the metadata available to Signal itself, and privacy-preserving contact discovery are important protections. 

Our findings do not mean that Signal is insecure or that its encryption is broken. They document a specific behavior in Signal Desktop that we reproduced and verified, and that can put some users at risk. We are publishing these findings because the activists, journalists and human rights defenders we support need to understand that risk and be able to protect themselves.

Why this matters

Consider a human rights defender crossing a border or having their computer seized during a raid. Beforehand, they have deleted sensitive Signal chats and assume their contact list can no longer be reconstructed. An examiner who obtains access to the Signal database stored on an activist’s computer may still find an entry for someone called Carol or Mahatma Gandhi or Martin Luther King Jr., along with that person’s Signal account identifier.

The identifier could be cross-referenced with records recovered from another device or with information already known to the authorities. It is not a public directory lookup of someone’s legal name, and it does not, by itself, prove any messages were exchanged. But it may help link the record to a particular Signal account. A stored name or nickname may also reveal whom the device owner believed the account belonged to.

In a repressive country, even a suspected connection to a journalist, an activist, a confidential source or someone designated by the authorities as an “enemy of the state”, “extremist” may be enough to trigger interrogation, surveillance, detention or prosecution. People may be threatened, abused, tortured or imprisoned because of whom they are suspected of knowing or contacting. The mere suspicion of an association can be dangerous, even without access to message contents.

Our tests confirmed that these records survive normal chat deletion in the tested version of Signal Desktop, but we have not established how long they remain in the database. The discovery of dozens of older contacts in our own backup prompted this investigation, although we have not independently verified when or how each of those records was created or why it was retained.

What users can do now

Deleting individual chats is not a reliable way to remove past contact identities from Signal Desktop. Until there is a verified method for selectively removing the residual identity records, the practical option for clearing the current local Desktop profile is to remove all Signal Desktop application data. This also removes local messages and the Desktop setup. To use Signal Desktop again, a user will have to relink the app to their Signal account. However, relinking may restore the contact information they intended to remove (see below).

Signal provides Settings → General → Delete Data / Delete application data for this purpose. Alternatively, quit Signal completely and delete its entire application-data folder at the standard location for your operating system:

SystemSignal Desktop application-data folder
Windows%APPDATA%\Signal (usually C:\Users\<username>\AppData\Roaming\Signal)
macOS~/Library/Application Support/Signal
Linux~/.config/Signal

These paths are for standard Signal Desktop installations; other packaging, beta versions and custom configurations may use different locations. Delete the data folder, not just db.sqlite, and only after Signal has fully quit. Do not confuse the application-data folder with the directory containing the installed program. Clearing Desktop data does not delete the Signal account on the phone or the data on other devices. 

It may also not remove the contact from your account.  After a conversation is deleted, the retained contact information may still be included in the data Signal synchronizes across linked devices. We confirmed this in a separate test: after relinking Signal Desktop to the same account, the previously deleted contact’s identifying information was restored to the local database. This means that relinking Signal Desktop may reintroduce contact records even after the previous local database has been removed.

If your goal is to ensure these records are absent from your computer before a search or border crossing, do not relink Signal Desktop until afterwards, as doing so may restore contact information. Restoring data from a backup may also bring contact information back.

Neither method is a guarantee that copies are gone from old backups, snapshots or previously deleted storage. Our recommendation addresses the active Signal Desktop profile, not forensic erasure of every historical copy. Users facing an imminent search should consider the consequences of losing their local history and seek advice appropriate to their circumstances.

Signal documents the built-in data-deletion option at Delete Account — Delete Signal Desktop data and the standard folders at Backup and Restore Messages.

Part II. Technical findings

Scope and method

We first reproduced the behavior before notifying Signal on 5 October 2026, using a newly created Signal account and a phone and Mac that had never had Signal installed. No restored database or earlier Signal installation was involved. The reproduction and technical findings were supplied with that notification.

We repeated the deletion on 21 October 2026 [for the second contact] to prepare a reproducible public report. This run used Signal Desktop 8.32.0, production (Apple silicon), on macOS, with the same account and devices as the earlier reproduction. No new messages were exchanged on 21 October. The test conversation contained two messages exchanged on 5 October 2026, an outgoing message at about 08:55 UTC and an incoming reply at about 10:20 UTC, and the contact had been given a local nickname. Between 09:06 and 09:07 UTC we deleted the private conversation using Delete chat and confirmed that it no longer appeared in the Desktop chat list. The contact was also absent from the primary phone’s visible Compose/contact list.

We ran the same conversations query (Command 1) against the live Desktop profile immediately before and immediately after the deletion. At 09:06:26 UTC, before deletion, the contact’s row had active_at set to 1792573429170 (21 October 2026, 09:03:49 UTC). At 09:07:33 UTC, after deletion, active_at was NULL, while the names and serviceId were unchanged. About 34 minutes later, at 09:41 UTC, we quit Signal Desktop, exported a working copy of its local database and ran the audit script on that copy.

We used signalbackup-tools and a local audit script that exported the database once and searched the retained conversation record and associated tables. The recorded tool identification was:

signalbackup-tools (signalbackup-tools) source version 20261001.082556 (SQLite: 3.53.4, OpenSSL: OpenSSL 3.6.5 29 Sep 2026)

Publication redactions: Carol is the local nickname the tester assigned to the test contact. It is a pseudonym, not their real name. The contact’s Signal profile name is a separate value, set by the contact and fetched from Signal, and is replaced with [profile name]. Signal account IDs and local conversation IDs are partly masked; sensitive key and credential values are replaced with [REDACTED]. The two outputs below show selected fields from our recorded results, not byte-for-byte terminal transcripts. The retained field values, record counts, timestamps and session sizes have not otherwise been altered.

Command 1 — retained contact row

The following query was run against the live Desktop profile immediately before and after the deletion. The output below is from the run after deletion and includes only the deleted test contact, rather than every database row.

signalbackup-tools --rundtprettysqlquery \
"SELECT id,
        type,
        name,
        profileFullName,
        profileName,
        e164,
        serviceId,
        active_at
 FROM conversations
 ORDER BY active_at DESC"

Output after deletion (contact row only; profile name and identifiers redacted):

id                  | type    | name   | profileFullName | profileName    | e164   | serviceId           | active_at
--------------------|---------|--------|-----------------|----------------|--------|---------------------|----------
01a1…2c24           | private | (NULL) | [profile name]  | [profile name] | (NULL) | 0ed7…837d           | (NULL)

The serviceId is the Signal account identifier (ACI in this test). It can be compared with the same account identifier in other sources. The local id identifies the record within this database; it should not be confused with the account identifier. In this test e164 was NULL, so the row did not reveal a phone number. The name column is NULL. The locally assigned nickname is stored only in the row’s JSON (nicknameGivenName, see Command 2), so the record holds two independent names: the one the contact chose and the one the device owner assigned. Names and nicknames are not verified legal identities.

Command 2 — retained JSON and related cryptographic records

To inspect the actual JSON structure and check identity keys, protocol sessions and remaining messages without the separate audit script, run this read-only query. The nickname Carol is the test value; substitute the locally assigned nickname of the contact being examined. This SQL is a self-contained reproduction query, not a claimed verbatim transcript of the audit script’s invocation.

signalbackup-tools --rundtsqlquery \
"SELECT json_pretty(json_object(
    'contact_row', json_object(
        'id', c.id,
        'json', json(c.json),
        'active_at', c.active_at,
        'profileLastFetchedAt', c.profileLastFetchedAt,
        'e164', c.e164,
        'serviceId', c.serviceId
    ),
    'identityKeys', (
        SELECT json_group_array(json_object('id', k.id, 'json', json(k.json)))
        FROM identityKeys k WHERE k.id = c.serviceId
    ),
    'sessions', (
        SELECT json_group_array(json_object(
            'conversationId', s.conversationId,
            'serviceId', s.serviceId,
            'deviceId', s.deviceId,
            'record', json_object('blob_bytes', length(s.record))
        ))
        FROM (SELECT * FROM sessions
              WHERE conversationId = c.id ORDER BY deviceId) s
    ),
    'liveMessages', (
        SELECT COUNT(*) FROM messages m WHERE m.conversationId = c.id
    )
)) AS retained_contact
FROM conversations c
WHERE json_extract(c.json, '$.nicknameGivenName') = 'Carol'"

Recorded audit values (not output of the query above). We did not run this query on the test database. The JSON below was assembled from the captured contact.json and related-records.json in the query’s structure, with selected fields only and identities and cryptographic values redacted:

{
  "contact_row": {
    "id": "01a1…2c24",
    "json": {
      "id": "01a1…2c24",
      "type": "private",
      "serviceId": "0ed7…837d",
      "lastMessage": "",
      "timestamp": null,
      "nicknameGivenName": "Carol",
      "storageID": "[REDACTED]",
      "storageVersion": 24,
      "profileKeyCredential": "[REDACTED]",
      "profileKeyCredentialExpiration": 1793145600000,
      "accessKey": "[REDACTED]",
      "profileKey": "[REDACTED]",
      "profileName": "[profile name]",
      "lastProfile": {
        "profileKey": "[REDACTED]",
        "profileKeyVersion": "[REDACTED]"
      },
      "messagesDeleted": true
    },
    "active_at": null,
    "profileLastFetchedAt": 1792573641900,
    "e164": null,
    "serviceId": "0ed7…837d"
  },
  "identityKeys": [
    {
      "id": "0ed7…837d",
      "json": {
        "id": "0ed7…837d",
        "publicKey": "[REDACTED]",
        "verified": 0,
        "firstUse": true,
        "timestamp": 1791190960289
      }
    }
  ],
  "sessions": [
    {
      "conversationId": "01a1…2c24",
      "serviceId": "0ed7…837d",
      "deviceId": 1,
      "record": {
        "blob_bytes": 5894
      }
    },
    {
      "conversationId": "01a1…2c24",
      "serviceId": "0ed7…837d",
      "deviceId": 2,
      "record": {
        "blob_bytes": 4837
      }
    },
    {
      "conversationId": "01a1…2c24",
      "serviceId": "0ed7…837d",
      "deviceId": 3,
      "record": {
        "blob_bytes": 5888
      }
    }
  ]
}

Unrelated keys have been omitted; this is not an unmodified dump. The values messagesDeleted: true, active_at: null, and lastMessage: “” were present after deletion. The audit did not record a message count. It found no rows in the messages table referencing this conversation or account, which is why no liveMessages value is shown. The audit did not examine the full-text search tables (messages_fts and its shadow tables, including messages_fts_content), free pages in the database file, or the write-ahead log (-wal), so it does not rule out residual message text there. The contact’s e164 was null in this test, so no phone number was found in that field.

One public identity-key record and three stored Signal Protocol session records remained. The three session records were associated with device IDs 1, 2 and 3, with sizes of 5,894, 4,837 and 5,888 bytes respectively. This is not evidence that three physical devices were currently online, nor does it reveal message contents. Three dates associated with the deleted contact were still recoverable:

Retained fieldOriginal value (Unix milliseconds)UTC dateInterpretation
identityKeys[0].json.timestamp17911909602895 October 2026, 09:02:40.289Timestamp stored with the contact’s identity-key record. It falls on 5 October, the day the test messages were exchanged, but about seven minutes after the first message visible in the conversation (sent at about 08:55 UTC), so it is not a first-contact or first-message timestamp.
contact_row.profileLastFetchedAt179257364190021 October 2026, 09:07:21.900Last recorded retrieval of this contact’s profile. It falls inside the roughly one-minute window in which we deleted the chat (still active in the database at 09:06:26 UTC, cleared by 09:07:33 UTC), five seconds before our post-deletion screenshot. We did not determine what triggered the fetch. It does not identify the last conversation, but it may approximate when the chat was last opened or deleted.
contact_row.json.profileKeyCredentialExpiration179314560000028 October 2026, 00:00:00Expiration time for the profile-key credential; it is not evidence of an interaction on this date.

The fields most directly associated with the deleted chat’s visible history were cleared: active_at was null, contact_row.json.timestamp was null, lastMessage was an empty string, messagesDeleted was true, and the audit found no rows in messages for the conversation. No retained field records the date the contact was originally added, the date of the first or last message, or the date the conversation was deleted. In our test, however, profileLastFetchedAt was set within a minute of the deletion, so it approximated the deletion time, and the identity-key date fell on the day the messages were exchanged. Both are relevant to a forensic timeline, but neither should be interpreted as proof of when two people communicated. The test does not demonstrate an encryption bypass or forensic recovery of deleted messages.

Significance and limits

The private conversation was removed from the UI, while the retained record explicitly carried messagesDeleted: true, a null active_at, the test contact’s profile name and nickname, an account-level serviceId, profile cryptographic metadata, a public identity key, and protocol sessions. In our controlled test, messages had been exchanged before deletion. The test contact also shared no groups with the test account, so the retained record was not the result of a shared group. In an unrelated forensic examination, the mere presence of a contact record would not by itself prove that two people exchanged messages, nor would a matching serviceId establish the legal identity of the person controlling the account. It can, however, provide a strong correlation key when that identity is established through other evidence.

The retained record also kept its Storage Service fields: storageID (redacted above), storageVersion: 24 and needsStorageServiceSync: false. Signal uses its encrypted Storage Service to sync contacts and their settings, including nicknames, across an account’s devices. These fields indicate that the contact remained part of that synced contact data after the chat was deleted. The retention may therefore not be limited to the Desktop database, and linking Signal Desktop again may bring the record back. We did not test re-linking, or what the phone stores.

The experiment was performed only on macOS. Signal Desktop also runs on Windows and Linux, but we do not claim runtime reproduction on those platforms here. Signal’s Android and iOS applications were outside the scope of this investigation. We would welcome careful research into whether either mobile application exhibits comparable contact-metadata retention.

Signal Desktop’s published schema for the tested release is available at v8.32.0/DATABASE_SCHEMA.md.

Notification to Signal and decision to publish

We reported the contact-metadata retention issue to Signal through its official security-reporting channel on 5 October 2026. Our report to Signal already included the clean-device reproduction and technical information: we had reproduced the issue with a new account and a phone and Mac on which Signal had never previously been installed. On 21 October 2026, we repeated the deletion with Signal Desktop 8.32.0, on a test conversation from that same setup, to prepare the evidence and reproducible steps for this public report. As of publication on 23 October 2026, we had not received a response from Signal.

We consider this a responsible disclosure: we notified Signal before publishing, documented the issue carefully, and limited our public evidence to masked identifiers and selected technical details. We chose not to wait a full 30 days after the notification because closely related concerns had already been described publicly, and people facing searches and device seizures need to know that deleting chats may leave identifiable contacts behind. We do not know whether Signal plans to change this behavior or, if it does, when a fix might be available. We therefore consider it important to warn the people and organizations we support without further delay.

Related publications found after our investigation

After documenting the problem ourselves, we found two earlier publications describing related contact-retention behavior:

These publications provide useful context, but the findings and measurements presented above come from our own test and preserved audit data.