">
 

A LaunchAgent gets `Operation not permitted` for `~/Documents` while Terminal works

Iniciado por joomlamz, Hoje at 02:25

Respostas: 1   |   Visualizações: 4

Tópico anterior - Tópico seguinte

0 Membros e 2 Visitantes estão a ver este tópico.

Saudações, estimados membros e entusiastas da tecnologia do **webmastersmz.com**! Como especialista em tecnologia, analisei o tópico em inglês intitulado *"A LaunchAgent gets Operation not permitted for ~/Documents while Terminal works"* (Um LaunchAgent obtém o erro 'Operação não permitida' para a pasta Documentos, enquanto o Terminal funciona).

Este é um problema clássico e bastante frustrante no macOS, relacionado com as políticas de segurança avançadas da Apple, especificamente o **Transparency, Consent, and Control (TCC)** e o mecanismo de **Sandbox**, introduzidos nas versões mais recentes do sistema operativo (como macOS Mojave e posteriores).

### Análise Técnica do Problema

1. **A Origem do Erro (`Operation not permitted`):**
   No macOS, pastas sensíveis como `~/Documents`, `~/Desktop` e `~/Downloads` são protegidas pelo sistema de permissões de privacidade do TCC. Quando executamos um comando ou script manualmente através do **Terminal**, o macOS pede o consentimento ao utilizador (ou herda as permissões do próprio Terminal, caso este já tenha acesso total ao disco).

2. **O Comportamento do LaunchAgent (`launchd`):**
   Por outro lado, um `LaunchAgent` corre em segundo plano, gerido pelo processo do sistema `launchd`. Quando um agente tenta aceder a diretórios protegidos, ele não possui uma sessão interativa de terminal associada para solicitar ou herdar permissões da mesma forma. Como resultado, o sistema bloqueia o acesso silenciosamente, retornando o erro `Operation not permitted`, mesmo que o script funcione perfeitamente quando corrido manualmente por si na consola.

3. **Como resolver a questão:**
   * **Full Disk Access (Acesso Total ao Disco):** A solução mais comum passa por ir a *Preferências do Sistema > Privacidade e Segurança > Acesso Total ao Disco* (Full Disk Access) e adicionar o binário responsável pela execução (como o `/bin/bash`, `/bin/zsh`, o interpretador Python, ou o próprio editor/daemon utilizado).
   * **Assinatura de Código (Code Signing):** Para daemons mais complexos, garantir que o binário está devidamente assinado pode mitigar bloqueios do Gatekeeper e do TCC.

Como é que vocês têm lidado com estas restrições rígidas de segurança do macOS nos vossos fluxos de trabalho de automação e desenvolvimento? Já depararam com este comportamento em scripts de rotina (`cron` ou `launchd`)? Deixem as vossas experiências, dicas e dúvidas aqui nos comentários para enriquecermos a nossa discussão na comunidade do **webmastersmz.com**!

---

Para garantir que os vossos projetos e fóruns rodam sem falhas, convido-vos a conhecer as soluções de alojamento de alta performance da AplicHost em https://aplichost.com.

A LaunchAgent gets `Operation not permitted` for `~/Documents` while Terminal works



Tópico: A LaunchAgent gets `Operation not permitted` for `~/Documents` while Terminal works
Categoria: Tutoriais | Programação & Tecnologia
Idioma Principal: Português (Conteúdo de Tecnologia)

Descrição do Conteúdo / Informações:
-------------------------------------------------------------------------
The same zsh script could list ~/Documents when I ran it in Terminal. Started as a LaunchAgent, it failed with:

ls: /Users/administrator/Documents: Operation not permitted

The LaunchAgent had the same user ID, the same $HOME, and the same script. That combination makes this look like a Unix permission problem. In this test it was not. The useful discriminator was the launch context: access succeeded from Terminal, failed from launchd, and still succeeded for a path outside the protected folder.

I reproduced this on macOS 15.6.1 (Darwin 24.6.0) with a LaunchAgent in gui/501. The probe was removed after the test.



Why chmod is the wrong first check


The obvious suspects were file ownership, a wrong home directory, or a job running as another user. The probe printed those facts before touching the files:

#!/bin/zsh

print -- "user=$(id -un) uid=$(id -u)"
print -- "home=$HOME pwd=$PWD"

/bin/ls "$HOME/Documents" 2>&1 | /usr/bin/head -5
/bin/cat "$HOME/Documents/vinh/working/CLAUDE.md" 2>&1 | /usr/bin/head -1

# Negative control: outside Documents
/bin/ls "$HOME/.pf004" 2>&1 | /usr/bin/head -5

The two runs produced this difference:

Check
Terminal
LaunchAgent in gui/501

User / uid

administrator / 501

administrator / 501

$HOME
/Users/administrator
/Users/administrator

ls ~/Documents
Listed entries
Operation not permitted

cat inside ~/Documents

Read the file
Operation not permitted

ls ~/.pf004
Listed entries
Listed entries

The working directory differed, but the script used absolute paths under $HOME, so PWD=/ did not explain the denial. The negative control mattered more: the LaunchAgent could read another directory owned by the same user. Changing ownership or mode bits would not explain why only the launch context changed the result.



The owning layer is the privacy context


On this machine, the access decision was attached to how the process was launched, not just to uid 501. Terminal had a privacy context that allowed access to the user's Documents folder. The process started by launchd did not inherit that access.

That is why these observations can all be true at once:


id -u reports the expected user.


$HOME points to the expected home directory.

• Ordinary files elsewhere under that home directory are readable.

• A read under ~/Documents returns Operation not permitted.

The smallest diagnostic is therefore not another chmod. Run one identical read from the interactive application and from the scheduled process, then add a control path outside Desktop, Documents, or Downloads. If the user and path are correct, the control succeeds, and only the protected folder fails, investigate the macOS privacy context of the scheduled process.



A pipeline can hide the denial


My first probe contained this line:

/bin/ls "$HOME/Documents" 2>&1 | /usr/bin/head -5
print -- "status=$?"

It printed Operation not permitted and then printed status=0.

In zsh, the default status of a pipeline is the status of its last command. head successfully printed the error text, so the pipeline looked successful even though ls failed. This is enough to turn a visible privacy denial into missing downstream data.

For a diagnostic script, enable pipeline failure before the probe:

set -o pipefail

/bin/ls "$HOME/Documents" 2>&1 | /usr/bin/head -5
print -- "status=$?"

I checked the behavior with a minimal control: /usr/bin/false | /usr/bin/head -1 returned 0 by default and 1 with pipefail enabled. In a larger job, capture and handle the status immediately rather than letting another command overwrite $?.



What to change in an unattended job


If the job does not need a protected folder, move its required inputs and state to an unprotected application directory. The negative-control path under ~/.pf004 was readable from both launch contexts in this test.

If the job must read Documents, treat that as a separate permission requirement and test it from the actual LaunchAgent. A successful Terminal run is not proof that the scheduled process has the same access. I did not test Full Disk Access, a system LaunchDaemon, Desktop, or Downloads, so this result does not establish how those configurations behave.

The practical rule is narrow: same uid and same $HOME do not make Terminal and a LaunchAgent equivalent readers of ~/Documents. Compare the launch contexts, keep an outside-path negative control, and make the pipeline report the command that actually failed.


Joomlamz
Consultoria em Informática
-------------------------------------------------------
Especialista em Sistemas Web & Manutenção de Servidores.
A desenvolver o novo AplPortal com suporte a PHP 8.
Precisa de ajuda profissional? Contacte-me.

Tags: