Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
*.manifest
*.spec

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
53 changes: 40 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,20 @@

Apple has a utility in `/usr/bin` named `tccutil`, but it only supports one command, which is to `reset` the entire database. It has been like this for many versions of macOS. I wanted a command-line utility that would be able to add, remove, list, and take other actions.

## Understanding Global vs Local TCC Databases

macOS maintains two separate TCC databases:

1. **Global TCC Database** (`/Library/Application Support/com.apple.TCC/TCC.db`)
- System-wide permissions that apply to all users
- **Requires sudo/admin privileges** to modify
- Used by default when running `tccutil.py` without the `--user` flag

2. **Local User TCC Database** (`~/Library/Application Support/com.apple.TCC/TCC.db`)
- User-specific permissions
- **Does NOT require sudo** - users can modify their own database
- Accessed by using the `--user` flag (e.g., `tccutil.py --list -u`)

## SIP Notice

This tool needs SIP disabled in order to function. The risk of doing so is up to you.
Expand Down Expand Up @@ -58,7 +72,10 @@ Clone this repo and manually copy `tccutil.py` to `/usr/local/bin` or run from a

## Usage

**This utility needs super-user priveleges for most operations.** It is important that you either run this as root or use `sudo`, otherwise it won't work and you will end up with “permission denied” errors.
**Important:** The privileges required depend on which database you're modifying:

- **Global TCC Database** (default): Requires super-user privileges. Run with `sudo`.
- **Local User TCC Database** (with `--user` flag): Does NOT require `sudo`. Can be run as a regular user.


```
Expand Down Expand Up @@ -96,30 +113,20 @@ optional arguments:

### Examples

#### Global TCC Database (System-wide, requires sudo)

List existing Entries in the Accessibility Database

```bash
sudo tccutil.py --list
```

List existing Entries in the Accessibility Database specific to the current user

```bash
sudo tccutil.py --list -u
```

Add `/usr/bin/osascript` to the Accessibility Database (using UNIX-Style Option)

```bash
sudo tccutil.py -i /usr/bin/osascript
````

Add `/usr/bin/osascript` to the Accessibility Database specific to user 'myuser' (using UNIX-Style Option)

```bash
sudo tccutil.py -i /usr/bin/osascript -u myuser
````

Add *Script Editor* to the Accessibility Database (using Long Option)

```bash
Expand Down Expand Up @@ -150,6 +157,26 @@ Reset system wide accessibility database
sudo tccutil.py reset ALL
```

#### Local User TCC Database (User-specific, no sudo required)

List existing Entries in the current user's Accessibility Database

```bash
tccutil.py --list -u
```

Add `/usr/bin/osascript` to the current user's Accessibility Database

```bash
tccutil.py -i /usr/bin/osascript -u
```

Add `/usr/bin/osascript` to a specific user's Accessibility Database

```bash
tccutil.py -i /usr/bin/osascript -u myuser
```

## Contributing

Many people have contributed already, so feel free to make a PR and we'll get it merged in.
16 changes: 13 additions & 3 deletions tccutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
util_name = os.path.basename(sys.argv[0])

# Utility Version
util_version = '1.5.0'
util_version = '1.5.1'

# Current OS X version
osx_version = version(mac_ver()[0]) # mac_ver() returns 10.16 for Big Sur instead 11.+
Expand All @@ -36,6 +36,9 @@
# Set "sudo" to True if called with Admin-Privileges.
sudo = True if os.getuid() == 0 else False

# Track if we're using local (user-specific) database
using_local_db = False

# Default Verbosity
verbose = False

Expand Down Expand Up @@ -105,9 +108,14 @@ def display_version():

def sudo_required():
"""Check if user has root priveleges to access the database."""
# Local user database doesn't require sudo
if using_local_db:
return

if not sudo:
print("Error:", file=sys.stderr)
print(f" When accessing the Accessibility Database, {util_name} needs to be run with admin-privileges.\n", file=sys.stderr)
print(f" When accessing the global TCC Database, {util_name} needs to be run with admin-privileges.", file=sys.stderr)
print(f" To modify the local user database without sudo, use the --user flag.\n", file=sys.stderr)
display_help(1)


Expand Down Expand Up @@ -333,10 +341,12 @@ def main():
return

global tcc_db
global using_local_db
if args.user != None:
try:
if (len(args.user) > 0): pwd.getpwnam(args.user)
tcc_db = os.path.abspath(os.path.expanduser(f'~{args.user}/{tcc_db}'))
tcc_db = os.path.abspath(os.path.expanduser(f'~{args.user}/Library/Application Support/com.apple.TCC/TCC.db'))
using_local_db = True
except KeyError:
print(f'User "{args.user}" does not exist. Do you mean to use "{args.user}" as ACTION?', file=sys.stderr)
sys.exit(1)
Expand Down
Loading