# DevToolsSecurity on macOS and debugger authorization on unattended CI

> Attaching a debugger on a Mac can show a password prompt, and unattended CI stalls on it. What DevToolsSecurity changes, read directly on macOS 27.0.1.

- Canonical: https://jaemyeong.com/en/blog/macos-devtoolssecurity-enable-developer-mode/
- Published: 2026.06.26
- Updated: 2026.10.04
- Category: IT/기술
- Tags: #macOS, #Xcode, #DeveloperMode, #Debugging, #CI-CD

When a debugger attaches to a program built in Xcode or the terminal on a Mac, or when Instruments starts, a "Developer Tools Access" prompt can appear and ask whether one process may control another. On my own Mac, typing the password ends it. On an unattended test or a headless CI/CD runner, the job stalls while that prompt waits for input.

The command that removes the prompt ahead of time is `sudo DevToolsSecurity -enable`. This post covers what the command changes and where to look when the prompt remains after enabling. What I confirmed with read-only commands on macOS 27.0.1 on October 4, 2026 is marked as such. I did not run `-enable` or the group command again this time.

## Why a debugger asks for authorization

macOS isolates the memory of each process. Stopping another process, reading or writing its memory, and injecting code into it are restricted.

lldb and Instruments need access to the target process to analyze it. They get the target's Mach task port through `task_for_pid` in XNU, and use that port to step line by line or dump memory. Without enough privilege, the request is denied or goes through an administrator password prompt. [Authorization Services](https://developer.apple.com/documentation/security/authorization-services) handles that authorization, and the rules are stored in `/var/db/auth.db`.

## The rule that DevToolsSecurity changes

`/usr/sbin/DevToolsSecurity` changes the rule of a right named `system.privilege.taskport`. The earlier version of this post explained that before enabling, the rule asks for the login password or root credentials, and that after enabling, it is tied to the `_developer` group. Of these, I could not check the behavior before enabling this time.

I read the rule in the enabled state with `security authorizationdb read system.privilege.taskport`. These are the values I read (macOS 27.0.1).

- `class` is `user`.
- `group` is `_developer`.
- `authenticate-user` is true, and `allow-root` is false.
- `timeout` is 36000.

An earlier version of this post said the class after enabling is `rule`, but the value I read this time was `user`. The comment on the rule says this right is used by `task_for_pid` and applies only when the requesting program and the target program are run by the same user. It does not authorize access to another user's program. I could not check the values before enabling, because the Mac I checked already had it enabled.

## Use -status to check the state

Running `/usr/sbin/DevToolsSecurity` with no argument does not show the state. According to the usage text, the default action is `-enable`.

This is the usage text, printed by passing an option that does not exist.

```text
$ /usr/sbin/DevToolsSecurity -help
DevToolsSecurity: unrecognized option `-help'
Changes the security authorization policies for developer systems
Usage: /usr/sbin/DevToolsSecurity [-verbose] [-enable | -disable | -status]
    -enable  :: (default) enable developer mode policies
    -disable :: return policies to system default
    -status  :: prints out whether or not developer mode policies are in effect
    -verbose :: makes output more verbose
```

To see only the state, use `-status`.

```text
$ /usr/sbin/DevToolsSecurity -status
Developer mode is currently enabled.
```

The earlier version said to run the command with no argument and look for `enabled`. That explanation was wrong, and it is corrected as shown above.

## When the prompt remains after enabling

After `-enable`, lldb in the terminal or C++ debugging in VS Code can still show the prompt or fail with `attach failed`. The place to look is whether the account is in the `_developer` group.

This command adds the currently logged-in account to the group.

```bash
# 현재 로그인된 계정을 _developer 그룹에 강제 멤버십 추가
sudo dscl . append /Groups/_developer GroupMembership $(whoami)
```

The Korean comment says the command adds the currently logged-in account to the `_developer` group.

After adding, reopening the terminal or logging out and back in is recommended. The members of the group can be listed with `dscl . read /Groups/_developer GroupMembership`.

I did not compare causes myself for this part. On the Mac I checked, the `_developer` group had no `GroupMembership` key at all.

```text
$ dscl . read /Groups/_developer GroupMembership
No such key: GroupMembership
```

I did not check how attaching a debugger behaves on this Mac, where the `GroupMembership` key was absent, or under exactly which condition group membership is needed. There is also no basis for saying that joining the group resolves every `attach failed`.

## What happens on an unattended runner

Mobile release automation uses a Mac mini or a macOS virtual machine in the cloud as a runner. The problem case is when this setup step is omitted after a fresh Xcode install or an OS upgrade.

When Appium or an Xcode UI test installs the test app and tries to attach for debugging, the authorization request appears in the GUI in the background. Nobody is at the runner to answer. The job ends only after the configured time limit passes, and a runner with no time limit keeps waiting. A result from reproducing this flow and timing it is not included here.

So the script that prepares a runner runs two things together.

```bash
# 개발자 도구 액세스 허용 활성화
sudo /usr/sbin/DevToolsSecurity -enable

# 빌드 실행 에이전트 계정을 개발자 그룹에 병합
sudo dscl . append /Groups/_developer GroupMembership build_agent_user
```

The first comment says "enable developer tools access," and the second says "add the build agent account to the developer group."

Replace `build_agent_user` with the account name the runner uses. Putting the enable command into the runner setup guide as well keeps it from being missed on a new machine. There is no basis for saying that every server needs both commands. I also did not measure how installing a test app on a device or simulator connects to task port authorization on the Mac.

## What is given up in security

This setting removes one authorization step. To that extent, developer tools can handle the memory of other processes run by the same user more widely. Access to the machine should be controlled, and binaries or code of unknown origin should not run on it.

Developer Mode on an iPhone or iPad targets something else. [Developer Mode on a device](https://developer.apple.com/documentation/xcode/enabling-developer-mode-on-a-device) allows locally installed apps, such as an app built and run from Xcode, to run on that device. It does not affect apps installed from the App Store or TestFlight. The setting in this post is the permission for tools such as lldb to control other processes on a Mac.

The values read this time come from one Mac running macOS 27.0.1, and because it was already enabled, the values before enabling could not be checked. A comparison across macOS versions is not included here either. I also could not confirm in the documentation exactly which signature the condition "only signed developer tools are allowed" refers to.
