playwright-secure-mcp

Wrapper alrededor del servidor MCP de Playwright con el objetivo de mantener los secretos fuera del alcance de la IA.

Documentación

playwright-secure-mcp

Un servidor MCP en Crystal que actúa como proxy transparente del servidor MCP de Playwright (@playwright/mcp) y añade manejo seguro de contraseñas. Su objetivo: un valor secreto resuelto nunca llega accidentalmente al LLM.

Cómo funciona

  • El binario habla MCP JSON-RPC 2.0 sobre stdio con el cliente (el host LLM) y lanza @playwright/mcp como un proceso hijo stdio, reenviando casi todos los mensajes sin cambios.
  • Añade cuatro herramientas secretas al tools/list upstream: tres herramientas de descubrimiento que listan o encuentran elementos LOGIN de 1Password utilizables en la página actual del navegador, y browser_type_secret, que escribe un campo de un elemento elegido en la página. Cerrar el navegador (browser_close) vacía la caché local de elementos. Ver Herramientas secretas.
  • Cada mensaje que fluye de vuelta al cliente pasa por un redactor que reemplaza cada secreto resuelto — incluyendo sus variantes codificadas en URL, Base64, escapadas en HTML y escapadas en JSON — con el token literal «REDACTED». Los secretos se detectan dondequiera que aparezcan: instantáneas de página, volcados de solicitudes de red, mensajes de consola y texto de error.

Herramientas secretas

Descubrimiento: listar o encontrar elementos para la página actual

Tres herramientas buscan elementos LOGIN de 1Password y devuelven solo aquellos utilizables en la página actual del navegador: el proxy lee el location.href de la página por sí mismo (el llamador nunca proporciona una URL) y conserva un elemento solo cuando una de sus URLs coincide con la página por host y prefijo de ruta. Si la URL actual no se puede determinar, el descubrimiento falla con un error. Los resultados son un arreglo JSON de identidades de elementos más metadatos de campos no secretos — vault, item, title, urls, tags, fields (id, label, type, purpose, section), y sections — nunca un valor de campo. Los tres aceptan un vault opcional (ID o nombre) para acotar la búsqueda.

HerramientaArgumentos requeridosResultado
browser_list_items(ninguno)Todos los elementos LOGIN utilizables en la página actual
browser_find_items_by_nameitem (título o ID)Elementos coincidentes, filtrados a la página actual
browser_find_items_by_tagtagElementos que llevan la etiqueta, filtrados a la página actual

Escritura: browser_type_secret

Refleja la herramienta browser_type upstream, pero en lugar de un valor literal text toma las coordenadas 1Password del secreto:

  • Requeridos: element, ref (como en browser_type), vault (ID de bóveda 1Password), item (ID de elemento 1Password), field (p. ej. username o password)
  • Opcionales: submit, slowly (como en browser_type)

El proxy resuelve el campo desde el elemento en caché (obteniendo el elemento de 1Password bajo demanda cuando no está en caché), descifra el valor localmente y emite una llamada interna browser_type al servidor upstream con el valor resuelto. La escritura se rechaza a menos que la página actual esté en el conjunto de URLs del elemento (la misma coincidencia de host + prefijo de ruta que el descubrimiento), y se rechaza cuando la URL de la página actual no se puede determinar.

Duración de la caché

Los elementos descubiertos — con sus valores de campo cifrados — se almacenan en caché en memoria, de una sola escritura. Llamar a la herramienta browser_close upstream vacía esta caché (el cierre aún se reenvía al navegador como de costumbre); de lo contrario, vive durante la vida del proceso.

Flujo de trabajo: encontrar, luego escribir

  1. Navega a la página de inicio de sesión, luego llama a una herramienta de descubrimiento — p. ej. browser_list_items — para obtener los IDs vault y item de un elemento utilizable en esa página.
  2. Llama a browser_type_secret con esos IDs y el field para escribir.

Instalación

Homebrew (macOS y Linux)

Instala desde el tap de Homebrew. La fórmula instala el binario precompilado desde la última versión de GitHub (las compilaciones de macOS están firmadas y notarizadas):

brew install jochenseeber/tap/playwright-secure-mcp

Esto coloca playwright-secure-mcp en tu PATH. Aún necesita la CLI de 1Password (op) y un servidor MCP de Playwright — ver Requisitos.

Para compilar desde el código fuente en su lugar, ver Compilación.

Requisitos

  • Crystal >= 1.20
  • La CLI de 1Password (op), con sesión iniciada
  • pnpm o npm para descargar @playwright/mcp bajo demanda, o un binario de servidor MCP de Playwright preinstalado

Compilación

rake setup
rake build

rake build escribe un binario de depuración en bin/<profile>-<mode>/playwright-secure-mcp (p. ej. bin/darwin-arm64-system-dynamic-debug/…) y un enlace simbólico bin/playwright-secure-mcp a la última compilación. Usa rake "build[release]" para un binario de lanzamiento. Ejecuta rake -T para listar todas las tareas disponibles.

Opciones

