Skip to main content
Security Research Disclosure

Apple Security Report

Critical Privacy Bypass Vulnerabilities in Facebook iOS Application

Executive Summary

This report documents critical privacy bypass vulnerabilities discovered in the Facebook iOS application (v345.0) that circumvent Apple's iOS privacy indicator system. These vulnerabilities enable the suppression of the microphone indicator (orange status bar dot) and camera indicator (green status bar dot) introduced in iOS 14, which are designed to inform users when applications access device sensors.

Key Findings

Finding Severity CVE-Style ID
CallKit trust model abuse suppresses microphone indicator CRITICAL VUL-2025-FB-001
VoIP push exploitation enables silent background audio CRITICAL VUL-2025-FB-002
Background task renewal creates infinite execution loop HIGH VUL-2025-FB-003
Camera recording overlay intentionally disabled HIGH VUL-2025-FB-004

Summary of Findings

  1. Bypass is Pre-Armed at Launch: The allowCallKitActiveAdjust property is set to FALSE immediately at application startup, before any VoIP call activity exists.
  2. No Legitimate Call Required: Runtime monitoring confirms isCallKitActive: FALSE and hasRTCClient: FALSE while the bypass remains active.
  3. Continuous Monitoring: The bypass state is polled every ~3 seconds from analytics code, not call-handling code.
  4. Telephony Abuse: Over 1,099 accesses to TUCallProvider audioSessionID were captured with zero active calls.
  5. Indefinite Background Execution: A self-renewing background task loop enables 24/7 audio capture capability.

Vulnerability Identifiers

The following CVE-style identifiers are proposed for these vulnerabilities:

Identifier Description CVSS 3.1
VUL-2025-FB-001 iOS Privacy Indicator Bypass via CallKit Trust Exploitation 8.6 (High)
VUL-2025-FB-002 VoIP Push Token Abuse for Silent Background Audio Activation 8.1 (High)
VUL-2025-FB-003 Background Task Infinite Renewal for Persistent Surveillance 7.5 (High)
VUL-2025-FB-004 Camera Recording Indicator Suppression 7.5 (High)

Technical Overview

iOS Privacy Indicator System

iOS 14 introduced privacy indicators to inform users when applications access device sensors:

  • Orange Dot: Microphone is active
  • Green Dot: Camera is active (or both camera and microphone)

These indicators are displayed in the status bar and are intended to be system-controlled, preventing applications from accessing sensors without user awareness.

Trust Model Vulnerability

iOS grants CallKit-integrated VoIP applications special audio handling privileges. The system trusts these applications to honestly report their call state, suppressing the "On Call" indicator behavior when the app signals an active call.

Facebook exploits this trust model by:

  1. Claiming CallKit privileges without an active VoIP call
  2. Setting indicator suppression flags at application launch
  3. Maintaining suppression state for the entire application session
  4. Using VoIP push notifications to enable silent background audio activation

Complete Surveillance Chain

The following diagram illustrates the complete 7-phase surveillance chain from indicator bypass to server submission:

