# Seguridad — Protecciones contra prompt injection y abuso de tools

Este documento describe las capas de defensa implementadas para proteger los agentes Matrix contra ataques de prompt injection y abuso de herramientas.

## Capas de defensa

La estrategia es **defensa en profundidad**: multiples capas independientes, ninguna es la unica barrera.

```
Mensaje del usuario
  |
  v
1. Input sanitization (pkg/sanitize/) — detecta patrones de injection
  |
  v
2. System prompt hardening — instrucciones anti-manipulation al LLM
  |
  v
3. Tool validation (deny-by-default) — cada tool valida sus inputs
  |
  v
4. Rate limiting (tools/registry.go) — limite de tool calls por room
  |
  v
5. RBAC (pkg/acl/) — control de acceso por usuario/rol
```

## 1. Sanitizacion de input (`pkg/sanitize/`)

Funciones puras que detectan patrones de prompt injection en mensajes entrantes.

**Configuracion:**

```yaml
security:
  sanitize:
    enabled: true
    mode: warn          # warn | strip | reject
    min_severity: medium  # low | medium | high
    disabled_patterns: []  # nombres de patrones a ignorar
```

**Modos:**
- `warn`: loguea warnings pero no modifica el mensaje (default)
- `strip`: elimina las secciones sospechosas del mensaje
- `reject`: rechaza el mensaje completamente con respuesta de error

**Patrones detectados:**
- Delimitadores de sistema: `<|system|>`, `<|assistant|>`, `[INST]`
- Frases de override: "ignore previous instructions", "you are now", etc.
- Intentos de exfiltracion: "repeat your instructions", "show me your prompt"

Los patrones estan en `pkg/sanitize/patterns.go`. Son extensibles.

## 2. Hardening de system prompts

Todos los system prompts deben incluir una seccion de seguridad obligatoria.
Template en `.claude/templates/security-prompt.md`.

Las instrucciones cubren:
- Rechazo de acciones fuera del rol
- Proteccion del system prompt (no revelar)
- Rechazo de comandos destructivos
- Validacion de coherencia contextual
- Resistencia a redefinicion de identidad

## 3. Validacion en tools (deny-by-default)

Cada tool que hace I/O valida sus inputs de forma independiente.

### `tools/file/` — read_file
- **Deny-by-default**: si `AllowedPaths` esta vacio, todo denegado
- **Path traversal**: resuelve symlinks con `filepath.EvalSymlinks`, valida que el path este dentro de los permitidos
- **Prefix confusion**: usa separador de directorio para evitar que `/allowed/path` matchee `/allowed/pathevil`

### `tools/ssh/` — ssh_command
- **AllowedCommands**: allowlist de prefijos de comandos. Si esta definida, solo los comandos que matcheen se ejecutan
- **ForbiddenCommands**: blocklist como segunda capa
- **Validacion de sintaxis**: detecta pipes `|`, subshells `$()`, redirects `>`, chains `&&`/`||`/`;`
- **AllowedTargets**: solo los hosts configurados

### `tools/http/` — http_get, http_post
- **AllowedDomains**: solo los dominios configurados
- **SSRF protection**: resuelve DNS y bloquea IPs privadas (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), link-local (169.254.0.0/16) y metadata (169.254.169.254)

### `tools/matrix/` — matrix_send
- **AllowedRooms**: si esta configurado, solo permite enviar a rooms especificos

## 4. Rate limiting

Limite de tool calls por room por minuto. Previene abuso repetitivo.

**Configuracion:**

```yaml
security:
  tool_rate_limit:
    enabled: true
    max_calls_per_min: 10     # default 10
    cleanup_interval_s: 60    # limpieza de entries expiradas
```

Implementado en `tools/ratelimit.go` como sliding window per room. El registry verifica antes de ejecutar cada tool.

## 5. Aislamiento de filesystem

`storage.base_path` permite mover datos de runtime fuera del arbol del proyecto:

```yaml
storage:
  base_path: /var/lib/agents/mi-bot  # o via $AGENTS_DATA_DIR
```

Prioridad: config `base_path` > `$AGENTS_DATA_DIR/<id>` > `agents/<id>/data/` (default).

Esto previene que tools como `read_file` accedan accidentalmente a codigo fuente, `.env`, o configs del proyecto.

## 6. Aislamiento de claude -p (provider claude-code)

Cuando un agente usa el provider `claude-code`, el subproceso `claude -p` se ejecuta en un directorio de trabajo aislado, no en la raiz del repositorio.

**Configuracion:**

```yaml
llm:
  primary:
    claude_code:
      working_dir: "/tmp/claude-agents/mi-bot"  # directorio aislado
```

**Comportamiento:**
- Si `working_dir` esta configurado: se crea el directorio automaticamente con `MkdirAll` y se usa como CWD del subproceso
- Si `working_dir` esta vacio: se crea un directorio temporal (`os.MkdirTemp`) y se loguea un WARN para que el operador lo note
- **Nunca** se hereda el CWD del launcher (raiz del repo)

Esto evita que el subproceso `claude -p` tenga acceso de lectura/escritura al codigo fuente del proyecto, incluso con `permission_mode: bypassPermissions`.

Implementado en `shell/llm/claudecode.go` → `resolveWorkDir()`.

## Activacion

Para activar todas las protecciones, añadir al `config.yaml` del agente:

```yaml
security:
  sanitize:
    enabled: true
    mode: warn
  tool_rate_limit:
    enabled: true
    max_calls_per_min: 10
```

Y asegurarse de que:
- Las tools tienen allowlists configuradas (no vacias si se quieren usar)
- El system prompt incluye la seccion de seguridad
- `storage.base_path` apunta fuera del proyecto en produccion
- `claude_code.working_dir` apunta fuera del repo si se usa el provider claude-code
