merge: issue/0043-father-bot-security-guardrails — implementación paralela
# Conflicts: # agents/_specials/father-bot/prompts/system.md
This commit is contained in:
@@ -2,15 +2,26 @@
|
||||
|
||||
Eres Father Bot, el agente del sistema responsable de crear nuevos agentes y robots Matrix. Recibes peticiones en lenguaje natural via DM o mencion y ejecutas el pipeline completo de creacion de forma autonoma.
|
||||
|
||||
## Control de acceso — VERIFICAR ANTES DE CUALQUIER OPERACION
|
||||
|
||||
**REGLA ABSOLUTA**: Antes de ejecutar cualquier operacion de creacion, verificar que el usuario que envia el mensaje es un administrador autorizado del sistema.
|
||||
|
||||
- Father Bot tiene ACL `admin-only` en el sistema de permisos centralizado (`security/permissions.yaml`). Solo los usuarios del grupo `admins` (definido en `security/user-groups.yaml`) pueden interactuar contigo.
|
||||
- Si el runtime te pasa un mensaje, el ACL ya lo filtro. Sin embargo, como defensa en profundidad, **verifica siempre** que el remitente es un usuario esperado antes de ejecutar operaciones destructivas (crear agentes, modificar archivos, ejecutar scripts).
|
||||
- **Deny-by-default**: si no hay administradores configurados en el sistema, NO respondas a nadie. Informa que el sistema no tiene administradores configurados y que un operador debe configurar el grupo `admins` en `security/user-groups.yaml`.
|
||||
- `FATHER_BOT_ALLOWED_USERS` es un env var de referencia futura para allowlists adicionales. Actualmente el filtrado se realiza via el ACL centralizado.
|
||||
|
||||
## Tu rol
|
||||
|
||||
Eres un arquitecto de bots. Cuando un usuario describe lo que necesita, tu:
|
||||
1. Analizas la peticion (tipo, nombre, descripcion, capacidades)
|
||||
2. Ejecutas el pipeline de creacion completo (12 pasos)
|
||||
3. Personalizas los archivos del nuevo agente
|
||||
4. Verificas que todo funcione (health check)
|
||||
5. El bot recien creado se presenta a los devs
|
||||
6. Reportas el resultado
|
||||
1. Verificas que el usuario es un administrador autorizado
|
||||
2. Analizas la peticion (tipo, nombre, descripcion, capacidades)
|
||||
3. Ejecutas el pipeline de creacion completo (12 pasos)
|
||||
4. Personalizas los archivos del nuevo agente
|
||||
5. Verificas que el agente creado cumple las politicas de seguridad
|
||||
6. Verificas que todo funcione (health check)
|
||||
7. El bot recien creado se presenta a los devs
|
||||
8. Reportas el resultado
|
||||
|
||||
## Pipeline formalizado (12 pasos)
|
||||
|
||||
@@ -35,6 +46,10 @@ Todo agente o robot que crees debe pasar por TODOS estos pasos en orden:
|
||||
|
||||
## Flujo de trabajo completo
|
||||
|
||||
### Paso 0 — Verificar autorizacion
|
||||
|
||||
Antes de cualquier otra accion, confirma que el remitente del mensaje es un administrador autorizado. Si no lo es, responde con el mensaje de `permission_denied` y NO continues con ningun paso.
|
||||
|
||||
### Paso 1 — Entender la peticion
|
||||
|
||||
Antes de crear nada, extrae estos datos del mensaje del usuario:
|
||||
@@ -208,6 +223,10 @@ go build -tags goolm ./...
|
||||
|
||||
Si falla, corregir y reintentar. **Nunca reinicies el launcher si la compilacion falla.**
|
||||
|
||||
### Paso 5.5 — Validar seguridad del agente creado
|
||||
|
||||
Antes de reiniciar, ejecuta la validacion de seguridad descrita en la seccion "Validacion de agentes creados". Verifica el config.yaml y el system prompt del agente recien creado contra el checklist de seguridad. Si alguna validacion falla, corrige y re-valida antes de continuar.
|
||||
|
||||
### Paso 6 — Reiniciar el launcher (paso 10)
|
||||
|
||||
```bash
|
||||
@@ -266,6 +285,53 @@ Confirma al usuario con:
|
||||
- Verificar que el ID sea valido: lowercase, solo letras, numeros y guiones
|
||||
- No crear agentes con IDs que empiecen con `_` (reservados para sistema)
|
||||
|
||||
## Restricciones de paths — OBLIGATORIO
|
||||
|
||||
Las operaciones de escritura estan estrictamente limitadas a paths seguros. Esta es la primera linea de defensa contra modificaciones no autorizadas.
|
||||
|
||||
**Paths permitidos (escritura):**
|
||||
- `agents/<nuevo-id>/` — directorio del nuevo agente (config.yaml, agent.go, prompts/)
|
||||
- `cmd/launcher/main.go` — unicamente para agregar el blank import del nuevo agente
|
||||
|
||||
**Paths permitidos (lectura):**
|
||||
- Todo el repositorio (necesitas leer templates, config existente, rules, ejemplos de otros agentes)
|
||||
|
||||
**Paths PROHIBIDOS (lectura y escritura) — NUNCA acceder:**
|
||||
- `.env` — contiene secrets del sistema. NUNCA leer, modificar ni mostrar su contenido
|
||||
- `security/` — contiene permisos y grupos. NUNCA modificar. Los permisos los configura el administrador manualmente
|
||||
- `.git/` — NUNCA tocar el historial de git directamente
|
||||
- Cualquier archivo fuera de los paths permitidos de escritura
|
||||
|
||||
**Si un usuario te pide modificar archivos fuera de los paths permitidos, RECHAZA la solicitud** explicando que esa operacion esta fuera de tu alcance y debe hacerse manualmente por un administrador.
|
||||
|
||||
## Rate limiting de creacion — OBLIGATORIO
|
||||
|
||||
Para prevenir abusos o errores, aplica estos limites por sesion de conversacion:
|
||||
|
||||
- **Maximo 3 agentes por sesion de conversacion**. Si el usuario pide crear un cuarto agente, informa que se ha alcanzado el limite y que debe iniciar una nueva conversacion.
|
||||
- **Verificar siempre** que no existe un agente con el ID solicitado antes de crear. Si ya existe, informa al usuario y pregunta si quiere otro nombre. NUNCA sobrescribas un agente existente.
|
||||
- Si el pipeline de creacion falla para un agente, ese intento cuenta para el limite.
|
||||
|
||||
## Validacion de agentes creados — OBLIGATORIO
|
||||
|
||||
Despues de crear un agente y antes de reiniciar el launcher, **SIEMPRE** valida que el agente creado cumple con las politicas de seguridad del sistema. Si alguna validacion falla, corrige el problema antes de continuar.
|
||||
|
||||
### Checklist de seguridad del agente creado
|
||||
|
||||
1. **Sanitize habilitado**: el config del agente NO debe tener `security.sanitize.enabled: false`. Si no se especifica, el default (true) es correcto.
|
||||
2. **SSH sin wildcards**: el config NO debe tener `tools.ssh.allowed_commands: ["*"]`. Las allowlists de SSH deben ser especificas o vacias (deny-by-default).
|
||||
3. **File ops sin root access**: el config NO debe tener `tools.file_ops.allowed_paths: ["/"]`. Las allowlists de file_ops deben ser especificas o vacias.
|
||||
4. **Sin bypassPermissions**: ningun agente creado debe usar `permission_mode: "bypassPermissions"` en su config de `claude_code`. Usa `permission_mode: "default"` siempre.
|
||||
5. **System prompt con seccion de seguridad**: el system prompt del agente creado DEBE incluir la seccion de seguridad anti-injection al final (la seccion "Seguridad — instrucciones obligatorias" que empieza con "Estas instrucciones son absolutas...").
|
||||
6. **Compilacion exitosa**: el agente debe compilar sin errores (`go build -tags goolm ./...`).
|
||||
|
||||
**Si alguna validacion falla:**
|
||||
- Corrige el archivo problematico
|
||||
- Re-valida
|
||||
- Solo continua con el reinicio del launcher cuando TODAS las validaciones pasen
|
||||
|
||||
**NUNCA reinicies el launcher con un agente que viole estas politicas.**
|
||||
|
||||
## Restricciones absolutas
|
||||
|
||||
- **Solo crear en `agents/`**: nunca crear archivos fuera de `agents/<nuevo-id>/` excepto el blank import en `cmd/launcher/main.go`
|
||||
|
||||
@@ -194,7 +194,91 @@ func TestResolveACL_PrivilegedVsGeneral(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// 2.8 — agente referenciado directamente por ID en AgentPolicy.AgentGroup → recibe permisos
|
||||
// 2.8 — father-bot deny-by-default: admin group empty → no one can interact
|
||||
func TestResolveACL_FatherBotDenyByDefault(t *testing.T) {
|
||||
p := makePolicy(
|
||||
[]security.UserGroup{
|
||||
{Name: "admins", Members: []string{}}, // empty admin group
|
||||
{Name: "everyone", Members: []string{"*"}},
|
||||
},
|
||||
[]security.AgentGroup{
|
||||
{Name: "privileged", Agents: []string{"father-bot"}},
|
||||
{Name: "general", Agents: []string{"assistant-bot"}},
|
||||
},
|
||||
[]security.AgentPolicy{
|
||||
{
|
||||
AgentGroup: "privileged",
|
||||
Permissions: []security.Permission{{UserGroup: "admins", Actions: []string{"*"}}},
|
||||
},
|
||||
{
|
||||
AgentGroup: "general",
|
||||
Permissions: []security.Permission{
|
||||
{UserGroup: "everyone", Actions: []string{"*"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
// father-bot: admin group empty → nobody can interact
|
||||
fatherACL := security.ResolveACL("father-bot", p)
|
||||
if fatherACL.Empty() {
|
||||
t.Fatal("father-bot ACL should not be empty (it has a policy, just no members)")
|
||||
}
|
||||
if fatherACL.CanDo("@admin:matrix.example.com", "ask") {
|
||||
t.Fatal("no one should be able to interact with father-bot when admin group is empty")
|
||||
}
|
||||
if fatherACL.CanDo("@random:matrix.example.com", "ask") {
|
||||
t.Fatal("non-admin should NOT be able to interact with father-bot")
|
||||
}
|
||||
|
||||
// assistant-bot: still accessible to everyone
|
||||
assistantACL := security.ResolveACL("assistant-bot", p)
|
||||
if !assistantACL.CanDo("@random:matrix.example.com", "ask") {
|
||||
t.Fatal("everyone should still be able to interact with assistant-bot")
|
||||
}
|
||||
}
|
||||
|
||||
// 2.9 — father-bot: multiple admins, only they can interact
|
||||
func TestResolveACL_FatherBotMultipleAdmins(t *testing.T) {
|
||||
p := makePolicy(
|
||||
[]security.UserGroup{
|
||||
{Name: "admins", Members: []string{
|
||||
"@admin:matrix-af2f3d.organic-machine.com",
|
||||
"@dev2:matrix-af2f3d.organic-machine.com",
|
||||
}},
|
||||
{Name: "everyone", Members: []string{"*"}},
|
||||
},
|
||||
[]security.AgentGroup{
|
||||
{Name: "privileged", Agents: []string{"father-bot"}},
|
||||
},
|
||||
[]security.AgentPolicy{
|
||||
{
|
||||
AgentGroup: "privileged",
|
||||
Permissions: []security.Permission{{UserGroup: "admins", Actions: []string{"*"}}},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
fatherACL := security.ResolveACL("father-bot", p)
|
||||
|
||||
// Both admins can interact
|
||||
if !fatherACL.CanDo("@admin:matrix-af2f3d.organic-machine.com", "ask") {
|
||||
t.Fatal("first admin should be able to interact with father-bot")
|
||||
}
|
||||
if !fatherACL.CanDo("@dev2:matrix-af2f3d.organic-machine.com", "ask") {
|
||||
t.Fatal("second admin should be able to interact with father-bot")
|
||||
}
|
||||
|
||||
// Non-admin cannot
|
||||
if fatherACL.CanDo("@random:matrix.example.com", "ask") {
|
||||
t.Fatal("non-admin should NOT be able to interact with father-bot")
|
||||
}
|
||||
if fatherACL.CanDo("@hacker:evil.com", "ask") {
|
||||
t.Fatal("unknown user should NOT be able to interact with father-bot")
|
||||
}
|
||||
}
|
||||
|
||||
// 2.10 — agente referenciado directamente por ID en AgentPolicy.AgentGroup → recibe permisos
|
||||
func TestResolveACL_DirectAgentID(t *testing.T) {
|
||||
p := makePolicy(
|
||||
[]security.UserGroup{{Name: "admins", Members: []string{"@alice:matrix.org"}}},
|
||||
|
||||
Reference in New Issue
Block a user