Proxy de credenciales — técnico

Cómo funciona el proxy.

Contra qué protege. Contra qué no.

Esta página está destinada a revisores de seguridad, probadores de penetración e ingenieros que evalúan el modelo de amenazas del proxy. Describe lo que hace el proxy a nivel de protocolo, dónde residen las credenciales en memoria y qué superficies de ataque permanecen.

Arquitectura

El proxy es un proxy MITM HTTPS basado en CONNECT. Un agente de IA establece HTTPS_PROXY para que apunte a él. Cuando el agente realiza una solicitud HTTPS, el proxy intercepta la conexión TLS, inspecciona las cabeceras de la solicitud en busca de referencias a credenciales, las resuelve contra la bóveda de Clavitor y reenvía la solicitud con las credenciales inyectadas a la API ascendente.

El proxy escucha en 127.0.0.1:1983 por defecto — el patrón sidecar donde el proxy y el agente comparten un host. Para despliegues compartidos (un proxy que sirve a múltiples agentes en una red privada, sidecar de contenedor a múltiples cargas de trabajo, host de proxy dedicado), la interfaz de escucha es configurable a través de CLAVITOR_PROXY_LISTEN.

illustration: unknown name=proxy-sequence

El proxy es un binario independiente de Go. Sin CGO. Toda la criptografía del protocolo Clavitor pasa a través de una implementación canónica de Rust compilada a WebAssembly y cargada a través de wazero al inicio.

Manejo de TLS

El proxy genera una CA raíz ECDSA P-256 autofirmada en la primera ejecución, persistida en el directorio del binario con modo 0600. Para cada host ascendente, se emite un certificado hoja bajo demanda, firmado por esta CA y almacenado en caché en memoria con desalojo limitado (1.000 hosts). Los certificados hoja son válidos durante 24 horas y se regeneran de forma transparente a las 23 horas para evitar la expiración en mitad de sesión.

El agente debe confiar en el certificado CA del proxy. Expórtelo con clavitor-proxy ca.

Las conexiones ascendentes utilizan TLS 1.3 como mínimo con negociación ALPN para HTTP/2 y HTTP/1.1. Se utiliza el pool de certificados del sistema para la verificación ascendente. Sin anclaje de certificados — el proxy confía en lo que confía el sistema operativo.

Credential lifecycle

Las credenciales nunca se almacenan en caché, nunca se escriben en disco y nunca se conservan más de una solicitud HTTP.

FaseDónde existe la credencialDuración
En reposo en la bóvedaCifrado AES-GCM en la base de datos de la bóvedaHasta que se elimine
En tránsito al proxyRespuesta JSON cifrada por TLS de la API de la bóvedaUn viaje de ida y vuelta HTTP
Descifrado en el proxyMemoria del proceso (cadena Go en el heap)Una solicitud HTTP
Inyectado en la solicitud ascendenteBytes cifrados por TLS en la red hacia el destino ascendenteUna solicitud HTTP

El proxy mantiene la clave de descifrado de credenciales del agente (16 bytes) en memoria durante toda su ejecución. Se carga desde la configuración cifrada del sidecar (formato CLV1) al inicio y se borra al apagar correctamente. La clave nunca sale del proceso.

La configuración del sidecar se cifra con AES-128-GCM y HMAC-SHA256 utilizando claves deterministas derivadas de una semilla estática. Esto es ofuscación, no confidencialidad — el límite de seguridad son los permisos de archivo (0600) y la posesión del archivo. El formato CLV1 es compartido entre el proxy, la CLI y la extensión del navegador.

Modos de resolución

Modo 1 — marcador de posición explícito

El agente incluye una referencia clavitor://Entry/field en una cabecera de solicitud. El proxy busca en la bóveda la entrada por nombre, la recupera, descifra el campo nombrado y sustituye el marcador de posición por el valor real.

Si la búsqueda devuelve cero o más de un resultado, el proxy devuelve 502 con un código de error estable. El marcador de posición nunca se elimina y se reenvía tal cual.

Modo 2 — coincidencia de URL

Cuando no hay un marcador de posición presente, el proxy solicita a la bóveda entradas cuyo campo URL coincida con el host ascendente. Si existe exactamente una coincidencia con una forma de campo reconocida, el proxy inyecta credenciales automáticamente.

Cero coincidencias → paso directo (sin expectativa de credencial). Múltiples coincidencias → 502 con guía de desambiguación. Forma de campo desconocida → 502.

