Safari 17.6 (17618.3.11.11.7, 17618) Crashes on Attempt to Run Extension in Developer Mode

Hi,

I'm trying to test out an extension I'm building in Xcode and every time I try to test it, Safari crashes immediately. On later versions of Mac OS, e.g. Sequoia, there's no problem.

I'm building this extension as part of a Mac Catalyst app that is a hybrid iPad/Mac OS app. On Safari 26.3 (20623.2.7.18.1) I can just add the source tree as a temporary extension and it works fine. But the .appex file for the same thing is causing the older Safari 17.6 (17618.3.11.11.7, 17618) to throw a fit.

Trying to get through this with LLMs has focused on whether the extension target is for iOS and Mac OS or just Mac OS alone, and futzing with UIDeviceFamily the Build Settings. But basically it just doesn't work no matter what I do, and Safari shouldn't crash.

Here's the .appex's Info.plist after compilation:

% defaults read /Users/[username]/Library/Developer/Xcode/DerivedData/PlainSite-[gibberish]/Build/Products/Debug-maccatalyst/PlainSite.app/Contents/PlugIns/PlainSiteRecycler.appex/Contents/Info.plist { BuildMachineOSBuild = 21H1320; CFBundleIdentifier = "com.thinkcomputer.[product].[extension]"; CFBundleShortVersionString = "1.0"; CFBundleSupportedPlatforms = ( MacOSX ); CFBundleVersion = 2; DTCompiler = "com.apple.compilers.llvm.clang.1_0"; DTPlatformBuild = 14C18; DTPlatformName = macosx; DTPlatformVersion = "13.1"; DTSDKBuild = 22C55; DTSDKName = "macosx13.1"; DTXcode = 1420; DTXcodeBuild = 14C18; LSMinimumSystemVersion = "12.0"; NSExtension = { NSExtensionAttributes = { SafariWebExtensionPath = src; }; NSExtensionPointIdentifier = "com.apple.Safari.web-extension"; NSExtensionPrincipalClass = "PlainSiteRecycler.SafariWebExtensionHandler"; }; UIDeviceFamily = ( 2, 6 ); }

Crash log:

Hardware Model: MacBookPro12,1 Process: Safari [44241] Path: /Applications/Safari.app/Contents/MacOS/Safari Identifier: com.apple.Safari Version: 17.6 (17618.3.11.11.7) Code Type: X86-64 (Native) Role: Background Parent Process: launchd [1] Coalition: com.apple.Safari [1098]

Date/Time: 2026-06-12 13:29:10.8546 -0700 Launch Time: 2026-06-12 13:27:27.7047 -0700 OS Version: macOS 12.7.6 (21H1320) Release Type: User Report Version: 104

Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Subtype: KERN_PROTECTION_FAILURE at 0x00007ff7b77d1ff8 Exception Codes: 0x0000000000000002, 0x00007ff7b77d1ff8 VM Region Info: 0x7ff7b77d1ff8 is in 0x7ff7b3fd2000-0x7ff7b77d2000; bytes after start: 58720248 bytes before end: 7 REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL MALLOC_SMALL 7fa313000000-7fa313800000 [ 8192K] rw-/rwx SM=PRV
GAP OF 0x54a07d2000 BYTES ---> STACK GUARD 7ff7b3fd2000-7ff7b77d2000 [ 56.0M] ---/rwx SM=NUL ... for thread 0 Stack 7ff7b77d2000-7ff7b7fd2000 [ 8192K] rw-/rwx SM=PRV thread 0 Exception Note: EXC_CORPSE_NOTIFY Termination Reason: SIGNAL 11 Segmentation fault: 11 Terminating Process: exc handler [44241]

Highlighted by Thread: 0

Backtrace not available

No thread state (register information) available

Binary Images: 0x0 - 0xffffffffffffffff ??? (*) <00000000-0000-0000-0000-000000000000> ???

Error Formulating Crash Report: dyld_process_info_create failed with 5 Failed to create CSSymbolicatorRef - corpse still valid ¯_(ツ)/¯ thread_get_state(PAGEIN) returned 0x10000003: (ipc/send) invalid destination port thread_get_state(EXCEPTION) returned 0x10000003: (ipc/send) invalid destination port thread_get_state(FLAVOR) returned 0x10000003: (ipc/send) invalid destination port

EOF


Full Report

