ISMS Copilot Docs

Redacción SSE: Defendiendo los prompts del sistema de LLM en arquitecturas de streaming

Por Better ISMS — febrero de 2026

Por Better ISMS — febrero de 2026

Si estás construyendo un producto sobre un LLM, tu prompt del sistema es tu lógica de producto. Cuando alguien lo extrae, obtiene tu razonamiento, tus salvaguardas, tu ventaja competitiva — todo. Y si estás transmitiendo respuestas mediante Eventos Enviados por el Servidor (SSE, por sus siglas en inglés) (que probablemente estés haciendo), defenderte contra la extracción es más difícil de lo que piensas.

Esta publicación describe la redacción SSE, una técnica que desarrollamos para ISMS Copilot para detectar y neutralizar fugas del prompt del sistema durante la transmisión. Compartimos la arquitectura para que otros que construyen productos con LLM puedan implementar algo similar.

El Problema

La mayoría de las aplicaciones de LLM transmiten respuestas al cliente fragmento por fragmento utilizando SSE. Cada fragmento se envía en el momento en que se genera. No hay un paso de "revisar la respuesta completa antes de enviarla" — eso derrotaría el propósito del streaming.

Esto crea una brecha de seguridad: si un prompt de jailbreak convence al modelo de volcar sus instrucciones del sistema, el contenido ya está siendo enviado al cliente antes de que puedas detenerlo. Para cuando te des cuenta de lo ocurrido, el usuario ya ha visto cientos o miles de caracteres de tu prompt del sistema.

El filtrado tradicional de salida no funciona aquí. No puedes almacenar en búfer toda la respuesta (la latencia arruina la experiencia del usuario), y no puedes revisar cada pequeño fragmento de forma aislada (un fragmento de 5 palabras no parece un prompt del sistema).

Para estrategias generales de prevención de jailbreaks, consulta Mitigar Jailbreaks e Inyecciones de Prompt. La redacción SSE es una medida de defensa en profundidad para cuando esas prevenciones fallan.

La Arquitectura

La redacción SSE funciona en cuatro etapas.

Etapa 1 — Creación de huellas. Antes de que ocurra cualquier conversación, extraes un conjunto de frases huella de tu prompt del sistema. Estas son cadenas distintivas que solo aparecerían juntas si el modelo está reproduciendo sus instrucciones. Quieres frases distribuidas en diferentes secciones de tu prompt — definiciones de roles, nombres de restricciones, reglas de comportamiento. El número de huellas y el umbral de coincidencia son parámetros ajustables que mantienes en secreto.

Etapa 2 — Acumulación y verificación periódica. A medida que el modelo transmite fragmentos, un guardián acumula el texto completo de la respuesta. A intervalos regulares (medidos por conteo de caracteres, no por fragmento), verifica el contenido acumulado contra el conjunto de huellas. Verificar cada fragmento sería un desperdicio — las huellas necesitan suficiente contexto circundante para coincidir de manera significativa.

Etapa 3 — Propagación de errores. Cuando el guardián detecta suficientes coincidencias de huellas, lanza un error tipado (en nuestro caso, SystemPromptLeakError). Aquí es donde reside la sutileza. En una arquitectura de streaming, el bucle de procesamiento de fragmentos típicamente tiene un bloque try/catch para manejar datos SSE malformados (JSON incorrecto, formatos inesperados). Ese bloque catch genérico se tragará tu error de seguridad si no tienes cuidado. Necesitas una cláusula de guardia que vuelva a lanzar tu tipo de error específico antes de que se ejecute el manejador genérico:

catch (e) {
  if (e instanceof Error && e.name === 'SystemPromptLeakError') throw e;
  // el manejo de errores genérico continúa para todo lo demás
}

Esto es una línea de código, pero sin ella, todo el sistema de detección es inerte. El guardián se activa, registra la detección y la transmisión continúa felizmente entregando tu prompt del sistema al atacante. Aprendimos esto de la manera difícil — nuestro guardián detectaba fugas perfectamente en los registros mientras no hacía absolutamente nada para detenerlas.

Etapa 4 — Redacción. Una vez que el error se propaga hasta el controlador de la transmisión, este envía un evento SSE de redacción al cliente. El cliente reemplaza lo que ya se había renderizado con un mensaje de rechazo. El servidor simultáneamente reemplaza el contenido almacenado en la base de datos para que la fuga no persista.

Lo que ve el usuario

El atacante ve brevemente contenido transmitido parcialmente — tal vez unos segundos de contenido — luego toda la respuesta es reemplazada por un mensaje de rechazo genérico. La experiencia es: aparece texto, luego desaparece y es reemplazado. El contenido parcial que vislumbraron está incompleto y mezclado con texto de respuesta normal, lo que lo hace poco confiable para la extracción.

Aprende más sobre cómo funcionan los mensajes de rechazo en Manejar Rechazos y Límites de Alcance.

El Problema del Bloque Catch

Esto merece énfasis porque es el tipo de error que pasa todas las pruebas pero falla en producción.

Si estás utilizando generadores asíncronos para el streaming, tu bucle de análisis SSE probablemente se vea así:

for (const line of sseLines) {
  try {
    const data = JSON.parse(line);
    const text = extractText(data);
    await onChunkCallback(text);  // <-- el guardián se ejecuta aquí
    yield text;
  } catch (e) {
    console.error('Error al analizar el fragmento:', e);
    // continúa con la siguiente línea
  }
}

