[libtacky / Calls] Disabled “Calls from Unknown” still leaks presence via <ringing/> #12
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?
[libtacky / Calls] Disabled “Calls from Unknown” still leaks presence via
Severity: Middle
Issue ID: CL-01r · QA cases: SEC-126, CONF-006
Date: November 3, 2026
Summary
When “Calls from Unknown” is disabled, an unknown caller can still receive a Jingle Message Initiation (JMI) response before the call is rejected.
This reveals that the target device is currently online and exposes its full JID, including the resource. The behavior can be repeated.
No IP address, ICE candidates, media, or Jingle session details were disclosed, and the call was not displayed to the user.
The issue affects:
libtacky: tacky/xmpp/modules/calls.tcl
iOS application: AnotherIM/Calls/CallsModel.swift
Environment
Item Details
Application anotherim-swift
c5fdeae, branch feat/ui-redesign, build 93libtacky 2f42a2f2 / v1.2.0-beta2
Server ejabberd 26.09 with configuration from anotherim-server b9e675d
Target main@example.local, libtacky application profile
Caller stranger@example.local, not in the target's roster
Test environment Level 1 cloud-based environment
Note: The issue was reproduced in the test environment but has not yet been reproduced on a physical device running TestFlight build 93.
Preconditions
“Calls from Unknown” is disabled:
AppPrivacySettings.callsFromUnknown = false
messages_from_strangers 1 is enabled.
The caller is not in the target's roster.
In the test environment, the agent immediately rejects every incoming call after receiving calls , matching CallsModel.swift:594-600.
Steps to Reproduce
Run:
bash setup/run_all.sh calls
Or:
python3 checks/run_calls.py
An unknown caller sends an audio JMI (XEP-0353) to the target's bare JID.
The target receives calls and immediately rejects the call with decline.
Inspect rig/stanzas_full.log.
Expected Behavior
With “Calls from Unknown” disabled, an unknown caller should not receive a response that reveals whether the target device is online.
A silent drop would be consistent with the existing behavior when messages_from_strangers 0, where the proposal is dropped without a response (CL-02 PASS).
This is a security recommendation, not an explicitly defined product requirement. However, XEP-0353 notes that exchanging messages with another entity can effectively leak presence information, and is intended for a device that has started ringing.
Actual Behavior
Run b3f825a1 shows:
Lines 128–129: the proposal is delivered to main@example.local/another.im (iOS).cA6y9cKn7V.
Lines 130–131: the target sends:
The from attribute exposes the target's full JID:
main@example.local/another.im (iOS).cA6y9cKn7V
Lines 132–133: the call is subsequently rejected with .
Agent events confirm the sequence:
call → call -outcome declined → callreject done
No Jingle session, ICE candidates, or IP addresses were sent.
Reproduction rate: 2/2 (b3f825a1 and 6b6e900b).
Evidence:
evidence/stanzas_str_b3f825a1.txt
evidence/events_b3f825a1.txt
evidence/stanzas_str_6b6e900b.txt
Root Cause
In tacky/xmpp/modules/calls.tcl:2253-2256, HandleJmiPropose sends :
SendJmi $from $sid [BuildJmiMessage $from ringing $sid 0]
Only afterwards does libtacky notify the application via emit calls .
The application's “Calls from Unknown” check occurs later in AnotherIM/Calls/CallsModel.swift:594-600, when it receives the incoming-call event. By that point, has already been sent.
The existing stranger-handling logic in calls.tcl:2154-2179 is controlled by messages_from_strangers; libtacky has no equivalent call-specific privacy setting.
Relevant source excerpts:
evidence/calls.tcl_2140-2257.txt
evidence/CallsModel.swift_575-605.txt
Suggested Fix
Either:
Pass a call-specific stranger policy to libtacky (for example, calls_from_strangers 0) and silently drop unknown proposals before sending ; or
Defer sending until after the application has evaluated the caller and accepted the incoming call.
The implementation choice is left to the development team.
Verification After Fix
With “Calls from Unknown” disabled:
an unknown caller should not trigger a visible incoming call;
the caller should not receive ;
the response should not expose the target's full JID.
Test from an account outside the target's roster and inspect the caller's XML console.
Evidence and Status
Test report:
autotests/metadata-audit/results/2026-11-03_calls_auth_contacts.md, section 2.
Complete evidence archive:
_claude_tmp/evidence_calls_auth_contacts_2026-11-03.tgz
Verified: stanza behavior and agent events from two runs; relevant source code in libtacky 2f42a2f2 and anotherim-swift
c5fdeae.Not verified: behavior on a physical iPhone; video-call behavior; behavior when the application is not running.
Moved to another-im/libtacky#15: the fix belongs to libtacky. The evidence archive went with it.