[libtacky / Link Previews] OMEMO 0.3 fetches link preview resources even though the preview is not sent #18

Open
opened 2026-11-05 09:52:15 +00:00 by fmodf · 1 comment

Moved from another-im/anotherim-swift#22, reported by @asemeniv on 2026-11-04. The evidence archive is attached below.

[libtacky / Link Previews] OMEMO 0.3 fetches link preview resources even though the preview is not sent

Severity: Minor
Issue ID: LP-04i
Date: November 4, 2026
Device Status: Not Run — failure expected based on test-environment findings and build 94 source code

Summary

When Settings → Privacy → Link Previews is set to Others' and Mine, libtacky fetches the linked webpage and its preview image even when the outgoing conversation uses legacy OMEMO 0.3, which does not support transmitting the generated preview.

As a result, the destination website receives a request from the sender's device, potentially revealing its IP address and request timestamp, while the recipient receives no link preview.

The issue occurs because preview generation begins before the outgoing message's OMEMO profile is determined.

The default Others' Only setting does not trigger this sender-side behavior.

Affected component: libtacky, message.tcl (outgoing message and preview generation).

Environment

Item Details
Application anotherim-swift 8f62071, branch feat/ui-redesign, build 94
libtacky 2f42a2f2 / v1.2.0-beta2
Server ejabberd 26.09, anotherim-server b9e675d
Sender main@example.local, libtacky application profile
Recipient peer2@example.local, OMEMO contact
Encryption Legacy OMEMO 0.3 (omemo set_mode legacy)
Link Previews link_previews always — Others' and Mine
Test URL https://page.lp.test/p4
Test page checks/lp_server.py, network namespace at 1.2.3.4
Verification Level 1 test environment

The test webpage uses a certificate signed by the test environment's CA, configured through tls_ca_file.

Preconditions

  1. Set Link Previews to Others' and Mine.
  2. Establish a conversation using legacy OMEMO 0.3.
  3. Make the test webpage accessible to the sender's HTTP client.

Steps to Reproduce

Run:

SWIFT_SRC=<anotherim-swift-build-94> SERVER_SRC=<anotherim-server> bash setup/run_all.sh run_link_preview

The test requires root privileges for ip netns.

  1. LP-CTRL: Fetch https://page.lp.test/ctrl through linkmeta preview and confirm that the page server records the request.

  2. LP-02: Send a link using OMEMO 2 and confirm that the recipient receives the preview inside the encrypted envelope.

  3. LP-04: Switch the conversation to legacy OMEMO:

    omemo set_mode peer2 legacy

  4. Send:

    old https://page.lp.test/p4 here

  5. Inspect the page server's request log (lp_requests_<run>.jsonl).

  6. Inspect the message received by peer2 for link preview metadata.

Expected Behavior

If the selected encryption profile cannot transmit link preview metadata, the sender should skip preview generation entirely.

The linked webpage and its associated resources should not be fetched solely for a preview that will be discarded.

This follows the privacy considerations in XEP-0511 v0.1.1 §7, which explain that fetching a remote resource can disclose the sender's interest and network address.

libtacky also documents in linkmeta.tcl:34-36 that the legacy encryption profile does not carry additional preview metadata.

The application's setting explains that a preview is generated by fetching the page from the device, establishing the intended relationship between the network request and preview functionality.

This is a privacy recommendation, not an explicitly documented product requirement.

Actual Behavior

The supplied test report identifies run cb11caf1 as reproducing the issue.

The legacy-OMEMO message was sent at approximately 20:00:36 UTC on November 4, 2026.

Relevant evidence:

  • evidence/run_link_preview_1.out
  • evidence/lp_requests_cb11caf1.jsonl
  • events_main_cb11caf1

The outgoing message contained:

old https://page.lp.test/p4 here

According to the reported behavior, libtacky initiated preview-resource fetching even though the legacy OMEMO profile did not include the generated preview in the outgoing message.

The supplied excerpt ends before the individual HTTP request records and received-message evidence. Those records should be attached to establish the exact resources fetched and confirm that the recipient received no preview.

Root Cause

Preview generation is initiated in libtacky's outgoing message processing before the final OMEMO encryption profile is known.

The legacy OMEMO profile cannot carry the additional link preview metadata, so the generated preview is omitted from the outgoing message.

However, the webpage request has already occurred.