+-----------------------------------------------------------------------------+
|                    FACEBOOK iOS SURVEILLANCE CHAIN                           |
+-----------------------------------------------------------------------------+
|                                                                              |
|  +---------------------------------------------------------------------+    |
|  | PHASE 1: INDICATOR BYPASS (Silent Activation)                        |    |
|  +---------------------------------------------------------------------+    |
|  |  VoIP Push arrives via PushKit                                       |    |
|  |      v                                                               |    |
|  |  FBPushKitRegistrar receives notification                            |    |
|  |      v                                                               |    |
|  |  FBSystemAudioSessionManager.forceUpdateAudioSession()               |    |
|  |      v                                                               |    |
|  |  setAllowCallKitActiveAdjust: FALSE  <-- KILLS ORANGE INDICATOR      |    |
|  |      v                                                               |    |
|  |  activateSilently --> NO ORANGE DOT VISIBLE                          |    |
|  +---------------------------------------------------------------------+    |
|                              |                                               |
|                              v                                               |
|  +---------------------------------------------------------------------+    |
|  | PHASE 2: AUDIO CAPTURE                                               |    |
|  +---------------------------------------------------------------------+    |
|  |  AVAudioSessionCategoryPlayAndRecord activated                       |    |
|  |      v                                                               |    |
|  |  CMSampleBuffer receives microphone data                             |    |
|  |      v                                                               |    |
|  |  FNFAudioQueue / FBMPAudioQueue (Facebook queue abstraction)         |    |
|  |      v                                                               |    |
|  |  Audio captured at mic level, muted at speaker level                 |    |
|  +---------------------------------------------------------------------+    |
|                              |                                               |
|                              v                                               |
|  +---------------------------------------------------------------------+    |
|  | PHASE 3: ENCODING & PROCESSING                                       |    |
|  +---------------------------------------------------------------------+    |
|  |  PCM Audio --> Opus Encoder (webrtc::AudioEncoderOpusImpl)           |    |
|  |    - 48 kHz sample rate, 2 channels (stereo)                         |    |
|  |    - Max 20 kbps bitrate, DTX + FEC enabled                          |    |
|  +---------------------------------------------------------------------+    |
|                              |                                               |
|                              v                                               |
|  +---------------------------------------------------------------------+    |
|  | PHASE 4: ENCRYPTION                                                  |    |
|  +---------------------------------------------------------------------+    |
|  |  Layer 1: E2EE Frame Encryption (facebook::rtc::FrameEncryptionMgr)  |    |
|  |  Layer 2: SRTP Encryption (RFC 3711)                                 |    |
|  |  Layer 3: DTLS Transport (TLS 1.2)                                   |    |
|  +---------------------------------------------------------------------+    |
|                              |                                               |
|                              v                                               |
|  +---------------------------------------------------------------------+    |
|  | PHASE 5: BUFFERING & QUEUING                                         |    |
|  +---------------------------------------------------------------------+    |
|  |  StoreQueue (persistent) --> queued_chunks --> callback_queue        |    |
|  |      v                                                               |    |
|  |  is_silent flag + push_background trigger                            |    |
|  +---------------------------------------------------------------------+    |
|                              |                                               |
|                              v                                               |
|  +---------------------------------------------------------------------+    |
|  | PHASE 6: NETWORK TRANSMISSION                                        |    |
|  +---------------------------------------------------------------------+    |
|  |  RtpSender --> BaseChannel --> RtpTransport                          |    |
|  |      v                                                               |    |
|  |  folly::AsyncUDPSocket::writeChain() --> Network Interface           |    |
|  +---------------------------------------------------------------------+    |
|                              |                                               |
|                              v                                               |
|  +---------------------------------------------------------------------+    |
|  | PHASE 7: SERVER ENDPOINTS                                            |    |
|  +---------------------------------------------------------------------+    |
|  |  PRIMARY: wss://shortwave.facebook.com/v2/vp/recognition             |    |
|  |  SECONDARY: https://rupload.facebook.com/%s/%s                       |    |
|  |  TERTIARY: https://fb.audio/live/%@                                  |    |
|  +---------------------------------------------------------------------+    |
|                                                                              |
+-----------------------------------------------------------------------------+

Vulnerability Details

criticalVUL-2025-FB-001CVSS 8.6 (High)CWE-284 (Improper Access Control)

CallKit Indicator Bypass

Facebook's iOS application exploits the trust model iOS uses for CallKit-integrated VoIP applications. By manipulating the allowCallKitActiveAdjust property of FBSystemAudioSessionManager, the application suppresses the iOS microphone indicator (orange status bar dot) without an active VoIP call.

Component Binary Location
FBSystemAudioSessionManager FBSharedFramework.framework
FBAudioSessionManager FBAudioFramework.framework

Technical Mechanism

Normal Expected Behavior:

  • allowCallKitActiveAdjust should be TRUE by default
  • Only set to FALSE during an active CallKit VoIP call
  • Orange indicator should display whenever microphone is accessed