El árbol de decisión es determinista: marcador de posición presente → resolver o fallar. Sin marcador de posición → coincidencia de URL o paso directo. No hay una ruta de respaldo silenciosa donde una resolución fallida resulte en una solicitud que vaya al destino ascendente sin credenciales.

Agent identity

Por defecto, la bóveda ve el ID de agente del propio proxy en cada solicitud. Los límites de tasa, las comprobaciones de alcance y las entradas de auditoría se atribuyen al proxy.

Cuando varios agentes comparten una instancia de proxy, el marcador de posición puede incluir un ID de agente: clavitor://agentid@Entry/field. El proxy envía este ID de agente a la bóveda, que aplica los alcances y límites de tasa de ese agente y registra el acceso contra él. El ID de agente es el valor hexadecimal de 32 caracteres que se muestra en la página de detalles del agente en la interfaz de usuario de la bóveda.

# Without agent ID — attributed to the proxy
Authorization: Bearer clavitor://OpenAI/key

# With agent ID — attributed to agent 0102030405060708090a0b0c0d0e0f10
Authorization: Bearer clavitor://0102030405060708090a0b0c0d0e0f10@OpenAI/key
DespliegueModelo de identidadAislamiento
Un proxy por agenteID de proxy = ID de agente (por defecto)Completo — binario, configuración, alcance, límites de tasa separados
Proxy compartido, sin ID de agente en la URLTodos los agentes comparten el ID del proxyAlcance y límites de tasa compartidos
Proxy compartido + agentid@ en la URLIdentidad por agenteAlcance, límites de tasa y auditoría por agente

El ID de agente en la URL no es un mecanismo de autenticación — el token CVT del proxy autentica la conexión. El ID de agente determina la atribución: qué alcances se aplican, qué límites de tasa cuentan, qué rastro de auditoría registra el acceso. La bóveda rechaza IDs de agente desconocidos con un fallo ruidoso.

Seguridad de red

Protección SSRF

Por defecto, el proxy bloquea las conexiones ascendentes a redes privadas (RFC 1918), metadatos de instancias en la nube (169.254.169.254), loopback, enlace local y rangos de NAT de grado de operador. La resolución DNS se realiza primero; todas las IPs devueltas se validan antes de establecer la conexión TCP, cerrando la ventana TOCTOU de revinculación de DNS.

Anule con CLAVITOR_PROXY_ALLOW_PRIVATE=true para agentes que acceden legítimamente a APIs privadas.

Anclaje de destino

El host de destino CONNECT se captura en el establecimiento del túnel y se utiliza durante toda la vida útil del túnel. Las solicitudes posteriores dentro del túnel no pueden redirigirse a un host diferente manipulando la cabecera Host. Una discrepancia resulta en 502.

Esto evita que un agente establezca un túnel a api.openai.com y luego envíe solicitudes a internal-service.corp.

Manejo de cabeceras

Las cabeceras hop-by-hop se eliminan de las solicitudes y respuestas según RFC 7230 §6.1: Connection, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, Proxy-Connection, TE, Trailers, Transfer-Encoding, Upgrade.

Set-Cookie se elimina de las respuestas ascendentes para evitar que los destinos implanten cookies en el cliente HTTP del agente.

Los cuerpos de solicitud y respuesta fluyen sin almacenamiento en búfer. Los cuerpos de solicitud están limitados a 64 MB por defecto (CLAVITOR_PROXY_MAX_BODY_MB). Los cuerpos de respuesta fluyen sin un límite estricto; se emite una advertencia de registro cuando Content-Length excede los 100 MB.

Field-to-header mapping

En el modo de coincidencia de URL, el proxy mapea las etiquetas de campo de la bóveda a cabeceras HTTP:

Etiqueta de campoCabecera inyectada
key, apikey, api_key, token, secret, bearer, access_tokenAuthorization: Bearer <value>
x-api-key, api-keyX-API-Key: <value>
username + password (emparejados)Authorization: Basic base64(user:pass)
Cualquier otra cosaRechazado — ERR-PROXY-052

En el modo de marcador de posición, el agente controla qué campo se resuelve y a dónde va. El mapeo anterior solo se aplica al modo de coincidencia de URL.

Error codes

Cada fallo produce un código estable ERR-PROXY-NNN. Estos códigos forman parte de la interfaz pública del proxy — los agentes y operadores pueden hacer coincidir con ellos para alertas y depuración.

