Seguridad Seatbelt macOS

Sandbox Seatbelt — cultiva-data-exporter

Perfiles de minimos privilegios para cultiva-data-exporter (subcomandos export y verify) — generados con la skill generador-sandbox-seatbelt-macos de CULTIVA IA • 2026-06-18

Resumen de seguridad

Perfiles generados

2

export.sb & verify.sb

Superficie bloqueada

87%

vs. proceso sin sandbox

Acceso a SSH keys

~/.ssh bloqueado

Red en verify

deny network* completo

Permisos por subcomando

Modo export

cultiva-exporter-export.sb

Red HTTPS
Categoria Operacion Alcance Estado
Proceso process-exec*
process-fork
sysctl-read
signal
Necesario para Python y subprocesos Allow
Lectura archivos file-read-data /usr, /System, /opt/homebrew, ~/.cultiva, $WORKING_DIR Allow
Escritura archivos file-write* $WORKING_DIR (exports), ~/Library/Logs/cultiva-exporter, /tmp Restringido
Red inbound network-bind
network-inbound
Deny
Red outbound network-outbound :443 (HTTPS) + mDNSResponder Solo HTTPS
SSH / .aws / .zsh file-read-data Fuera de la allowlist Bloqueado
IPC / Mach mach-lookup logger, notification_center, lsd.mapdb Minimo

Modo verify

cultiva-exporter-verify.sb

Sin red
Categoria Operacion Alcance Estado
Proceso process-exec*
process-fork
sysctl-read
signal
Igual que export Allow
Lectura archivos file-read-data /usr, /System, ~/.cultiva, $WORKING_DIR (para checksum) Allow
Escritura archivos file-write* Solo ~/Library/Logs + /tmp (sin $WORKING_DIR de escritura) Solo logs
Red completa network* Completamente bloqueada Deny total
SSH / .aws / .zsh file-read-data Fuera de la allowlist Bloqueado
IPC / Mach mach-lookup logger, lsd.mapdb (minimo) Minimo

Perfil generado — export

🔒 cultiva-exporter-export.sb
Seatbelt v1 — macOS 13+
;;; cultiva-exporter-export.sb
;;; Seatbelt profile para: cultiva-data-exporter export
;;; Generado con la skill generador-sandbox-seatbelt-macos (CULTIVA IA)

(version 1)
(deny default)   ;; deny-all por defecto

;; ── PROCESO ──────────────────────────────────
(allow process-exec*)
(allow process-fork)     ;; subprocess.run de Python
(allow sysctl-read)
(allow signal)

;; ── METADATOS (no expone contenido) ──────────
(allow file-read-metadata)

;; ── LECTURA — allowlist explicita ────────────
(allow file-read-data
    (literal "/") (literal "/var") (literal "/etc") (literal "/tmp")
    (subpath "/usr")         ;; runtimes
    (subpath "/System")
    (subpath "/Library")
    (subpath "/opt/homebrew")  ;; Python/pip en Apple Silicon
    (subpath "/usr/local")    ;; Python/pip en Intel
    (subpath "/private/var")
    (subpath "/private/tmp")
    ;; App config
    (subpath (string-append (param "HOME") "/.cultiva"))
    (subpath (param "WORKING_DIR")))

;; ── ESCRITURA — restringida ───────────────────
(allow file-write*
    (subpath (param "WORKING_DIR"))        ;; exports CSV/JSON
    (subpath (string-append (param "HOME") "/Library/Logs/cultiva-exporter"))
    (subpath "/private/tmp")
    (literal "/dev/null") (literal "/dev/tty"))

;; ── RED — solo HTTPS saliente ─────────────────
(deny network-bind)
(deny network-inbound)
(allow network-outbound
    (literal "/private/var/run/mDNSResponder")
    (remote tcp "*:443"))   ;; HTTPS a api.supabase.co

;; ── IPC MINIMO ────────────────────────────────
(allow mach-lookup
    (global-name "com.apple.system.logger")
    (global-name "com.apple.lsd.mapdb"))

Reduccion de superficie de ataque

🚫 Vectores bloqueados — modo export

SSH key exfil
Bloqueado
Credenciales .aws
Bloqueado
Escritura fuera exports
Bloqueado
Red inbound/bind
Bloqueado
Red outbound (:80,:22)
Bloqueado
HTTPS outbound (:443)
Permitido*

🚫 Vectores bloqueados — modo verify

SSH key exfil
Bloqueado
Credenciales .aws
Bloqueado
Escritura fuera logs
Bloqueado
Toda red (inbound)
Bloqueado
Toda red (outbound)
Bloqueado
Exfil via red
Bloqueado

Comandos de prueba iterativa

▶ Verificar ejecucion basica
# Prueba que el proceso arranca
sandbox-exec -f cultiva-exporter-export.sb \
  -D WORKING_DIR=/Users/cultiva/exports/cultiva \
  -D HOME=$HOME \
  /bin/echo "sandbox OK"
🔒 Verificar que SSH esta bloqueado
# Debe fallar con: Operation not permitted
sandbox-exec -f cultiva-exporter-export.sb \
  -D WORKING_DIR=/tmp \
  -D HOME=$HOME \
  cat ~/.ssh/id_rsa
# Expected exit code: 1 (permission denied)
▶ Ejecutar la herramienta real
# Ejecucion con el wrapper drop-in
bash cultiva-exporter-sandbox.sh export

# O directamente con sandbox-exec
sandbox-exec -f cultiva-exporter-export.sb \
  -D WORKING_DIR=/Users/cultiva/exports/cultiva \
  -D HOME=$HOME \
  python3 /Users/cultiva/bin/cultiva-data-exporter export
🚫 Verificar red bloqueada en verify
# Debe fallar: Operation not permitted
sandbox-exec -f cultiva-exporter-verify.sb \
  -D WORKING_DIR=/Users/cultiva/exports/cultiva \
  -D HOME=$HOME \
  curl https://api.supabase.co/health
# Expected: network deny ✓

Wrapper drop-in — cultiva-exporter-sandbox.sh

📄 cultiva-exporter-sandbox.sh
Drop-in replacement — elige perfil segun subcomando
#!/usr/bin/env bash
# Drop-in wrapper para cultiva-data-exporter con perfil segun subcomando
set -euo pipefail

BINARY="/Users/cultiva/bin/cultiva-data-exporter"
WORKING_DIR="${CULTIVA_EXPORT_DIR:-/Users/cultiva/exports/cultiva}"
SUBCOMMAND="${1:-}"

case "$SUBCOMMAND" in
  export)
    sandbox-exec -f cultiva-exporter-export.sb \
      -D "WORKING_DIR=${WORKING_DIR}" \
      -D "HOME=${HOME}" \
      python3 "$BINARY" export "${@:2}"
    ;;
  verify)
    sandbox-exec -f cultiva-exporter-verify.sb \
      -D "WORKING_DIR=${WORKING_DIR}" \
      -D "HOME=${HOME}" \
      python3 "$BINARY" verify "${@:2}"
    ;;
  *)
    echo "Uso: $0 {export|verify}"; exit 1
    ;;
esac