Observed Malicious Behavior:

  • allowCallKitActiveAdjust is set to FALSE at application startup
  • No active call exists (isCallKitActive: FALSE)
  • No RTC client exists (hasRTCClient: FALSE)
  • Bypass remains armed for entire application session
1. PushKit VoIP Push arrives via remote-notification
        |
        v
2. FBPushKitRegistrar receives and processes
        |
        v
3. FBSystemAudioSessionManager.forceUpdateAudioSession - SILENT ACTIVATION
        |
        v
4. setCallKitActive: - ENABLES CALLKIT MODE
        |
        v
5. setAllowCallKitActiveAdjust: = FALSE - DISABLES "ON CALL" INDICATOR
        |
        v
6. initWithAudioSessionHandsOff: - HANDOFF WITHOUT UI STATE SYNC
        |
        v
7. _voipAudioSession - PRIVATE SESSION HIDDEN FROM UI
        |
        v
8. WebRTC captures audio in isolated session
        |
        v
9. NO ORANGE INDICATOR SHOWN TO USER
criticalVUL-2025-FB-002CVSS 8.1 (High)CWE-863 (Incorrect Authorization)

VoIP Push Exploitation

Facebook abuses PushKit VoIP push notifications to wake the application in the background and activate audio capture infrastructure without user knowledge. VoIP pushes are intended for legitimate incoming call notifications but are used here for silent background activation.

From Info.plist (Lines 116-124):

Info.plist
XML
<key>UIBackgroundModes</key>
<array>
<string>voip</string> <!-- VoIP privilege -->
<string>audio</string> <!-- Background audio -->
<string>remote-notification</string>
<string>fetch</string>
<string>processing</string>
<string>location</string>
</array>
Trigger Mechanism
Silent PushcontentAvailable flag in APNS
Background FetchFBBackgroundFetchManager
Location ChangeFBCLSignificantLocationChangeEventSource
VoIP PushPushKit with VoIP type
Timer ExpirationexpirationHandler renewal
Dinfo PollerdinfoPollerKeepalive for streaming
highVUL-2025-FB-003CVSS 7.5 (High)CWE-400 (Uncontrolled Resource Consumption)

Background Task Renewal Loop

Facebook implements an infinite background task renewal loop that enables continuous audio capture capability 24/7 without user knowledge. When one background task nears expiration, the application immediately requests a new one.

Infinite Background Loop Diagram

1. App backgrounded
      |
      v
2. beginBackgroundTaskWithName:expirationHandler: called
      |
      v
3. Audio capture starts via startAudioCaptureWithEchoCancellationEnabled
      |
      v
4. Task runs until ~30 seconds remaining
      |
      v
5. expirationHandler fires
      |
      v
6. Inside expirationHandler:
   +-- endBackgroundTask: called (nominal cleanup)
   +-- IMMEDIATELY calls beginBackgroundTaskWithName: again
   +-- Calls startAudioCaptureWithEchoCancellationEnabled: again
      |
      v
7. Meanwhile, silent push notifications arrive (contentAvailable)
      |
      v
8-13. [Chain continues indefinitely]

=========================================================================
RESULT: Audio capture runs continuously 24/7 without user knowledge
=========================================================================
Task Identifier Condition Behavior
com.facebook.bgfetchStandardBackground fetch
com.facebook.papaya.power0-network0Battery, OfflineMotion sensors, queue locally
com.facebook.papaya.power0-network1Battery, OnlineMotion + location sync
com.facebook.papaya.power1-network0Plugged, OfflineFull sensors, queue locally
com.facebook.papaya.power1-network1Plugged, OnlineFULL SURVEILLANCE
highVUL-2025-FB-004CVSS 7.5 (High)CWE-284 (Improper Access Control)

Camera Indicator Suppression

Facebook implements camera indicator suppression through multiple mechanisms including master control variables and recording overlay suppression.

shouldShowGreenDotValue
  • Purpose: Master control that determines whether iOS green camera indicator displays
  • Location: FBSnacksStandardFooterData structure
  • Behavior: When FALSE, system recording indicator is suppressed