{"app_name":"Safari","timestamp":"2026-06-12 13:29:12.00 -0700","app_version":"17.6","slice_uuid":"af2262af-647d-3262-adc8-e52c3ef7579e","build_version":"17618.3.11.11.7","platform":0,"bundleID":"com.apple.Safari","share_with_app_devs":0,"is_first_party":0,"bug_type":"309","os_version":"macOS 12.7.6 (21H1320)","incident_id":"8F871759-8566-49DE-A6F9-EE73128BB836","name":"Safari"} { "uptime" : 100000, "procLaunch" : "2026-06-12 13:27:27.7047 -0700", "procRole" : "Background", "version" : 2, "userID" : 503, "deployVersion" : 210, "modelCode" : "MacBookPro12,1", "procStartAbsTime" : 102649791496150, "coalitionID" : 1098, "osVersion" : { "train" : "macOS 12.7.6", "build" : "21H1320", "releaseType" : "User" }, "captureTime" : "2026-06-12 13:29:10.8546 -0700", "incident" : "8F871759-8566-49DE-A6F9-EE73128BB836", "bug_type" : "309", "pid" : 44241, "procExitAbsTime" : 102752878214260, "cpuType" : "X86-64", "procName" : "Safari", "procPath" : "&#x2F;Applications&#x2F;Safari.app&#x2F;Contents&#x2F;MacOS&#x2F;Safari", "bundleInfo" : {"CFBundleShortVersionString":"17.6","CFBundleVersion":"17618.3.11.11.7","CFBundleIdentifier":"com.apple.Safari"}, "buildInfo" : {"ProjectName":"Safari","SourceVersion":"7618003011011007","ProductBuildVersion":"618G22","BuildVersion":"12"}, "storeInfo" : {"deviceIdentifierForVendor":"28124F28-A4EB-556C-A50C-D710162ABDA6","thirdParty":true}, "parentProc" : "launchd", "parentPid" : 1, "coalitionName" : "com.apple.Safari", "crashReporterKey" : "134BE33B-9612-8725-73E0-95998174507F", "wakeTime" : 67008, "sleepWakeUUID" : "F942DC6A-04DF-4EE2-AA9F-DB3EDCB24AC3", "sip" : "enabled", "isCorpse" : 1, "exception" : {"codes":"0x0000000000000002, 0x00007ff7b77d1ff8","rawCodes":[2,140701912080376],"type":"EXC_BAD_ACCESS","signal":"SIGSEGV","subtype":"KERN_PROTECTION_FAILURE at 0x00007ff7b77d1ff8"}, "termination" : {"flags":0,"code":11,"namespace":"SIGNAL","indicator":"Segmentation fault: 11","byProc":"exc handler","byPid":44241}, "usedImages" : [ { "size" : 0, "source" : "A", "base" : 0, "uuid" : "00000000-0000-0000-0000-000000000000" } ], "sharedCache" : { "base" : 140703277129728, "size" : 19331678208, "uuid" : "246818c3-4b9f-3462-bcaf-fdf71975e5fe" }, "legacyInfo" : { "threadHighlighted" : 0 }, "trialInfo" : { "rollouts" : [ { "rolloutId" : "61301e3a61217b3110231469", "factorPackIds" : { "SIRI_FIND_MY_CONFIGURATION_FILES" : "652886aa2c02f032beae8316" }, "deploymentId" : 240000028 }, { "rolloutId" : "5ffde50ce2aacd000d47a95f", "factorPackIds" : {

  },
  "deploymentId" : 240000550
}

], "experiments" : [

] }, "reportNotes" : [ "dyld_process_info_create failed with 5", "Failed to create CSSymbolicatorRef - corpse still valid ¯\(ツ)_&#x2F;¯", "thread_get_state(PAGEIN) returned 0x10000003: (ipc&#x2F;send) invalid destination port", "thread_get_state(EXCEPTION) returned 0x10000003: (ipc&#x2F;send) invalid destination port", "thread_get_state(FLAVOR) returned 0x10000003: (ipc&#x2F;send) invalid destination port" ] }

Any help would be greatly appreciated!

Replying to my own post here...

Claude says:

