[iOS / libtacky / Jingle] Incoming P2P file offers are auto-accepted and expose the device IP address without user interaction #17
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
[iOS / libtacky / Jingle] Incoming P2P file offers are auto-accepted and expose the device IP address without user interaction
Severity: Major
Issue ID: P2P-06, P2P-07
Date: October 26, 2026 · Updated November 4, 2026
Summary
AnotherIM does not use direct peer-to-peer file transfers in its iOS attachment workflow, but leaves libtacky's P2P file transfer functionality enabled with default settings.
As a result, incoming Jingle File Transfer (XEP-0234) offers from contacts can be automatically accepted without user interaction. The client's
session-acceptresponse includes a direct connection candidate containing the device's network IP address.This allows a contact, or someone controlling their account, to obtain the recipient's network address simply by initiating a file transfer.
Depending on the network, the disclosed address may be private or publicly routable.
Testing confirmed that:
session-acceptresponse.file_transfer_p2premoves the direct IP candidate in the tested SOCKS5 configuration.Affected components:
AnotherIM/AppEnvironment.swifttacky/xmpp/modules/jinglefile.tcl,s5b.tcl,file.tclThe issue was reproduced in the libtacky application profile and confirmed against the build 93 source code. Physical-device behavior remains unverified.
Environment
c5fdeae, branchfeat/ui-redesign, build 932f42a2f2/ v1.2.0-beta2mod_proxy65, anotherim-serverb9e675dmain@example.local, libtacky application profilepeer2(OMEMO/JET),observer(without OMEMO)192.0.2.2(test environment)The test environment uses SOCKS5 without WebRTC data channels (
MEDIA_BACKEND=none).Preconditions
Start the test environment:
PUSH_WINDOW=0 GRACE_PERIOD=0 CLEAN=1 BIND_IP=0.0.0.0 bash setup/up.shBuild libtacky from the application submodule.
Configure
mainandpeer2as mutual OMEMO contacts.Configure
mainandobserveras mutual contacts, with OMEMO unavailable forobserver.Leave
file_transfer_p2pandattachment_autofetchunset, matching the iOS application configuration.Steps to Reproduce
Run:
cd checks && python3 run_p2p.pyP2P-06 — OMEMO/JET transfer
peer2initiate a 3,000-byte direct file transfer tomainusing Jingle and SOCKS5 with JET (XEP-0391).session-acceptstanza and file transfer events.P2P-07 — Contact without OMEMO
mainexchange an unencrypted message withobserver, which does not support OMEMO.observerinitiate a 2,048-byte unencrypted SOCKS5 file transfer.session-acceptstanza.Expected Behavior
Incoming direct file offers should not expose the recipient's network IP address without user interaction.
Since AnotherIM does not expose P2P file transfer functionality in its UI, it should either:
This is a privacy/security recommendation, not an explicitly documented product requirement.
Actual Behavior
P2P-06 — OMEMO/JET
Run
00e86829(evidence/stanzas_p2p_00e86829.log) showed thatmainresponded to the incoming offer withsession-acceptin the same second.The response contained:
192.0.2.2was the recipient's network address in the test environment.The transfer events showed:
activeimmediately after acceptance.doneapproximately 268 ms later.offeredstate requiring user confirmation.The file was downloaded automatically.
P2P-07 — Unencrypted transfer
In the same run:
mainsent an unencrypted message toobserver.observerinitiated a SOCKS5 file transfer.mainautomatically responded withsession-accept.host='192.0.2.2'withtype='direct'.No user interaction occurred.
Control tests:
file_transfer_p2p 0, the response contained only the proxy candidate (P2P-05).The XMPP server can also observe the disclosed address because Jingle signaling is transmitted through ordinary XMPP stanzas.
Reproduction Rate
8/8 successful automated runs:
3ae8f93e,ac7b9bfa,006606da,7179ab9cb1cef65b,ce8a5e8800e86829,63b8406dBoth November 3 runs confirmed automatic acceptance and direct IP disclosure using libtacky v1.2.0-beta2.
Root Cause
libtacky automatically accepts incoming Jingle file offers from eligible contacts.
jinglefile.tcl:1058-1059callsAcceptwhen the sender passesAutofetchAllowed, the file is within the size limit, andMayAutoAcceptpermits acceptance.file.tcl:158-159, 672-687defaults to autofetching from contacts with a maximum file size of 5 MB.jinglefile.tcl:1075-1083allows automatic acceptance for:jinglefile.tcl:2928includes a direct network candidate unlessfile_transfer_p2pis explicitly set to"0".s5b.tcl:240obtains local addresses from the network connection.iOS integration:
AppEnvironment.swift:396-402does not configurefile_transfer_p2porattachment_autofetch.TackyWire.File.acceptAPI is not called by the application outside generated code.AttachmentService.swift:507andmessage send_file -url.Consequently, unused P2P functionality remains enabled in libtacky and can disclose the recipient's address.
Suggested Fix
Disable direct P2P candidates in the iOS libtacky configuration:
file_transfer_p2p = "0"The P2P-05 control test confirmed that this removes the recipient's direct IP candidate from the SOCKS5 response, leaving only the server proxy.
Disable automatic acceptance of incoming direct file transfers, either through a suitable
attachment_autofetchconfiguration or a dedicated libtacky setting.Verify that changing autofetch behavior does not interfere with the application's normal HTTP attachment downloads.
Review WebRTC/ICE handling separately. The
file_transfer_p2psetting may not prevent IP disclosure through ICE candidates when data channels are available.Disabling direct candidates alone does not prevent automatic file acceptance.
Verification After Fix
session-acceptresponses for direct SOCKS5 and ICEhost/srflxcandidates.Evidence and Status
Evidence directory:
2026-10-26_P2P_ip_autoaccept/evidence/November 3 evidence:
stanzas_p2p_00e86829.logstanzas_p2p_63b8406d.logstanzas_jingle_00e86829.txtstanzas_jingle_63b8406d.txtevents_main_00e86829events_main_63b8406dp2p_00e86829.jsonp2p_63b8406d.jsonAutomated test:
autotests/metadata-audit/checks/run_p2p.pyTest report:
autotests/metadata-audit/results/2026-11-03.mdComplete evidence archive:
_claude_tmp/evidence_ma_2026-11-03.tgzVerified:
file_transfer_p2p 0.Not verified:
4832765: file_transfer_p2p = 0 and attachment_autofetch_max = 0. libtacky no longer accepts incoming direct offers by itself and offers no direct candidate. The app's HTTP downloads are unaffected. WebRTC/ICE for files was not reviewed.