08/Documentation
Seguridad de un durable agent
Qué puede y qué no puede hacer un durable agent, reglas de confianza del socket y del token, qué hace Collie con el texto de un durable agent y qué conserva el registro de auditoría
Experimental. El protocolo de red, el SDK y esta página pueden cambiar, o la funcionalidad puede eliminarse, en una versión menor posterior. Durable agents indica el criterio para decidir si se mantiene.
Un durable agent es código que se ejecuta o despliega, y Collie procesa su texto como no confiable. Esta página describe a qué puede acceder un durable agent, qué impide el acceso de otros a él, qué hace Collie con su texto y qué conserva el registro de auditoría. Seguridad cubre Collie en su totalidad.
Qué puede y qué no puede hacer un durable agent
Un agente duradero pregunta y un dispositivo emparejado decide. Un agente duradero recibe lo que se responde y se le envía, así como las solicitudes del cable. Collie no le da acceso a los terminales.
| un agente duradero puede | un agente duradero no puede |
|---|---|
| Plantear una pregunta: un sí o un no, una opción, una línea de texto o un formulario breve | Responder a su propia pregunta mediante Collie |
| Listar elementos de inicio y colocar hasta cuatro botones propios en la barra | Escribir en los terminales o mostrar una pantalla |
Incluir texto, código y enlaces https:// en una conversación | Mostrar HTML sin procesar, una imagen o un enlace que no sea una dirección web |
| Elegir las palabras de su propia notificación push, dentro de los límites | Enviar más notificaciones push de las permitidas por la protección |
Solo la pulsación de una persona responde a una pregunta. La ruta de respuesta se ejecuta para un dispositivo emparejado detrás de la puerta de escritura, y ningún elemento en el puente la invoca para un agente duradero, un hook o la salida de un modelo. En el teléfono, Permitir siempre requiere una segunda pulsación. Un agente duradero que ofrece esta opción posee el permiso que requiere mayor cuidado, ya que una sola respuesta desde una herramienta hostil permitiría todas las llamadas posteriores sin confirmación.
El agente duradero, y no Collie, aplica lo que realiza una acción aprobada. Un botón del agente duradero se ejecuta con los permisos del agente duradero, y Collie solo envía la pulsación.
Un agente duradero no puede saturar la pantalla de bloqueo. Collie procesa cada pregunta una sola vez, identificada por el agente duradero y la llamada a la herramienta, y envía a lo sumo una notificación push. Permite 3 notificaciones push por conversación por minuto, 10 por host por minuto y 30 por host por hora. La notificación que correspondería a la número 31 se convierte en una única notificación de resumen, y el host no envía más hasta pasada una hora. Siempre se muestra una tarjeta.
Precaución. El mismo usuario puede responder a una pregunta en un socket. Un socket bloquea a otros usuarios, pero no a los procesos del propio usuario, lo que incluye las herramientas que ejecuta el agente. La comprobación de descendientes es la defensa propia del agente duradero, y Collie no puede determinar si un agente duradero la está ejecutando.
Con la comprobación, un agente duradero rechaza answer, send, abort, action, rename, close, reopen y starter provenientes de sí mismo, de cualquier proceso iniciado por él y de cualquier emisor que no pueda distinguir de estos. El rechazo devuelve 403 caller-refused y las lecturas permanecen abiertas. La comprobación requiere Bun en Linux, donde el SDK lee el emisor de un socket. La tabla describe lo que se aplica según el entorno donde se ejecuta el agente duradero:
| dónde se ejecuta el agente duradero | lo que aplica la comprobación de descendientes |
|---|---|
| Bun en Linux | Se ejecuta de forma predeterminada. El SDK lee el emisor de cada conexión y rechaza las acciones del agente duradero, de sus descendientes o de emisores no identificados con 403 caller-refused |
| Bun en otros sistemas, como macOS | No se puede ejecutar. openCollie se detiene al inicio con un error, a menos que el agente duradero pase callerCheck: "off". Con off, cualquier proceso del usuario puede responder |
| Node | No se puede ejecutar. El agente duradero se inicia y escribe una sola línea de advertencia. Cualquier proceso del usuario puede responder |
Aísle las herramientas del agente en un sandbox sin acceso al socket, trate la tarjeta como un aviso en lugar de un control de acceso, o ejecute el agente duradero en Bun. callerCheck: "off" es la opción propia del agente duradero para ejecutarse sin la comprobación.
El transporte por socket
Un socket privado bloquea a todos los demás usuarios, y su único control de acceso es la ruta.
ls -ld /run/user/1000 /run/user/1000/desk /run/user/1000/desk/app.sockEl socket no transporta ningún token ni encabezado Authorization. Collie solo se conecta cuando toda la ruta es privada, y realiza este recorrido antes de cada conexión, desde / hacia abajo, con lstat, de modo que no sigue ningún enlace:
| parte | lo que Collie requiere | lo que indica el motivo |
|---|---|---|
| Cada parte de la ruta, incluido el socket | No un enlace simbólico, ni siquiera uno que apunte a una ubicación válida | socket-not-private: <path> is a symlink |
| La carpeta propia del socket | Una carpeta real, propia, con modo exactamente 0700 | the socket's folder <path> has mode 0755, not 0700, o belongs to user <a>, not to <b>, o <path> is not a directory |
| Cada carpeta superior | Una carpeta real en la que el grupo y otros usuarios no puedan escribir. Se permite allí una carpeta con el sticky bit, como /tmp, pero nunca como la carpeta propia del socket. No se comprueba su propietario, porque un servicio con un /tmp privado muestra las carpetas de root como el usuario 65534 | <path> has mode 0775, so group or others can write to it |
| El socket | Un socket, propio, sin permisos para el grupo ni para otros usuarios | the path is not a socket, the socket belongs to user <a>, not to <b>, the socket has mode 0666, not 0600 |
| Una plataforma sin identificadores de usuario | Falla de forma cerrada: Collie nunca marca la conexión | this platform shows no file owner |
| Windows | Solo está disponible el transporte HTTPS: collie durable attach --socket rechaza la conexión antes de escribir | a private socket needs Unix user ids; on Windows use --url <https://...> --token-env VAR |
Una ruta que falla queda inaccesible de inmediato, sin período de gracia. collie doctor nombra la misma comprobación en su fila durable-socket e indica la solución. Una ruta sin contenido devuelve no socket at <path>, lo cual no constituye un fallo de privacidad.
Un agente duradero compilado con el SDK crea la carpeta del socket con modo 0700 si no existe. Rechaza iniciarse en una carpeta existente con otro modo. Asigna al socket el modo 0600 y elimina cualquier archivo de socket inactivo antes de escuchar.
El transporte por socket es para Linux y macOS. Windows no dispone de transporte por socket, por lo que allí se debe usar el transporte por token.
El transporte por token
Una URL y un token permiten acceder a un agente duradero en otro host, y el token constituye la barrera completa de acceso.
openssl rand -hex 32| regla | valor |
|---|---|
| Token | De 32 a 4096 bytes tras el recorte, ASCII imprimible sin espacios |
| URL | https://, o http://127.0.0.1:<port> o http://localhost:<port> para un agente duradero en esta máquina. 2048 bytes como máximo. Sin nombre de usuario, contraseña, consulta ni fragmento |
| Certificado | Se comprueba del mismo modo que cualquier cliente. Collie no dispone de ninguna opción para omitir la comprobación |
| Redirecciones | Collie no sigue ninguna, por lo que el token nunca llega a otro host |
Cualquiera que posea el token actúa como el teléfono. Puede leer cada conversación, responder a cada pregunta, enviar texto, detener un turno, cambiar el nombre o cerrar, y ejecutar un iniciador. Una conexión TLS desde internet no tiene un emisor que comprobar, por lo que aquí no existe la comprobación de descendientes. Un agente duradero al que se acceda de este modo solo debe ofrecer Permitir y Denegar, nunca permitir siempre.
El host tiene visibilidad sobre el texto. TLS finaliza en el host, por lo que este observa cada petición, incluido el token en su cabecera, y las conversaciones residen en su almacenamiento.
Collie almacena el token en texto sin formato en dos ubicaciones. sources.json lo conserva para una entrada, y una copia de seguridad o una sincronización de la carpeta de configuración lo traslada. Collie mantiene ese archivo con el modo 0600, restringe los permisos más amplios al inicio registrando una línea en su registro, y collie doctor muestra una fila sources roja para aquellos legibles por el grupo o por otros usuarios. La modalidad exclusiva de agente duradero lo conserva en .env o config.toml, y un archivo que lo contenga debe tener el modo 0600. Collie nunca imprime el token. collie durable list muestra (token set), collie doctor muestra set, <n> bytes, y ninguna línea de error o registro contiene el valor. attach lo lee a partir de la variable que nombra --token-env, por lo que no aparece en ninguna línea de comandos.
El token no caduca. Para rotarlo, proporcione el nuevo token al agente duradero antes de reiniciar Collie; de lo contrario, el teléfono indicará que el agente duradero lo ha rechazado. Un agente duradero puede aceptar un segundo token mientras se ejecuta la rotación: el ejemplo estacionado de Cloudflare acepta COLLIE_TOKEN y, mientras esté configurado, COLLIE_TOKEN_NEXT (ADR 0103). Los pasos se detallan en Tokens.
Esta es una llamada saliente que Collie efectúa a la URL configurada, y se declina sin adjuntar contenido. Cada petición incluye Authorization: Bearer <token>, la versión del protocolo en red, el ETag de la última lectura y, para una pulsación, el cuerpo de lo respondido o enviado. Una lectura es un GET sin cuerpo.
Cada sondeo a través de https es una petición que el host puede facturar, y una respuesta de tipo "sin cambios" también cuenta. Sin ningún teléfono abierto, el sondeo en reposo se ejecuta cada 10 s, por lo que Collie consulta 8640 veces al día, y cada 2 s mientras un teléfono supervisa. Un agente duradero caído o que rechace el token se consulta como máximo una vez cada 10 s, y esas peticiones también se facturan. Utilice un plan de pago para un agente duradero que Collie sondee durante todo el día.
Qué hace Collie con el texto de un agente duradero
Collie limpia cada cadena procedente de un agente duradero antes de que cualquier otra cosa la lea, y la dibuja como texto.
Un agente duradero debería enviar cadenas dentro de los límites. Collie no asume que lo haya hecho. Cada cadena pasa por tres pasos:
- Se eliminan los controles. Collie elimina los controles C0, DEL y los controles C1. Los campos que contienen varias líneas conservan el salto de línea y la tabulación: el texto de un elemento, la salida y el resumen de una llamada a herramienta, y el motivo de una pregunta.
- Se eliminan los caracteres invisibles y de dirección. Collie elimina las marcas de dirección U+200E, U+200F y U+061C, las invalidaciones y los aislamientos U+202A a U+202E y U+2066 a U+2069, los caracteres de ancho cero U+200B a U+200D, el delimitador de palabras U+2060, la marca de orden de bytes U+FEFF y los caracteres de etiqueta U+E0000 a U+E007F, que pueden contener una frase invisible completa.
- La cadena se recorta. Collie la recorta a su límite de bytes en un carácter completo y termina con
….
Una pregunta cuyo título o motivo cambió durante la limpieza lleva una marca de "Texto acortado" en su tarjeta. Se descarta una opción o un botón del cinturón que se quede sin palabras, de modo que un botón nunca queda en blanco. Un campo sin ninguna palabra se nombra mediante su id.
| texto | límite |
|---|---|
| El título de un espacio de trabajo, una pestaña, una conversación o una pregunta | 256 bytes |
| Una opción, un campo o una etiqueta inicial | 128 bytes |
| La etiqueta de un botón del cinturón | 16 caracteres |
| El motivo de una pregunta | 2048 bytes |
| La salida de una llamada a herramienta | 16384 bytes |
| El texto de un mensaje o una respuesta | 65536 bytes |
El texto de un elemento markdown o code | 32768 bytes |
| Texto que se envía a un agente duradero | 1 a 32768 bytes, rechazado antes de salir |
| Una respuesta de un agente duradero | 16 KiB para hello, 4 MiB para una instantánea |
Los id nunca se limpian ni se recortan. Un id tiene entre 1 y 128 bytes, sin caracteres de control, sin espacios en blanco y sin ninguno de /, ? o #; de lo contrario, el objeto que lo contiene se descarta.
Collie dibuja el texto como texto. Un elemento markdown muestra encabezados, listas, énfasis, fragmentos de código y enlaces, y el HTML sin procesar nunca se renderiza: una etiqueta se muestra con sus propios caracteres. Un enlace dentro de un elemento markdown solo abre una dirección web. Un elemento link requiere una dirección https:// con un host, sin nombre de usuario ni contraseña, sin espacios, caracteres de control o invisibles, y con un máximo de 2048 caracteres. De lo contrario, Collie descarta el elemento y escribe una línea en su registro para cada conversación. Las imágenes y los archivos no son elementos.
Qué se registra
Collie escribe cada escritura que realiza un teléfono hacia un agente duradero en <state-dir>/audit.log, modo 0600.
Cada línea contiene el nombre del agente duradero como session, el dispositivo emparejado y el evento:
| evento | cuando | lo que conserva la línea |
|---|---|---|
answer | Una pulsación respondió a una pregunta | El id de solicitud, la pregunta y su revisión, el id de opción o el tipo de respuesta (optionIds, text o values), y el resultado. Nunca las palabras escritas |
send | Se envió o redirigió texto | El id de solicitud, el turno o la pregunta que nombró, steer, el resultado y el texto como una vista previa de 120 caracteres |
abort | Se detuvo un turno | El id de solicitud, el turno o la pregunta que nombró, y el resultado |
action | Se pulsó un botón de la barra | El id de solicitud, el id de acción, el turno y el resultado |
starter.start | Se pulsó un elemento de inicio | El id del elemento de inicio, el id de solicitud y el resultado |
durable.reopen | Se reabrió una conversación cerrada | El id de la conversación |
space.rename | Se cambió el nombre de un espacio de trabajo | El id del espacio y el nuevo nombre |
Cerrar y cambiar el nombre de una conversación o una pestaña utiliza los eventos habituales, pane.close, pane.rename y tab.rename. COLLIE_AUDIT_CONTENT=none oculta cada cadena en el detalle excepto algunos campos específicos como el id de solicitud, por lo que la vista previa de un send se incluye en ello. El registro muestra lo sucedido a posteriori. No detiene nada.
Collie también conserva un comprobante de cada respuesta, envío, detención, pulsación de botón y elemento de inicio, sin texto escrito. Dónde almacena Collie los datos de un durable agent indica durante cuánto tiempo.