This creates an unnecessary privacy disclosure: the sender's device contacts the website without delivering the preview that justified the request.

Suggested Fix

Determine whether the selected outgoing encryption profile supports link preview metadata before initiating any preview-related HTTP requests.

For legacy OMEMO 0.3:

  • Skip fetching the webpage and preview image.
  • Send the original message without preview metadata.
  • Preserve the existing preview behavior for supported profiles, including OMEMO 2.

Verification After Fix

  1. Enable Others' and Mine link previews.
  2. Send a URL in an OMEMO 0.3 conversation.
  3. Verify that no HTTP requests are made to the linked webpage or its preview resources.
  4. Verify that the recipient receives the original message normally.
  5. Repeat in an OMEMO 2 conversation and confirm that the preview is fetched and delivered.
  6. Repeat with the default Others' Only setting to ensure that sender-side preview fetching remains disabled.
  7. Verify behavior on a physical iPhone running build 94.

Evidence and Status

Available evidence references:

  • evidence/run_link_preview_1.out
  • evidence/lp_requests_cb11caf1.jsonl
  • events_main_cb11caf1
  • checks/lp_server.py
  • autotests/metadata-audit/checks/run_link_preview.py

Reported:

  • The sender-side preview feature is enabled with link_previews always.
  • The conversation uses legacy OMEMO 0.3.
  • The outgoing message was sent in run cb11caf1.
  • The reported defect is unnecessary webpage and image fetching without preview delivery.

Not independently established by the supplied excerpt:

  • The exact HTTP request entries and timestamps.
  • The specific image resource requested.
  • The received message's preview metadata.
  • The reproduction rate across repeated runs.
  • End-to-end behavior on a physical iPhone.

Device status: Not Run.