RangoCategoría
001–019Configuración (configuración, inicialización, generación de CA, WASM)
020–029Ciclo de vida del demonio
030–049Resolución de marcador de posición (URIs clavitor://)
050–069Inyección por coincidencia de URL
070–089Ascendente / TLS

Los campos de identidad son inalcanzables

Las entradas de la bóveda admiten tres niveles de cifrado. Los campos cifrados por la bóveda son metadatos en texto plano. Los campos cifrados con credenciales se descifran con la clave del agente. Los campos cifrados con identidad se cifran con una clave que el servidor y el proxy nunca han visto. Solo el propietario de la bóveda, a través de su clave de hardware, puede descifrarlos.

Si un marcador de posición hace referencia a un campo cifrado con identidad, el proxy devuelve ERR-PROXY-035. Sin respaldo, sin resultado parcial. El campo es arquitectónicamente inalcanzable desde el proxy.

Contra qué no protege el proxy

El modelo de amenazas del proxy es una habilidad comprometida o una inyección de prompt que hace que un agente autenticado coseche credenciales. Los límites de tasa por agente de la bóveda, las cuotas de entradas únicas y el bloqueo de dos advertencias son las defensas primarias. El proxy añade un punto de aplicación a nivel de red donde las credenciales se resuelven por solicitud y nunca son retenidas por el agente.

Un host comprometido

El proxy se ejecuta en la misma máquina que el agente. Un atacante con acceso root puede leer la memoria del proceso, adjuntar un depurador o interceptar el tráfico de loopback. El proxy es una capa de inyección de credenciales, no un límite de seguridad de hardware.

Exfiltración de credenciales a través de la respuesta de la API

Si la API ascendente devuelve la credencial en su respuesta (por ejemplo, un endpoint "whoami"), el agente la ve. El proxy inyecta credenciales en las solicitudes, no en las respuestas. No filtra lo que regresa.

Registro

El proxy registra una línea por cada CONNECT aceptado y emite líneas de error para fallos. Nunca registra:

  • Valores de credenciales descifrados
  • URLs de solicitud completas (las cadenas de consulta pueden contener secretos — solo se registran el esquema, el host y la ruta)
  • Cuerpos de solicitud o respuesta
  • La clave de descifrado de credenciales o el contenido de la configuración del sidecar

Cuando el proxy detecta que una respuesta 400 del destino ascendente contiene palabras clave relacionadas con la autenticación (unauthorized, invalid token, etc.), registra una pista de diagnóstico que sugiere que la credencial inyectada puede estar obsoleta. La respuesta se reenvía sin cambios.

Criptografía

Toda la criptografía del protocolo Clavitor — descifrado de campos AES-GCM, derivación de claves HKDF, codificación base62, emisión de tokens CVT, empaquetado/desempaquetado de configuración CLV1 — se ejecuta dentro de un único módulo WebAssembly (clavis_crypto.wasm) cargado a través de wazero, un runtime WASM puro de Go. Sin CGO. Sin reimplementación en Go de primitivas Clavitor.

El módulo WASM se compila a partir del mismo crate de Rust (clavis-crypto) utilizado por el navegador, la CLI y las extensiones del navegador. Una única fuente de verdad, un único binario, una única superficie de auditoría.

El proxy utiliza crypto/tls de Go para la conexión TLS y crypto/ecdsa para la generación de certificados MITM. Estas son preocupaciones de transporte, no operaciones del protocolo Clavitor.

Configuration

Los secretos (clave de descifrado de credenciales, ID de agente, ID de dispositivo, URL de la bóveda) residen en la configuración cifrada del sidecar CLV1, escrita una vez durante clavitor-proxy init. Los controles operativos residen en variables de entorno:

VariablePor defectoPropósito
CLAVITOR_PROXY_LISTEN127.0.0.1Interfaz de escucha. Establecer en 0.0.0.0 para despliegues compartidos, o en una IP de interfaz específica.
CLAVITOR_PROXY_PORT1983Puerto de escucha
CLAVITOR_PROXY_ALLOW_PRIVATEfalsePermitir conexiones a redes RFC-1918 / privadas
CLAVITOR_PROXY_MAX_BODY_MB64Límite del tamaño del cuerpo de la solicitud
CLAVITOR_PROXY_WRITE_TIMEOUT300Tiempo de espera de escritura de respuesta en segundos
CLAVITOR_CONFIG(directorio del ejecutable)Anular la ruta de la configuración del sidecar

Los controles operativos no son secretos. No pertenecen a la configuración cifrada. Pertenecen a donde las herramientas de despliegue ya los gestionan — el entorno.

Revíselo usted mismo.

La criptografía es un único artefacto WASM auditable. El modelo de amenazas está documentado. Si encuentra algo que hemos pasado por alto, queremos saberlo.