Let me symbolicate the recursion frames. First I need to locate the SafariSharedUI and Safari binaries on disk (they're in the dyld shared cache), then run atos against them with the load addresses from the report.

Ran

Locate Safari framework binaries and atos Both staged framework binaries are on disk and atos is available. Let me symbolicate the 17-frame recursion cycle.

Ran

Symbolicate the recursion-cycle frames with atos

Got it — and the symbolication is the payoff. Here's the exact recursion cycle Safari is stuck in (one iteration, which repeats ~30× until the stack is exhausted):

 -[ExtensionsPreferences _extensionEnabledStateDidChange:]               (Safari)   ← notification observer
  → -[WBSExtensionsController  setExtension:isEnabled:dueToUserGesture:skipSavingToStorage:]
  → -[WBSExtensionsController writeExtensionsStateToStorageWithCompletionHandler:]
      → -[WBSWebExtensionsController webExtensionForExtensionIdentifier:]
      → -[WBSExtensionsController extensionDataForExtension:]
  → -[WBSExtensionsController _disableAndBlockExtension:]              ←★ THE TRIGGER
  → -[WBSExtensionsController setExtension:isEnabled:]
  → -[WBSExtensionsController setExtension:isEnabled:dueToUserGesture:skipSavingToStorage:]
  → -[NSNotificationCenter postNotificationName:object:userInfo:]      (Foundation)
  → __CFXNotificationPost → __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__  (CoreFoundation)
  → -[ExtensionsPreferences _extensionEnabledStateDidChange:]          ← same observer fires again → ∞

What this actually means Safari is trying to disable-and-block a web extension (_disableAndBlockExtension:). Doing so flips the extension's enabled state, which posts a notification, which the Extensions-preferences observer (_extensionEnabledStateDidChange:) handles by... calling back into the disable path, which posts the notification again — forever. It's a reentrant notification loop in Safari's own web-extensions controller. Classic missing reentrancy guard.

So this is extension-related after all — but not the way you feared:

It's still 100% an Apple bug. A correct Safari disables the extension once. This one recurses until it segfaults. Your JavaScript is nowhere near it (the loop is entirely Objective-C in SafariSharedUI/Safari.framework). The trigger is Safari deciding one of your registered dev extensions should be blocked. Safari blocks a web extension when it can't validate it — typically a dev build whose signature/app bundle is in a flux state (rebuilt from DerivedData, app bundle moved, etc.). You have exactly two such dev extensions registered (the test app and the [full product], both from build dirs), and we've been rebuilding/moving them all session.

The fix that breaks the loop

Give Safari nothing to block. If we unregister the dev extension builds Safari is choking on (and relaunch Safari), the _disableAndBlockExtension: path never fires, so the recursion can't start. For ongoing dev, register a properly-signed copy from a stable location (not DerivedData) so Safari validates it instead of blocking it.

Want me to do the cleanup now — unregister the two DerivedData/build-dir extension registrations from LaunchServices and confirm Safari sees a clean slate? That's the most direct way to stop the crashes. I'll show you exactly what I unregister first and it's fully reversible (a rebuild re-registers them).

To recap the whole arc: your machine can build, sign, embed, and load a Catalyst Safari extension fine (the test app proved that, and it appeared in Safari's Extensions list). The crashes you've been hitting are a recurring Apple bug — a missing reentrancy guard in Safari's _disableAndBlockExtension: → _extensionEnabledStateDidChange: notification path that stack-overflows whenever Safari tries to block a web extension it won't validate. It's triggered by dev extensions loaded from DerivedData, but the fault is entirely in Safari's Objective-C, never in your code.

Can someone at Apple please fix this?

Crash solved!

Two changes, either of which might have been the fix.

First, I made sure that manifest.json was in Resources/ directly instead of Resources/src, where it had been (since I had a build phase that copied in an entire /src tree from outside of my Xcode project). Gemini had told me that I could use a key in Info.plist to point to src/ but I started to doubt whether that was actually a real thing.

Second, in the following block of code, I removed "let SFExtensionMessageKey = "message":

import SafariServices
import os.log

let SFExtensionMessageKey = "message"

class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {

	func beginRequest(with context: NSExtensionContext) {
        let item = context.inputItems[0] as! NSExtensionItem
        let message = item.userInfo?[SFExtensionMessageKey]
        os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@", message as! CVarArg)

        let response = NSExtensionItem()
        response.userInfo = [ SFExtensionMessageKey: [ "Response to": message ] ]

        context.completeRequest(returningItems: [response], completionHandler: nil)
    }
    
}

That did the trick. No more Safari crash!

Apple, please fix this, I just wasted an entire week!

Safari 17.6 (17618.3.11.11.7, 17618) Crashes on Attempt to Run Extension in Developer Mode
 
 
Q