fix: document + tool the macOS com.apple.provenance workaround (#3)
Root cause: macOS Sequoia+ blocks Python.app from executing files carrying the com.apple.provenance extended attribute. Files written by an agent/IDE terminal get it (shell scripts and pre-session files do not). This is a macOS security feature, not a bug in our code — so the fix is an operator workaround, not a code change to the tools. - scripts/clear-provenance: recursively removes ONLY com.apple.provenance under a path (default: repo root); tolerates files without it; leaves other xattrs intact; supports --dry-run. Advises running from a Full-Disk-Access terminal. - README Troubleshooting section documenting the symptom, the helper, manual xattr equivalents, and the Full Disk Access alternative. Narrow + macOS-specific; no auth/release/worktree/tracker/MCP behavior changed. Tests: tests/test_clear_provenance.py (6 cases) — dry-run default/explicit path, missing-path error, bad-flag/too-many-args exit 2, and that only com.apple.provenance is targeted (not a blanket xattr clear). Dry-run only; no real xattr mutation. bash -n clean; py_compile mcp_server.py clean; full suite 319 passed / 0 failures; git diff --check clean; no secrets. Closes #3. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Executable
+61
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# clear-provenance — strip the macOS com.apple.provenance extended attribute so
|
||||
# Python.app can execute .py files created by agent/IDE terminals (issue #3).
|
||||
#
|
||||
# macOS Sequoia+ blocks Python.app from executing files carrying
|
||||
# com.apple.provenance. Files written by the agent terminal get it; shell
|
||||
# scripts are unaffected. This is a macOS security feature, not a bug in our
|
||||
# code — see the Troubleshooting section of the README.
|
||||
#
|
||||
# Run from a terminal with Full Disk Access (e.g. Terminal.app), not the IDE
|
||||
# terminal, or the removal itself may be blocked.
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
usage: scripts/clear-provenance [--dry-run] [path]
|
||||
|
||||
Recursively remove the com.apple.provenance extended attribute under <path>
|
||||
(default: the repository root). macOS only. Only that attribute is removed;
|
||||
other extended attributes are left intact.
|
||||
|
||||
Examples:
|
||||
scripts/clear-provenance --dry-run
|
||||
scripts/clear-provenance
|
||||
scripts/clear-provenance /path/to/file.py
|
||||
EOF
|
||||
}
|
||||
|
||||
dry_run=0
|
||||
while [[ "${1:-}" == --* ]]; do
|
||||
case "$1" in
|
||||
--dry-run) dry_run=1 ;;
|
||||
--help) usage; exit 0 ;;
|
||||
*) usage >&2; exit 2 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ $# -gt 1 ]]; then
|
||||
usage >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
repo_root="$(cd "$script_dir/.." && pwd)"
|
||||
target="${1:-$repo_root}"
|
||||
|
||||
if [[ ! -e "$target" ]]; then
|
||||
printf 'clear-provenance: no such path: %s\n' "$target" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Remove only com.apple.provenance; tolerate files that do not carry it.
|
||||
if [[ "$dry_run" -eq 1 ]]; then
|
||||
printf 'clear-provenance: [dry-run] would run: xattr -r -d com.apple.provenance %q\n' "$target"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
xattr -r -d com.apple.provenance "$target" 2>/dev/null || true
|
||||
printf 'clear-provenance: removed com.apple.provenance recursively under: %s\n' "$target"
|
||||
Reference in New Issue
Block a user