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
- Bypass is Pre-Armed at Launch: The
allowCallKitActiveAdjustproperty is set toFALSEimmediately at application startup, before any VoIP call activity exists. - No Legitimate Call Required: Runtime monitoring confirms
isCallKitActive: FALSEandhasRTCClient: FALSEwhile the bypass remains active. - Continuous Monitoring: The bypass state is polled every ~3 seconds from analytics code, not call-handling code.
- Telephony Abuse: Over 1,099 accesses to
TUCallProvider audioSessionIDwere captured with zero active calls. - 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:
- Claiming CallKit privileges without an active VoIP call
- Setting indicator suppression flags at application launch
- Maintaining suppression state for the entire application session
- 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
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.
Affected Components
Affected Components
| Component | Binary Location |
|---|---|
| FBSystemAudioSessionManager | FBSharedFramework.framework |
| FBAudioSessionManager | FBAudioFramework.framework |
Technical Mechanism
Technical Mechanism
Normal Expected Behavior:
allowCallKitActiveAdjustshould beTRUEby default- Only set to
FALSEduring an active CallKit VoIP call - Orange indicator should display whenever microphone is accessed
Observed Malicious Behavior:
allowCallKitActiveAdjustis set toFALSEat application startup- No active call exists (
isCallKitActive: FALSE) - No RTC client exists (
hasRTCClient: FALSE) - Bypass remains armed for entire application session
VoIP Entitlement Abuse Chain
VoIP Entitlement Abuse Chain
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 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.
Background Mode Exploitation
Background Mode Exploitation
From Info.plist (Lines 116-124):
<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>Wake-Up Triggers
Wake-Up Triggers
| Trigger | Mechanism |
|---|---|
| Silent Push | contentAvailable flag in APNS |
| Background Fetch | FBBackgroundFetchManager |
| Location Change | FBCLSignificantLocationChangeEventSource |
| VoIP Push | PushKit with VoIP type |
| Timer Expiration | expirationHandler renewal |
| Dinfo Poller | dinfoPollerKeepalive for streaming |
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
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
========================================================================= Papaya Background Task Matrix
Papaya Background Task Matrix
| Task Identifier | Condition | Behavior |
|---|---|---|
| com.facebook.bgfetch | Standard | Background fetch |
| com.facebook.papaya.power0-network0 | Battery, Offline | Motion sensors, queue locally |
| com.facebook.papaya.power0-network1 | Battery, Online | Motion + location sync |
| com.facebook.papaya.power1-network0 | Plugged, Offline | Full sensors, queue locally |
| com.facebook.papaya.power1-network1 | Plugged, Online | FULL SURVEILLANCE |
Camera Indicator Suppression
Facebook implements camera indicator suppression through multiple mechanisms including master control variables and recording overlay suppression.
Master Control Variable
Master Control Variable
shouldShowGreenDotValue - Purpose: Master control that determines whether iOS green camera indicator displays
- Location:
FBSnacksStandardFooterDatastructure - Behavior: When
FALSE, system recording indicator is suppressed
Recording Overlay Suppression Chain
Recording Overlay Suppression Chain
| Step | Method | Effect |
|---|---|---|
| 1 | shouldShowGreenDotValue = FALSE | Disables indicator at app level |
| 2 | recordingOverlayEnabled = FALSE | Suppresses overlay UI |
| 3 | recordingOverlayEnabledForCaptureViewController: | Gate function blocks display |
| 4 | FBARSessionRecordingConfiguration | Session-level override |
Binary Evidence
FBSharedFramework Key Offsets
FBSharedFramework Key Offsets
| Offset | Function/Symbol |
|---|---|
| 0x01db2510 | audio_capture |
| 0x01e4c1f0 | fnf-audio-queue-callback |
| 0x01da8740 | is_silent |
| 0x01da87a0 | push_background |
| 0x01e21350 | FNFWorkplaceWebRTC |
| 0x01e6ea00 | FBMPSessionConnectOperation |
| 0x01df8100 | optionSRTParserCa (SRTP) |
| 0x01da2dd0 | FBMemAudioAsset |
Audio Send Path
Audio Send Path
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 Evidence File Locations
Evidence File Locations
| 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
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.
[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
Finding 2: Telephony Audio Session Access
Finding 2: Telephony Audio Session Access
The system telephony daemon callservicesd logged over 1,000 accesses to TUCallProvider audioSessionID during the test period, despite no incoming or outgoing calls.
PKPushRegistry VoIP Infrastructure Abuse
PKPushRegistry VoIP Infrastructure Abuse
Runtime monitoring captured extreme abuse of iOS VoIP APIs:
[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) !!!Runtime Evidence Summary
Runtime Evidence Summary
| Finding | Count/Evidence | Implication |
|---|---|---|
| allowCallKitActiveAdjust polling | 18 calls, every 3 seconds | Indicator bypass monitoring |
| TUCallProvider audioSessionID | 1,099 accesses, 0 calls | Telephony audio abuse |
| Background style requests | 454 requests | Aggressive persistence |
| Total audio captures | 20,000+ in ~5 minutes | Massive covert capture volume |
| Scroll capture rate | 400-600/second | UI-triggered audio activation |
| PKPushRegistry instances | 321,700+ created | VoIP 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
- Install Frida on a jailbroken iOS device
- Close Facebook application completely
- Launch Facebook by tapping the app icon
- Immediately attach Frida and run the following script
Proof of Concept Script
Proof of Concept Script
1// fb_check_state.js - Microphone Indicator Bypass Detection2console.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 active11 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 isCallKitActive20 try {21 var isActive = instance.isCallKitActive();22 console.log('[FB] isCallKitActive: ' + isActive);23 } catch(e) { console.log('[FB] Error: ' + e); }24 25 // Check other properties26 try {27 console.log('[FB] hasRTCClient: ' + instance.hasRTCClient());28 } catch(e) {}29 30 // List all properties31 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 state41 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 ==========');Observed Output (Reproduced Consistently)
Observed Output (Reproduced Consistently)
[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 |
|---|---|---|---|
| allowCallKitActiveAdjust | true | false | Bypass ACTIVE |
| isCallKitActive | N/A | false | No legitimate call |
| hasRTCClient | N/A | false | No VoIP client |
| AVAudioSession.category | N/A | Ambient | Not 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
Potential Abuse Scenarios
Potential Abuse Scenarios
- Silent Audio Surveillance: Recording user conversations without indicator display
- Ambient Audio Collection: Continuous microphone access for advertising or profiling purposes
- Video Recording Without Indicator: Camera access that bypasses green dot display
- 24/7 Background Surveillance: Indefinite execution via background task renewal loop
- Location Tracking: Continuous background location monitoring
Recommended Remediation
For Apple (iOS Platform)
For Apple (iOS Platform)
Immediate Actions
- Validate CallKit State Independently: iOS should independently verify CallKit call state through the telephony daemon rather than trusting application-reported values
- Indicator Override Protection: System-level microphone/camera indicators should not be suppressible by application-level audio session properties
- Audit VoIP Push Usage: Implement telemetry to detect applications using VoIP push without corresponding incoming call activity
Medium-Term Actions
- Entitlement Requirement for Indicator Control: Require a specific Apple-granted entitlement for any application behavior that affects indicator display
- CallKit Trust Boundary Enforcement: Require active CXCall object in system call directory before granting indicator suppression
- Background Audio Auditing: Implement system-level tracking of background audio session duration
Long-Term Actions
- Privacy Indicator Hardening: Consider hardware-based indicator control (similar to camera LED on MacBooks)
- Developer Audit Program: Establish ongoing security audit program for applications claiming VoIP/CallKit entitlements
For Facebook/Meta
For Facebook/Meta
- Remove Pre-Activation: Do not set
allowCallKitActiveAdjust: FALSEat application startup - Legitimate Use Only: Ensure
setCallKitActive:is only called when a real CXCall is active - Background Task Compliance: Discontinue infinite background task renewal pattern
- Transparency: Disclose all audio/video collection practices to users
- Remove Hidden Activation Code: Remove audio activation from unrelated code paths (e.g., UI rendering components)
Disclosure Timeline
| Date | Action |
|---|---|
| December 26, 2025 | Initial vulnerability discovery through binary analysis |
| December 27, 2025 | Complete surveillance chain documented |
| December 28, 2025 | Indicator bypass mechanism confirmed |
| December 29, 2025 | Runtime 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 Guidelines | Misuse of VoIP/CallKit entitlements |
| GDPR Article 13 | Lack of transparent disclosure of recording |
| CCPA | Undisclosed data collection |
| FTC Act Section 5 | Deceptive practices |
| Federal Wiretapping Laws (18 U.S.C. 2511) | Unauthorized audio interception |
| State Wiretapping Laws | Varies by jurisdiction (two-party consent states) |