La callback está dentro del bloque try. Si el guardián lanza una excepción, el catch la registra como un error de análisis y continúa. En nuestro caso, el guardián detectó la fuga correctamente en cada fragmento después del umbral — los registros mostraban que SystemPromptLeakError se activaba repetidamente — mientras que la transmisión se completaba normalmente, guardaba el prompt filtrado completo en la base de datos y lo enviaba al cliente.

La complicación adicional: este comportamiento depende del entorno de ejecución. En Node.js, los errores de generadores asíncronos de callbacks pueden propagarse de manera diferente que en Deno. Nuestras pruebas pasaron en el entorno de prueba de Node.js porque el error se propagó por casualidad. En producción con Deno, fue tragado. Si estás construyendo esto, prueba en tu entorno de ejecución de producción real, no solo en tu ejecutor de pruebas.

Decisiones de Diseño que Vale la Pena Mencionar

¿Por qué huellas en lugar de similitud de embeddings o coincidencia exacta? Las huellas son rápidas (coincidencia de cadenas), deterministas (sin llamadas a modelos) y robustas contra la paráfrasis. El modelo rara vez parafrasea su propio prompt del sistema durante una fuga — lo reproduce de manera textual o casi textual. La similitud de embeddings añade latencia por verificación e introduce riesgo de falsos positivos en contenido legítimo de cumplimiento. La coincidencia exacta de subcadenas es demasiado frágil (diferencias de espacio en blanco, formato).

¿Por qué verificar periódicamente en lugar de cada fragmento? Los fragmentos son pequeños (a menudo de 3 a 10 caracteres). Un solo fragmento no tiene significado para la detección. Acumular hasta un umbral mínimo antes de verificar reduce la computación y asegura suficiente contexto para una coincidencia confiable.

¿Por qué no almacenar en búfer toda la respuesta? Almacenar en búfer arruina la experiencia de streaming. Los usuarios esperan ver el texto aparecer en tiempo real. Un búfer de 2 segundos es perceptible; almacenar en búfer una respuesta completa de más de 4000 caracteres es inaceptable. La redacción SSE preserva el streaming en tiempo real para el 99.99% de las conversaciones e interviene solo durante una fuga activa.

¿Por qué reemplazar también en la base de datos? Si solo redactas en el cliente, el contenido filtrado persiste en el servidor. Cualquiera con acceso a la base de datos, cualquier función de exportación, cualquier punto final de historial de conversaciones lo expondría.

Lo que Esto No Resuelve

La redacción SSE es una medida de defensa en profundidad, no una solución mágica.

No evita que el modelo intente filtrar. Eso es lo que manejan las propias instrucciones de tu prompt del sistema (instrucciones explícitas de rechazo, secciones de restricción). La redacción SSE es la red de seguridad para cuando esas instrucciones fallan — y con suficiente creatividad, los jailbreaks ocasionalmente tienen éxito.

No evita fugas más cortas que el umbral de detección. Si alguien persuade al modelo para que revele una sola oración del prompt del sistema, el conteo de huellas no alcanzará el umbral. Esto es por diseño — estás equilibrando entre detectar extracciones completas (alta confianza) y marcar menciones parciales (alto riesgo de falsos positivos).

El atacante sí ve contenido parcial antes de la redacción. Durante unos segundos, el texto transmitido es visible. Esto es inherente a las arquitecturas de streaming. El contenido parcial está incompleto y carece de estructura, pero no es una exposición cero.

La redacción SSE complementa, pero no reemplaza, las mejores prácticas de seguridad del prompt del sistema. Consulta Prompts del Sistema y Proteger el Espacio de Trabajo e Instrucciones Personalizadas para medidas de seguridad fundamentales.

Lista de Verificación de Implementación

Si quieres construir esto para tu propio producto con LLM:

  1. Extrae frases huella de tu prompt del sistema — elige cadenas distintivas que abarquen secciones.
  2. Construye un guardián que acumule contenido transmitido y verifique periódicamente contra las huellas.
  3. Define una clase de error tipado con un nombre distintivo para la detección de fugas.
  4. Audita cada bloque catch en tu pipeline de streaming — añade guardias de re-lanzamiento para tu tipo de error.
  5. En tu controlador de transmisión, maneja el error enviando un evento de redacción y reemplazando el contenido almacenado.
  6. En el cliente, maneja el evento de redacción reemplazando el contenido renderizado con un mensaje de rechazo.
  7. Prueba en tu entorno de ejecución de producción, no solo en tu ejecutor de pruebas.
  8. Mantén tus huellas, umbrales e intervalos de verificación en secreto.

Reflexión Final

La parte más difícil de esto no fue el algoritmo de detección — fue un error de una línea en un bloque catch que desactivó silenciosamente todo el sistema. La seguridad en arquitecturas de streaming falla a nivel de plumbing, no a nivel de algoritmo. Si estás construyendo características de seguridad para LLM, rastrea el camino completo del error desde la detección hasta la acción visible para el usuario, y verifícalo en tu entorno de producción real.

Para una visión más amplia de las prácticas de seguridad de IA en ISMS Copilot, consulta Resumen de Seguridad de IA y Uso Responsable.

Better ISMS construye herramientas de cumplimiento para equipos de seguridad de la información. ISMS Copilot es nuestro asistente de IA para ISO 27001, SOC 2, GDPR y marcos relacionados.

On this page