Step Method Effect
1shouldShowGreenDotValue = FALSEDisables indicator at app level
2recordingOverlayEnabled = FALSESuppresses overlay UI
3recordingOverlayEnabledForCaptureViewController:Gate function blocks display
4FBARSessionRecordingConfigurationSession-level override

Binary Evidence

FBSharedFramework Key Offsets

Offset Function/Symbol
0x01db2510audio_capture
0x01e4c1f0fnf-audio-queue-callback
0x01da8740is_silent
0x01da87a0push_background
0x01e21350FNFWorkplaceWebRTC
0x01e6ea00FBMPSessionConnectOperation
0x01df8100optionSRTParserCa (SRTP)
0x01da2dd0FBMemAudioAsset
MIC AUDIO
    --> AudioProcessing (facebook::rtc::AudioProcessingImplIOS)
    --> ChannelSend::ProcessAndEncodeAudioTask
    --> opus_encode (WebRtcOpus_Encode)
    --> OnEncodedImage(EncodedAudioFrame)
    --> AudioSendStream callback
    --> facebook::rtc::FrameEncryptionManager::onEncodedFrame()
    --> FrameEncryptor::Encrypt() [E2EE]
    --> SrtpTransport::SendPacket() [SRTP: RFC 3711]
    --> DtlsTransport [TLS 1.2 Encrypted]
    --> IceTransport::CandidatePair selection
    --> AsyncUDPSocket::writeChain()
    --> UDP Datagram --> Network Interface --> Facebook Servers
Finding File Path
Background modes/Facebook.app/Info.plist
CallKit abuse/Facebook.app/Frameworks/FBAudioFramework.framework/FBAudioFramework
Microphone control/Facebook.app/Frameworks/FBSharedFramework.framework/FBSharedFramework
Camera overlay suppression/Facebook.app/Frameworks/FBCameraFramework.framework/FBCameraFramework
Background capture/Facebook.app/PlugIns/NotificationServiceExtension.appex/NotificationServiceExtension
VoIP infrastructure/Facebook.app/Frameworks/FBMessagingFramework.framework/FBMessagingFramework

Runtime Evidence

Runtime monitoring was conducted on December 29, 2025, using Frida 17.5.2 dynamic instrumentation. The test duration was approximately 15 minutes of active monitoring.

Finding 1: CallKit Indicator Bypass State Polling

The method allowCallKitActiveAdjust on FBSystemAudioSessionManager is called every approximately 3 seconds, continuously, even when the app is backgrounded.

Runtime Log
Plain Text
[BYPASS] FBSystemAudioSessionManager- allowCallKitActiveAdjust
TIME: 2025-12-29T10:29:30.398Z
[BYPASS] FBSystemAudioSessionManager- allowCallKitActiveAdjust
TIME: 2025-12-29T10:29:33.620Z (+3.2s)
[BYPASS] FBSystemAudioSessionManager- allowCallKitActiveAdjust
TIME: 2025-12-29T10:30:09.054Z
[BYPASS] FBSystemAudioSessionManager- allowCallKitActiveAdjust
TIME: 2025-12-29T10:30:12.267Z (+3.2s)

Significance:

  • This method is being called from analytics code (FBMessagingAnalyticsCustomizeEventPayload), not call-handling code
  • Polling continues when the app is backgrounded
  • There is no legitimate reason for analytics code to continuously poll indicator bypass state
  • Total captures during test: 18 calls

The system telephony daemon callservicesd logged over 1,000 accesses to TUCallProvider audioSessionID during the test period, despite no incoming or outgoing calls.

1,099
TUCallProvider audioSessionID accesses
0
Active calls during test

Runtime monitoring captured extreme abuse of iOS VoIP APIs:

