{"id":48377,"date":"2025-07-07T14:58:22","date_gmt":"2025-07-07T18:58:22","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=48377"},"modified":"2025-07-07T14:58:22","modified_gmt":"2025-07-07T18:58:22","slug":"the-curious-case-of-the-responsible-process","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2025\/07\/07\/the-curious-case-of-the-responsible-process\/","title":{"rendered":"The Curious Case of the Responsible Process"},"content":{"rendered":"<p><a href=\"https:\/\/www.qt.io\/blog\/the-curious-case-of-the-responsible-process\">Tor Arne Vestb&oslash;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/www.qt.io\/blog\/the-curious-case-of-the-responsible-process\"><p>As it turns out, permissions are inherited by child processes. And when a process is about to access some protected resource, the TCC subsystem figure&rsquo;s out which process is the <em>responsible<\/em> one, and uses that as basis for requesting and persisting the result.<\/p><p>[&#8230;]<\/p><p>In the case of an application embedding and launching helper executables this behavior of course makes sense, but it can be a bit surprising in cases such as launching apps from the terminal.<\/p><p>[&#8230;]<\/p><p>As it turned out, since Qt Creator was launching <em>user<\/em> applications when running and debugging, it was effectively becoming the responsible process for all these user applications. And if one of them required a permission that needed a corresponding usage description, then the only way to make the application work was to add the description to the responsible process; Qt Creator.<\/p><p>[&#8230;]<\/p><p>Somehow <code>lldb<\/code> was circumventing the logic that was deciding which process was the responsible one.<\/p><p>Luckily LLDB is part of the open source LLVM project, so I was able to track it down to <a href=\"https:\/\/github.com\/llvm\/llvm-project\/commit\/041c7b84a4b925476d1e21ed302786033bb6035f\">this<\/a> change, with the magic formula:<\/p><p><code>int responsibility_spawnattrs_setdisclaim(posix_spawnattr_t attrs, int disclaim);<\/code><\/p><\/blockquote>\n\n<p>He says it &ldquo;just works&rdquo; with Xcode, though he isn&rsquo;t sure why, but my experience is that often neither Xcode nor the app prompts for Automation or Contacts access when running an app or testing and so the APIs just fail.<\/p>\n\n<p>Via <a href=\"https:\/\/steipete.me\/posts\/2025\/applescript-cli-macos-complete-guide\">Peter Steinberger<\/a> (<a href=\"https:\/\/mastodon.social\/@steipete\/114658959230784669\">tweet<\/a>):<\/p>\n<blockquote cite=\"https:\/\/steipete.me\/posts\/2025\/applescript-cli-macos-complete-guide\">\n<p>If you&rsquo;re building a macOS CLI that uses AppleScript, you need to embed an Info.plist into your binary, sign it with proper entitlements, and optionally use the undocumented <code>responsibility_spawnattrs_setdisclaim<\/code> API to avoid permission dialogs that blames the hosting app.<\/p>\n<p>[&#8230;]<\/p>\n<p>Getting AppleScript to work in a CLI tool turned out to be a maze of undocumented APIs, security permissions, and macOS quirks that nobody warns you about.<\/p>\n<\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2025\/06\/27\/claude-code-experience\/\">Claude Code Experience<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2025\/05\/28\/dropdmg-3-6-9\/\">DropDMG 3.6.9<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2020\/10\/16\/avoiding-applescript-security-and-privacy-requests\/\">Avoiding AppleScript Security and Privacy Requests<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2019\/02\/05\/mojave-privacy-protection-aftermath\/\">Mojave Privacy Protection Aftermath<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2018\/08\/31\/aedeterminepermissiontoautomatetarget-added-but-aepocalyse-still-looms\/\">AEDeterminePermissionToAutomateTarget Added, But AEpocalyse Still Looms<\/a><\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>Tor Arne Vestb&oslash;: As it turns out, permissions are inherited by child processes. And when a process is about to access some protected resource, the TCC subsystem figure&rsquo;s out which process is the responsible one, and uses that as basis for requesting and persisting the result.[&#8230;]In the case of an application embedding and launching helper [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2025-07-07T18:58:24Z","apple_news_api_id":"d4ac33e7-0243-47cd-bdd6-acaa6b2cfe88","apple_news_api_modified_at":"2025-07-07T18:58:25Z","apple_news_api_revision":"AAAAAAAAAAD\/\/\/\/\/\/\/\/\/\/w==","apple_news_api_share_url":"https:\/\/apple.news\/A1Kwz5wJDR8291qyqayz-iA","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[159,466,2777,2518,317,30,1609,1666,2598,71,349,1960,226],"class_list":["post-48377","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-applescript","tag-codesigning","tag-cursor","tag-entitlements","tag-lldb","tag-mac","tag-macos-10-14","tag-macos-10-15","tag-macos-15-sequoia","tag-programming","tag-qt","tag-transparency-consent-and-control-tcc","tag-xcode"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/48377","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=48377"}],"version-history":[{"count":1,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/48377\/revisions"}],"predecessor-version":[{"id":48378,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/48377\/revisions\/48378"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=48377"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=48377"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=48377"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}