> Moved from another-im/anotherim-swift#22, reported by @asemeniv on 2026-11-04. The evidence archive is attached below. # [libtacky / Link Previews] OMEMO 0.3 fetches link preview resources even though the preview is not sent **Severity:** Minor **Issue ID:** LP-04i **Date:** November 4, 2026 **Device Status:** Not Run — failure expected based on test-environment findings and build 94 source code ## Summary When **Settings → Privacy → Link Previews** is set to **Others' and Mine**, libtacky fetches the linked webpage and its preview image even when the outgoing conversation uses legacy OMEMO 0.3, which does not support transmitting the generated preview. As a result, the destination website receives a request from the sender's device, potentially revealing its IP address and request timestamp, while the recipient receives no link preview. The issue occurs because preview generation begins before the outgoing message's OMEMO profile is determined. The default **Others' Only** setting does not trigger this sender-side behavior. **Affected component:** libtacky, `message.tcl` (outgoing message and preview generation). ## Environment | Item | Details | |---|---| | Application | anotherim-swift `8f62071`, branch `feat/ui-redesign`, build 94 | | libtacky | `2f42a2f2` / v1.2.0-beta2 | | Server | ejabberd 26.09, anotherim-server `b9e675d` | | Sender | `main@example.local`, libtacky application profile | | Recipient | `peer2@example.local`, OMEMO contact | | Encryption | Legacy OMEMO 0.3 (`omemo set_mode legacy`) | | Link Previews | `link_previews always` — Others' and Mine | | Test URL | `https://page.lp.test/p4` | | Test page | `checks/lp_server.py`, network namespace at `1.2.3.4` | | Verification | Level 1 test environment | The test webpage uses a certificate signed by the test environment's CA, configured through `tls_ca_file`. ## Preconditions 1. Set Link Previews to **Others' and Mine**. 2. Establish a conversation using legacy OMEMO 0.3. 3. Make the test webpage accessible to the sender's HTTP client. ## Steps to Reproduce Run: `SWIFT_SRC=<anotherim-swift-build-94> SERVER_SRC=<anotherim-server> bash setup/run_all.sh run_link_preview` The test requires root privileges for `ip netns`. 1. **LP-CTRL:** Fetch `https://page.lp.test/ctrl` through `linkmeta preview` and confirm that the page server records the request. 2. **LP-02:** Send a link using OMEMO 2 and confirm that the recipient receives the preview inside the encrypted envelope. 3. **LP-04:** Switch the conversation to legacy OMEMO: `omemo set_mode peer2 legacy` 4. Send: `old https://page.lp.test/p4 here` 5. Inspect the page server's request log (`lp_requests_<run>.jsonl`). 6. Inspect the message received by `peer2` for link preview metadata. ## Expected Behavior If the selected encryption profile cannot transmit link preview metadata, the sender should skip preview generation entirely. The linked webpage and its associated resources should not be fetched solely for a preview that will be discarded. This follows the privacy considerations in XEP-0511 v0.1.1 §7, which explain that fetching a remote resource can disclose the sender's interest and network address. libtacky also documents in `linkmeta.tcl:34-36` that the legacy encryption profile does not carry additional preview metadata. The application's setting explains that a preview is generated by fetching the page from the device, establishing the intended relationship between the network request and preview functionality. This is a privacy recommendation, not an explicitly documented product requirement. ## Actual Behavior The supplied test report identifies run `cb11caf1` as reproducing the issue. The legacy-OMEMO message was sent at approximately **20:00:36 UTC on November 4, 2026**. Relevant evidence: - `evidence/run_link_preview_1.out` - `evidence/lp_requests_cb11caf1.jsonl` - `events_main_cb11caf1` The outgoing message contained: ```text old https://page.lp.test/p4 here ``` According to the reported behavior, libtacky initiated preview-resource fetching even though the legacy OMEMO profile did not include the generated preview in the outgoing message. The supplied excerpt ends before the individual HTTP request records and received-message evidence. Those records should be attached to establish the exact resources fetched and confirm that the recipient received no preview. ## Root Cause Preview generation is initiated in libtacky's outgoing message processing before the final OMEMO encryption profile is known. The legacy OMEMO profile cannot carry the additional link preview metadata, so the generated preview is omitted from the outgoing message. However, the webpage request has already occurred. This creates an unnecessary privacy disclosure: the sender's device contacts the website without delivering the preview that justified the request. ## Suggested Fix Determine whether the selected outgoing encryption profile supports link preview metadata **before** initiating any preview-related HTTP requests. For legacy OMEMO 0.3: - Skip fetching the webpage and preview image. - Send the original message without preview metadata. - Preserve the existing preview behavior for supported profiles, including OMEMO 2. ## Verification After Fix 1. Enable **Others' and Mine** link previews. 2. Send a URL in an OMEMO 0.3 conversation. 3. Verify that no HTTP requests are made to the linked webpage or its preview resources. 4. Verify that the recipient receives the original message normally. 5. Repeat in an OMEMO 2 conversation and confirm that the preview is fetched and delivered. 6. Repeat with the default **Others' Only** setting to ensure that sender-side preview fetching remains disabled. 7. Verify behavior on a physical iPhone running build 94. ## Evidence and Status **Available evidence references:** - `evidence/run_link_preview_1.out` - `evidence/lp_requests_cb11caf1.jsonl` - `events_main_cb11caf1` - `checks/lp_server.py` - `autotests/metadata-audit/checks/run_link_preview.py` **Reported:** - The sender-side preview feature is enabled with `link_previews always`. - The conversation uses legacy OMEMO 0.3. - The outgoing message was sent in run `cb11caf1`. - The reported defect is unnecessary webpage and image fetching without preview delivery. **Not independently established by the supplied excerpt:** - The exact HTTP request entries and timestamps. - The specific image resource requested. - The received message's preview metadata. - The reproduction rate across repeated runs. - End-to-end behavior on a physical iPhone. **Device status:** Not Run.
Owner

Fixed in libtacky 1.2.0-rc3. The send decides the profile before it fetches: a page is fetched only when the message can carry the preview, that is in clear text or when the recipients get an OMEMO 2 envelope (a mixed chat too, the preview rides its OMEMO 2 part). Under OMEMO 0.3 alone, and while the chat's keys are still being fetched, nothing is fetched and the message goes without a preview. Secret chats (OTR, Telegram) and encrypted Matrix chats never fetched. linkmeta preview is unchanged: it names no chat and is the app's explicit request.

Fixed in libtacky 1.2.0-rc3. The send decides the profile before it fetches: a page is fetched only when the message can carry the preview, that is in clear text or when the recipients get an OMEMO 2 envelope (a mixed chat too, the preview rides its OMEMO 2 part). Under OMEMO 0.3 alone, and while the chat's keys are still being fetched, nothing is fetched and the message goes without a preview. Secret chats (OTR, Telegram) and encrypted Matrix chats never fetched. `linkmeta preview` is unchanged: it names no chat and is the app's explicit request.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
another-im/libtacky#18
No description provided.