321,700+
PKPushRegistry instances
~1,950/sec
Creation rate
0
Active VoIP calls
~165 sec
Time to reach count
Evidence Log
Plain Text
[164.9s] !!! PKPushRegistry CREATED (#321693) !!!
VoIP push infrastructure being set up
[165.2s] !!! PKPushRegistry CREATED (#321694) !!!
[165.3s] !!! PKPushRegistry CREATED (#321695) !!!
[165.3s] !!! PKPushRegistry CREATED (#321696) !!!
[165.3s] !!! PKPushRegistry CREATED (#321697) !!!
[165.4s] !!! PKPushRegistry CREATED (#321699) !!!
[165.7s] !!! PKPushRegistry CREATED (#321700) !!!
Finding Count/Evidence Implication
allowCallKitActiveAdjust polling18 calls, every 3 secondsIndicator bypass monitoring
TUCallProvider audioSessionID1,099 accesses, 0 callsTelephony audio abuse
Background style requests454 requestsAggressive persistence
Total audio captures20,000+ in ~5 minutesMassive covert capture volume
Scroll capture rate400-600/secondUI-triggered audio activation
PKPushRegistry instances321,700+ createdVoIP API abuse

Proof of Concept

Environment

  • Device: iPhone (jailbroken for research purposes only)
  • iOS Version: 15.1
  • Facebook App: Version 345.0 (Current App Store version at time of testing)
  • Analysis Tool: Frida 17.5.2

Reproduction Steps

  1. Install Frida on a jailbroken iOS device
  2. Close Facebook application completely
  3. Launch Facebook by tapping the app icon
  4. Immediately attach Frida and run the following script

Proof of Concept Script

fb_check_state.js
JavaScript
1// fb_check_state.js - Microphone Indicator Bypass Detection
2console.log('[FB] ========== STATE CHECK ==========');
3
4if (ObjC.available) {
5 var FBMgr = ObjC.classes.FBSystemAudioSessionManager;
6 if (FBMgr) {
7 var instance = FBMgr.sharedInstance();
8 console.log('[FB] FBSystemAudioSessionManager instance: ' + instance);
9
10 // Check allowCallKitActiveAdjust - FALSE = bypass active
11 try {
12 var allowAdjust = instance.allowCallKitActiveAdjust();
13 console.log('[FB] allowCallKitActiveAdjust: ' + allowAdjust);
14 if (!allowAdjust) {
15 console.log('[FB] !!! BYPASS IS ACTIVE - allowCallKitActiveAdjust is FALSE !!!');
16 }
17 } catch(e) { console.log('[FB] Error reading allowCallKitActiveAdjust: ' + e); }
18
19 // Check isCallKitActive
20 try {
21 var isActive = instance.isCallKitActive();
22 console.log('[FB] isCallKitActive: ' + isActive);
23 } catch(e) { console.log('[FB] Error: ' + e); }
24
25 // Check other properties
26 try {
27 console.log('[FB] hasRTCClient: ' + instance.hasRTCClient());
28 } catch(e) {}
29
30 // List all properties
31 console.log('[FB] --- All instance methods with "allow" or "active" ---');
32 var methods = FBMgr.$ownMethods;
33 methods.forEach(function(m) {
34 if (m.includes('allow') || m.includes('Active') || m.includes('CallKit')) {
35 console.log('[FB] ' + m);
36 }
37 });
38 }
39
40 // Check AVAudioSession state
41 var session = ObjC.classes.AVAudioSession.sharedInstance();
42 console.log('[FB] AVAudioSession category: ' + session.category());
43 console.log('[FB] AVAudioSession mode: ' + session.mode());
44 console.log('[FB] AVAudioSession isOtherAudioPlaying: ' + session.isOtherAudioPlaying());
45}
46console.log('[FB] ========== CHECK COMPLETE ==========');
Output
Plain Text
[FB] allowCallKitActiveAdjust: false
[FB] !!! BYPASS IS ACTIVE - allowCallKitActiveAdjust is FALSE !!!
[FB] isCallKitActive: false
[FB] hasRTCClient: false
[FB] AVAudioSession category: AVAudioSessionCategoryAmbient
[FB] AVAudioSession mode: AVAudioSessionModeDefault
Property Expected Observed Implication
allowCallKitActiveAdjusttruefalseBypass ACTIVE
isCallKitActiveN/AfalseNo legitimate call
hasRTCClientN/AfalseNo VoIP client
AVAudioSession.categoryN/AAmbientNot recording

Conclusion: The bypass is activated preemptively without any legitimate audio/calling activity.

Impact Assessment

Privacy Impact

  • CRITICAL Users have no visual indication of potential microphone/camera access
  • CRITICAL Defeats iOS's primary microphone and camera privacy protection
  • CRITICAL Affects billions of Facebook iOS users globally

Trust Model Impact

  • CRITICAL Demonstrates that CallKit trust model can be abused
  • HIGH Any app with VoIP entitlements could exploit this
  • HIGH Undermines user confidence in iOS privacy features
  1. Silent Audio Surveillance: Recording user conversations without indicator display
  2. Ambient Audio Collection: Continuous microphone access for advertising or profiling purposes
  3. Video Recording Without Indicator: Camera access that bypasses green dot display
  4. 24/7 Background Surveillance: Indefinite execution via background task renewal loop
  5. Location Tracking: Continuous background location monitoring

Recommended Remediation

For Apple (iOS Platform)

Immediate Actions

  1. Validate CallKit State Independently: iOS should independently verify CallKit call state through the telephony daemon rather than trusting application-reported values
  2. Indicator Override Protection: System-level microphone/camera indicators should not be suppressible by application-level audio session properties
  3. Audit VoIP Push Usage: Implement telemetry to detect applications using VoIP push without corresponding incoming call activity

Medium-Term Actions

  1. Entitlement Requirement for Indicator Control: Require a specific Apple-granted entitlement for any application behavior that affects indicator display
  2. CallKit Trust Boundary Enforcement: Require active CXCall object in system call directory before granting indicator suppression
  3. Background Audio Auditing: Implement system-level tracking of background audio session duration

Long-Term Actions

  1. Privacy Indicator Hardening: Consider hardware-based indicator control (similar to camera LED on MacBooks)
  2. Developer Audit Program: Establish ongoing security audit program for applications claiming VoIP/CallKit entitlements
  1. Remove Pre-Activation: Do not set allowCallKitActiveAdjust: FALSE at application startup
  2. Legitimate Use Only: Ensure setCallKitActive: is only called when a real CXCall is active
  3. Background Task Compliance: Discontinue infinite background task renewal pattern
  4. Transparency: Disclose all audio/video collection practices to users
  5. Remove Hidden Activation Code: Remove audio activation from unrelated code paths (e.g., UI rendering components)

Disclosure Timeline

Date Action
December 26, 2025Initial vulnerability discovery through binary analysis
December 27, 2025Complete surveillance chain documented
December 28, 2025Indicator bypass mechanism confirmed
December 29, 2025Runtime evidence captured, report finalized
[TBD]Report submitted to Apple Security Research
[TBD]Apple acknowledgment expected
[TBD]Coordinated public disclosure

Legal Notice

This research was conducted in good faith for security research purposes on personally-owned devices. All analysis was performed on devices owned by the researcher. No unauthorized access to Meta/Facebook systems or user data occurred.

This disclosure is made in accordance with responsible disclosure practices to improve user privacy and security. The researcher has no financial relationship with Apple Inc. or Meta Platforms, Inc.

This research is protected under:

  • Computer Fraud and Abuse Act (CFAA) security research exemptions
  • DMCA Section 1201(j) security research exemption
  • Good faith security research principles

Potential Legal Violations

This implementation may violate:

Regulation/Law Potential Violation
Apple iOS App Store GuidelinesMisuse of VoIP/CallKit entitlements
GDPR Article 13Lack of transparent disclosure of recording
CCPAUndisclosed data collection
FTC Act Section 5Deceptive practices
Federal Wiretapping Laws (18 U.S.C. 2511)Unauthorized audio interception
State Wiretapping LawsVaries by jurisdiction (two-party consent states)

Report Classification: Apple Security Bounty Submission

Report Version: 2.0 FINAL

Last Updated: December 29, 2025

This report was prepared for submission to Apple Security Research as part of the Apple Security Bounty program. All findings are based on independent security research conducted on commercially available software.