feat: import agents_and_robots platform as unibots (Matrix-out, unibus transport)
Reemplaza el scaffold del echobot por la plataforma completa de bots traida desde ~/DataProyects/Github/agents_and_robots tras la operacion Matrix-out: los bots ya no hablan por Matrix sino por el bus unibus (modelo todo-rooms + E2E via shell/transportunibus sobre github.com/enmanuel/unibus/pkg/client). - go.mod: replace de unibus -> ../unibus y de fn-registry -> ../../../.. (paths relativos reajustados a la nueva ubicacion dentro de fn_registry). - app.md: bump a 0.2.0, descripcion + arquitectura + comandos + gotchas reales. - modulo Go conservado como github.com/enmanuel/agents (sin reescribir imports). agents_and_robots queda archivado como museo de la era Matrix.
This commit is contained in:
@@ -0,0 +1,237 @@
|
||||
# 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()`.
|
||||
|
||||
## 7. Sistema de grupos centralizados (`security/`)
|
||||
|
||||
Control de acceso centralizado: quien puede hablar con que agentes, y que puede hacer.
|
||||
Reemplaza los campos per-agente `security.roles` y `matrix.filters.allowed_users` (ahora deprecados).
|
||||
|
||||
### Estructura de archivos
|
||||
|
||||
```
|
||||
security/
|
||||
user-groups.yaml # grupos de usuarios Matrix
|
||||
agent-groups.yaml # grupos de agentes
|
||||
permissions.yaml # politicas: que grupo de usuarios tiene que acciones en que agentes
|
||||
```
|
||||
|
||||
### user-groups.yaml
|
||||
|
||||
```yaml
|
||||
groups:
|
||||
admins:
|
||||
members: ["@admin:matrix-af2f3d.organic-machine.com"]
|
||||
developers:
|
||||
members: ["@dev1:homeserver.com", "@dev2:homeserver.com"]
|
||||
everyone:
|
||||
members: ["*"] # wildcard: todos los usuarios
|
||||
```
|
||||
|
||||
### agent-groups.yaml
|
||||
|
||||
```yaml
|
||||
groups:
|
||||
all:
|
||||
agents: ["*"] # wildcard: todos los agentes
|
||||
production:
|
||||
agents: ["assistant-bot", "asistente-2"]
|
||||
```
|
||||
|
||||
### permissions.yaml
|
||||
|
||||
```yaml
|
||||
policies:
|
||||
- agent_group: all # aplica a todos los agentes
|
||||
permissions:
|
||||
- user_group: admins
|
||||
actions: ["*"] # admins pueden hacer todo
|
||||
- user_group: everyone
|
||||
actions: ["ask"] # todos pueden chatear
|
||||
- agent_group: production # solo agentes de produccion
|
||||
permissions:
|
||||
- user_group: developers
|
||||
actions: ["ask", "command:deploy", "tool:ssh_command"]
|
||||
```
|
||||
|
||||
### Acciones disponibles
|
||||
|
||||
| Accion | Descripcion |
|
||||
|--------|-------------|
|
||||
| `*` | Todo permitido |
|
||||
| `ask` | Puede chatear con el agente (mensajes normales) |
|
||||
| `command:<name>` | Puede ejecutar el comando `!<name>` |
|
||||
| `tool:<name>` | El LLM puede llamar la tool `<name>` para este usuario |
|
||||
|
||||
### Resolucion de ACL
|
||||
|
||||
Al arrancar, el launcher:
|
||||
1. Carga todos los YAMLs con `shellsecurity.Load("security/")`
|
||||
2. Para cada agente, llama `pksecurity.ResolveACL(agentID, policy)`
|
||||
3. Inyecta la `acl.ACL` resultante en `agents.New()`
|
||||
|
||||
**Comportamiento cuando la politica esta vacia**: si `security/` no existe o no hay politicas que apliquen al agente, la ACL esta vacia y el acceso es abierto (sin restricciones). Preferible a denegar todo por defecto en produccion.
|
||||
|
||||
### Campos deprecados
|
||||
|
||||
Los siguientes campos en `config.yaml` del agente estan deprecated y no tienen efecto desde la activacion del sistema centralizado:
|
||||
|
||||
- `security.roles` — reemplazado por `security/permissions.yaml`
|
||||
- `matrix.filters.allowed_users` — reemplazado por `security/user-groups.yaml`
|
||||
|
||||
Los campos siguen en el schema para compatibilidad con configs existentes y se eliminarán en un issue futuro.
|
||||
|
||||
## 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
|
||||
Reference in New Issue
Block a user