OpciónPredeterminadoSignificado
--package-managerpnpmpnpm (pnpm dlx), npm (npx -y) o none (preinstalado)
--mcp-versionlatest@playwright/mcp etiqueta/rango de versión (ignorado cuando none)
--mcp-binmcp-server-playwrightBinario preinstalado; implica --package-manager none
--command(ninguno)Anulación explícita del comando upstream
--op-commandopBinario de la CLI de 1Password
--account-from-git(ninguno)Leer el correo de la cuenta desde DIR/.git/config (user.email)
--account(ninguno)Cuenta de 1Password (abreviatura, correo de inicio de sesión o ID de cuenta)
--account-email(ninguno)Correo de la cuenta de 1Password
--token-tag(ninguno)Etiqueta de elemento de 1Password cuyo campo credential contiene un token de cuenta de servicio
--require-hardware-key(desactivado)Rechazar iniciar sin protección de clave Secure Enclave/TPM
--version(ninguno)Imprimir la versión y salir
-- <args...>(ninguno)Argumentos adicionales reenviados al servidor upstream

Las tres opciones de cuenta se resuelven en una sola cuenta pasada a op mediante --account; cuando se proporciona más de una, la precedencia es --account-from-git > --account-email > --account. Con --token-tag, la cuenta resuelta se usa una vez al inicio (op interactivo) para obtener el campo credential del elemento etiquetado, y ese valor se usa luego como OP_SERVICE_ACCOUNT_TOKEN para toda resolución de secretos posterior — en ese modo, --account no se pasa a op read. Sin --token-tag, cada op read usa la cuenta resuelta directamente.

Configuración del cliente MCP

{
    "mcpServers": {
        "playwright": {
            "command": "/path/to/bin/playwright-secure-mcp",
            "args": ["--", "--headless"]
        }
    }
}

Modelo de seguridad

  • El secreto resuelto viaja op → este proceso → hijo upstream → navegador. Nunca está presente en nada que el LLM haya enviado, y nunca está presente sin redactar en nada que el LLM reciba.
  • Los elementos revelados se almacenan en caché en memoria durante la vida del proceso (o hasta que el navegador se cierra mediante browser_close) en una bóveda ofuscada: cada valor de campo está cifrado con AES-256-CBC bajo una clave de datos aleatoria por proceso con un IV aleatorio nuevo por entrada. La clave de datos en sí está protegida por hardware cuando es posible — ver Protección de la clave de caché.
  • Advertencia: la bóveda es ofuscación / defensa en profundidad, no un límite de seguridad. Con el nivel de respaldo en memoria, la clave de cifrado vive en la misma memoria del proceso que el texto cifrado, por lo que derrota la inspección casual del montón, el escaneo estilo strings y el registro accidental de texto plano — pero no a un atacante con acceso completo a la memoria del proceso. Un nivel respaldado por hardware elimina la clave de larga duración de la memoria del proceso, pero ver las limitaciones a continuación.

Protección de la clave de caché

Al inicio, el proxy elige el mejor nivel de protección disponible para la clave de datos AES-256 de la bóveda y registra la elección:

  1. Secure Enclave (macOS, hardware): se genera una clave P-256 efímera y no extraíble dentro del Secure Enclave, y la clave de datos se envuelve con ECIES bajo ella. La clave envuelta se desenvuelve en el enclave por lote criptográfico y la clave en texto plano se pone a cero después; la clave de larga duración nunca existe en la memoria del proceso ni en disco.
  2. TPM 2.0 (Linux, hardware): la clave de datos se sella dentro del TPM de la plataforma mediante la biblioteca ESYS de tpm2-tss sobre /dev/tpmrm0 y se desella transitoriamente por lote criptográfico, luego se pone a cero. El binario enlaza tpm2-tss, que se asume presente en el host.
  3. Llavero del kernel (Linux, no hardware): la clave de datos se almacena en el llavero del kernel y AES se ejecuta en el kernel mediante un socket AF_ALG, por lo que la clave nunca vuelve a entrar en la memoria del proceso — pero está respaldada por el kernel, no por hardware. Requiere Linux ≥ 5.4.
  4. En memoria (respaldo): una clave simple por proceso, con una advertencia de inicio de que la protección respaldada por hardware no está disponible.

En Linux, el orden es TPM → llavero → en memoria. Pasa --require-hardware-key para fallar de forma segura: el proxy se niega a iniciar a menos que se inicialice un nivel respaldado por hardware (Secure Enclave / TPM). El nivel de llavero del kernel no satisface --require-hardware-key.

Requisito de implementación (macOS): el Secure Enclave solo se puede usar cuando el binario distribuido está firmado con el entitlement apropiado (acceso a Secure Enclave / llavero). Un binario sin firmar no puede generar una clave de enclave (Security.framework falla con OSStatus -26276) y cae al respaldo de la clave en el proceso — o se niega a iniciar bajo --require-hardware-key.

Limitaciones:

  • La clave de datos desenvuelta está en la memoria del proceso transitoriamente por lote criptográfico, luego se pone a cero con el mejor esfuerzo.
  • El texto plano del secreto descifrado aún transita por la memoria del proceso durante la redacción y la escritura (fuera de alcance; requeriría un sidecar).
  • El costo de ruta crítica por mensaje con el Secure Enclave es de ~2–20 ms (un desenvuelto de clave por lote de mensajes).

Pruebas

rake spec
rake lint