{"id":13647708,"url":"https://github.com/sveinbjornt/STPrivilegedTask","last_synced_at":"2025-04-22T02:32:35.875Z","repository":{"id":2029789,"uuid":"2966260","full_name":"sveinbjornt/STPrivilegedTask","owner":"sveinbjornt","description":"An NSTask-like wrapper around the macOS Security Framework's  AuthorizationExecuteWithPrivileges function to run shell commands with root privileges in Objective-C / Cocoa.","archived":false,"fork":false,"pushed_at":"2023-10-17T14:15:18.000Z","size":214,"stargazers_count":392,"open_issues_count":3,"forks_count":67,"subscribers_count":20,"default_branch":"master","last_synced_at":"2024-03-14T22:22:58.671Z","etag":null,"topics":["authorization","authorizationexecutewithprivileges","cocoa","macos","macosx","nstask","objective-c","osx","root-privileges","wrapper"],"latest_commit_sha":null,"homepage":"","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sveinbjornt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null},"funding":{"custom":["https://paypal.me/sveinbjornt","sveinbjorn.org/donations"]}},"created_at":"2011-12-12T18:12:01.000Z","updated_at":"2024-02-06T18:09:53.000Z","dependencies_parsed_at":"2024-01-14T10:33:05.632Z","dependency_job_id":"f6674b98-30c8-44b6-bef4-1aa97a0c6ac4","html_url":"https://github.com/sveinbjornt/STPrivilegedTask","commit_stats":{"total_commits":67,"total_committers":7,"mean_commits":9.571428571428571,"dds":"0.29850746268656714","last_synced_commit":"177d2a93207868aa0da20e0cd9a6c2a3181a7f98"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sveinbjornt%2FSTPrivilegedTask","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sveinbjornt%2FSTPrivilegedTask/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sveinbjornt%2FSTPrivilegedTask/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sveinbjornt%2FSTPrivilegedTask/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sveinbjornt","download_url":"https://codeload.github.com/sveinbjornt/STPrivilegedTask/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250163776,"owners_count":21385310,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authorization","authorizationexecutewithprivileges","cocoa","macos","macosx","nstask","objective-c","osx","root-privileges","wrapper"],"created_at":"2024-08-02T01:03:43.718Z","updated_at":"2025-04-22T02:32:35.613Z","avatar_url":"https://github.com/sveinbjornt.png","language":"Objective-C","readme":"[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)\n[![Language](https://img.shields.io/badge/language-objective--c-lightgrey)]()\n[![Release](https://shields.io/github/v/release/sveinbjornt/STPrivilegedTask?display_name=tag)]()\n[![CocoaPods](https://img.shields.io/cocoapods/v/STPrivilegedTask.svg)](https://img.shields.io/cocoapods/v/STPrivilegedTask.svg)\n\n\n# STPrivilegedTask\n\nA Cocoa-style NSTask-like wrapper class around the\n[AuthorizationExecuteWithPrivileges()](https://developer.apple.com/documentation/security/1540038-authorizationexecutewithprivileg)\nfunction in the macOS Security API to run shell commands with root privileges.\nImplemented in Objective-C.\n\nSTPrivilegedTask was created a *very long time ago* (~2005) and has a long history. It has been\nupdated over the years to work with the latest versions of macOS (macOS 13 \"Ventura\" as of writing)\nand is available via [CocoaPods](https://cocoapods.org). It relies on a native system function that\nhas been deprecated since Mac OS X 10.7 \"Lion\" (2011) and will fail gracefully if the function is\nnot available in a future version of the operating system. That being said, *caveat emptor!*\n\n## Usage\n\nAdd the following to your `Podfile` target's dependencies:\n\n```ruby\n    pod 'STPrivilegedTask', '~\u003e 1.0.8'\n```\n\n...or just download the two `STPrivileged.*` source files and include them directly in your project.\n\nTo import:\n\n```objective-c\n#import \"STPrivilegedTask.h\"\n```\n\n## Examples\n\n### Create and launch task\n\n```objective-c\n// Create task\nSTPrivilegedTask *privilegedTask = [STPrivilegedTask new];\n[privilegedTask setLaunchPath:@\"/usr/bin/touch\"];\n[privilegedTask setArguments:@[@\"/etc/my_test_file\"]];\n\n// Setting working directory is optional, defaults to /\n// NSString *path = [[NSBundle mainBundle] resourcePath];\n// [privilegedTask setCurrentDirectoryPath:path];\n\n// Launch it, user is prompted for password (blocking)\nOSStatus err = [privilegedTask launch];\nif (err == errAuthorizationSuccess) {\n    NSLog(@\"Task successfully launched\");\n}\nelse if (err == errAuthorizationCanceled) {\n    NSLog(@\"User cancelled\");\n} \nelse {\n    NSLog(@\"Something went wrong, error %d\", err);\n}\n```\nSee [Authorization.h](http://www.opensource.apple.com/source/libsecurity_authorization/libsecurity_authorization-36329/lib/Authorization.h)\nfor a list of possible error codes.\n\n### Launch task one-liner\n\n```objective-c\nOSStatus err = [STPrivilegedTask launchedPrivilegedTaskWithLaunchPath:@\"/bin/sh\" \n                                                            arguments:@[@\"/path/to/script.sh\"]];\n```\n\n\n### Getting task output\n\n```objective-c\n// ... Launch task\n\n[privilegedTask waitUntilExit]; // This is blocking\n\n// Read output file handle for data\nNSData *outputData = [[privilegedTask outputFileHandle] readDataToEndOfFile];\nNSString *outputString = [[NSString alloc] initWithData:outputData \n                                               encoding:NSUTF8StringEncoding];\n\n```\n\n### Getting output while task runs in background\n\n```objective-c\n\n// ... Launch privilegedTask\n\nNSFileHandle *readHandle = [privilegedTask outputFileHandle];\n[[NSNotificationCenter defaultCenter] addObserver:self\n                                         selector:@selector(getOutputData:)\n                                             name:NSFileHandleReadCompletionNotification\n                                           object:readHandle];\n[readHandle readInBackgroundAndNotify];\n\n// ...\n\n- (void)getOutputData:(NSNotification *)aNotification {\n    // Get data from notification\n    NSData *data = [[aNotification userInfo] objectForKey:NSFileHandleNotificationDataItem];\n    \n    // Make sure there's actual data\n    if ([data length]) {\n        // Do something with the data\n        NSString *outputString = [[NSString alloc] initWithData:data \n                                                       encoding:NSUTF8StringEncoding];\n        NSLog(@\"%@\", outputString);\n        \n        // Go read more data in the background\n        [[aNotification object] readInBackgroundAndNotify];\n    } else {\n        // Do something else\n    }\n}\n```\n\n### Task termination\n\nYou can observe STPrivilegedTaskDidTerminateNotification:\n\n```objective-c\n[[NSNotificationCenter defaultCenter] addObserver:self\n                                         selector:@selector(privilegedTaskFinished:)\n                                             name:STPrivilegedTaskDidTerminateNotification\n                                           object:nil];\n\n- (void)privilegedTaskFinished:(NSNotification *)aNotification {\n    // Do something\n}\n```\n\nOr alternatively set a termination handler block:\n\n```objective-c\nprivilegedTask.terminationHandler = ^(STPrivilegedTask *privilegedTask) {\n    NSLog(@\"Terminating task: %@\", [privilegedTask description]);\n};\n```\n\n### Launch using external AuthorizationRef\n\n```objective-c\n// ... Create your own AuthorizationRef\n\n[STPrivilegedTask launchedPrivilegedTaskWithLaunchPath:@\"/bin/sh\"\n                                             arguments:@\"/path/to/script\"\n                                      currentDirectory:@\"/\"\n                                         authorization:authRef]\n```\n\n###  AuthorizationExecuteWithPrivileges() is deprecated\n\n[AuthorizationExecuteWithPrivileges()](https://developer.apple.com/library/mac/documentation/Security/Reference/authorization_ref/#//apple_ref/c/func/AuthorizationExecuteWithPrivileges)\nis deprecated as of macOS 10.7 but still remains available in macOS 13 \"Ventura\". If you want to be \nfuture-proof, here's how you check if STPrivilegedTask works in the running version of macOS:\n\n```objective-c\n// ...create privilegedTask object\n\nOSStatus err = [privilegedTask launch];\nif (err == errAuthorizationFnNoLongerExists) {\n    NSLog(@\"AuthorizationExecuteWithPrivileges not available\");\n    // Do something to handle the situation\n}\n```\n\nIf you need to check whether STPrivilegedTask works before you launch the task:\n\n```objective-c\nBOOL works = [STPrivilegedTask authorizationFunctionAvailable];\n```\n\n## Sample app\n\nA sample app which makes use of STPrivilegedTask is included in the project. This app runs the following script:\n\n```\n#!/bin/sh\n\necho \"/usr/bin/whoami:\"\nwhoami\necho \"\"\necho \"Real User ID:\"\necho $UID \\($USER\\)\necho \"\"\necho \"Effective User ID:\"\n/usr/bin/id -u\necho \"\"\necho \"Current working directory:\"\necho \"$PWD\"\n\nexit 5\n```\n\nIt waits for the script to finish and then shows the output in a window, along with the exit code.\n\n\u003cimg src=\"screenshot.png\"\u003e\n\n## BSD License \n\nCopyright (c) 2008-2023 Sveinbjorn Thordarson \u0026lt;sveinbjorn@sveinbjorn.org\u0026gt;\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or other\nmaterials provided with the distribution.\n\n3. Neither the name of the copyright holder nor the names of its contributors may\nbe used to endorse or promote products derived from this software without specific\nprior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\nIN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\nWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.\n","funding_links":["https://paypal.me/sveinbjornt","sveinbjorn.org/donations"],"categories":["Objective-C"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsveinbjornt%2FSTPrivilegedTask","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsveinbjornt%2FSTPrivilegedTask","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsveinbjornt%2FSTPrivilegedTask/lists"}