playwright-secure-mcp

Wrapper em torno do servidor MCP Playwright com o objetivo de manter segredos da IA

Documentação

playwright-secure-mcp

Um servidor MCP em Crystal que faz proxy de forma transparente para o servidor MCP do Playwright (@playwright/mcp) e adiciona manipulação segura de senhas. Seu objetivo: um valor de segredo resolvido nunca chega acidentalmente ao LLM.

Como funciona

  • O binário fala MCP JSON-RPC 2.0 via stdio com o cliente (o host do LLM) e inicia @playwright/mcp como um processo filho stdio, encaminhando quase todas as mensagens sem alteração.
  • Ele adiciona quatro ferramentas de segredo ao tools/list upstream: três ferramentas de descoberta que listam ou encontram itens LOGIN do 1Password utilizáveis na página atual do navegador, e browser_type_secret, que digita um campo de um item escolhido na página. Fechar o navegador (browser_close) esvazia o cache local de itens. Veja Ferramentas de segredo.
  • Cada mensagem que flui de volta ao cliente passa por um redator que substitui cada segredo resolvido — incluindo suas variantes codificadas em URL, Base64, HTML e JSON — pelo token literal «REDACTED». Os segredos são capturados onde quer que apareçam: snapshots de página, dumps de requisições de rede, mensagens de console e texto de erro.

Ferramentas de segredo

Descoberta: listar ou encontrar itens para a página atual

Três ferramentas consultam itens LOGIN do 1Password e retornam apenas aqueles utilizáveis na página atual do navegador: o proxy lê o location.href da página por conta própria (o chamador nunca fornece uma URL) e mantém um item apenas quando uma de suas URLs corresponde à página por host e prefixo de caminho. Se a URL atual não puder ser determinada, a descoberta falha com um erro. Os resultados são um array JSON de identidades de itens mais metadados de campos não secretos — vault, item, title, urls, tags, fields (id, rótulo, tipo, propósito, seção) e sections — nunca um valor de campo. Todas as três aceitam um vault opcional (ID ou nome) para limitar a busca.

FerramentaArgumentos obrigatóriosResultado
browser_list_items(nenhum)Todos os itens LOGIN utilizáveis na página atual
browser_find_items_by_nameitem (título ou ID)Itens correspondentes, filtrados para a página atual
browser_find_items_by_tagtagItens com a tag, filtrados para a página atual

Digitação: browser_type_secret

Espelha a ferramenta browser_type upstream, mas em vez de um valor literal text, recebe as coordenadas 1Password do segredo:

  • Obrigatórios: element, ref (como em browser_type), vault (ID do cofre 1Password), item (ID do item 1Password), field (ex.: username ou password)
  • Opcionais: submit, slowly (como em browser_type)

O proxy resolve o campo do item em cache (buscando o item do 1Password sob demanda quando não está em cache), descriptografa o valor localmente e emite uma chamada interna browser_type ao servidor upstream com o valor resolvido. A digitação é recusada a menos que a página atual esteja no conjunto de URLs do item (a mesma correspondência de host + prefixo de caminho da descoberta), e recusada quando a URL da página atual não puder ser determinada.

Vida útil do cache

Itens descobertos — com seus valores de campo criptografados — são armazenados em cache na memória, com escrita única. Chamar a ferramenta browser_close upstream esvazia esse cache (o fechamento ainda é encaminhado ao navegador como de costume); caso contrário, ele dura pela vida útil do processo.

Fluxo de trabalho: encontrar, depois digitar

  1. Navegue até a página de login e chame uma ferramenta de descoberta — ex.: browser_list_items — para obter os IDs vault e item de um item utilizável nessa página.
  2. Chame browser_type_secret com esses IDs e o field para digitar.

Instalação

Homebrew (macOS e Linux)

Instale a partir do tap Homebrew. A fórmula instala o binário pré-compilado da última versão do GitHub (os builds para macOS são assinados e notarizados):

brew install jochenseeber/tap/playwright-secure-mcp

Isso coloca playwright-secure-mcp no seu PATH. Ainda é necessário o CLI do 1Password (op) e um servidor MCP do Playwright — veja Requisitos.

Para compilar a partir do código-fonte, veja Compilação.

Requisitos

  • Crystal >= 1.20
  • O CLI do 1Password (op), conectado
  • pnpm ou npm para baixar @playwright/mcp sob demanda, ou um binário pré-instalado do servidor MCP do Playwright

Compilação

rake setup
rake build

rake build grava um binário de depuração em bin/<profile>-<mode>/playwright-secure-mcp (ex.: bin/darwin-arm64-system-dynamic-debug/…) e um symlink bin/playwright-secure-mcp para a compilação mais recente. Use rake "build[release]" para um binário de versão. Execute rake -T para listar todas as tarefas disponíveis.

Opções

OpçãoPadrãoSignificado
--package-managerpnpmpnpm (pnpm dlx), npm (npx -y) ou none (pré-instalado)
--mcp-versionlatestTag/intervalo de versão @playwright/mcp (ignorado quando none)
--mcp-binmcp-server-playwrightBinário pré-instalado; implica --package-manager none
--command(nenhum)Substituição explícita do comando upstream
--op-commandopBinário do CLI do 1Password
--account-from-git(nenhum)Ler o e-mail da conta de DIR/.git/config (user.email)
--account(nenhum)Conta 1Password (abreviação, e-mail de login ou ID da conta)
--account-email(nenhum)E-mail da conta 1Password
--token-tag(nenhum)Tag do item 1Password cujo campo credential contém um token de conta de serviço
--require-hardware-key(desativado)Recusar iniciar sem proteção de chave Secure Enclave/TPM
--version(nenhum)Imprimir a versão e sair
-- <args...>(nenhum)Argumentos extras encaminhados ao servidor upstream

As três opções de conta resolvem para uma única conta passada a op via --account; quando mais de uma é fornecida, a precedência é --account-from-git > --account-email > --account. Com --token-tag, a conta resolvida é usada uma vez na inicialização (op interativo) para buscar o campo credential do item marcado, e esse valor é então usado como OP_SERVICE_ACCOUNT_TOKEN para toda resolução subsequente de segredos — nesse modo, --account não é passado para op read. Sem --token-tag, cada op read usa a conta resolvida diretamente.

Configuração do cliente MCP

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

Modelo de segurança

  • O segredo resolvido viaja op → este processo → filho upstream → navegador. Ele nunca está presente em nada que o LLM enviou e nunca está presente sem redação em nada que o LLM recebe.
  • Itens revelados são armazenados em cache na memória pela vida útil do processo (ou até o navegador ser fechado via browser_close) em um cofre ofuscado: cada valor de campo é criptografado com AES-256-CBC sob uma chave de dados aleatória por processo com um IV aleatório novo por entrada. A própria chave de dados é protegida por hardware quando possível — veja Proteção da chave do cache.
  • Ressalva: o cofre é ofuscação / defesa em profundidade, não um limite de segurança. Com a camada de fallback em memória, a chave de criptografia vive na mesma memória do processo que o texto cifrado, então isso impede inspeção casual de heap, varredura estilo strings e registro acidental de texto simples — mas não um atacante com acesso total à memória do processo. Uma camada com suporte a hardware remove a chave de longa duração da memória do processo, mas veja as limitações abaixo.

Proteção da chave do cache

Na inicialização, o proxy escolhe a melhor camada de proteção disponível para a chave de dados AES-256 do cofre e registra a escolha:

  1. Secure Enclave (macOS, hardware): uma chave P-256 efêmera e não extraível é gerada dentro da Secure Enclave, e a chave de dados é encapsulada com ECIES sob ela. A chave encapsulada é desencapsulada na enclave por lote criptográfico e a chave em texto simples é zerada depois; a chave de longa duração nunca existe na memória do processo ou em disco.
  2. TPM 2.0 (Linux, hardware): a chave de dados é selada dentro do TPM da plataforma via biblioteca ESYS do tpm2-tss sobre /dev/tpmrm0 e desselada transitoriamente por lote criptográfico, depois zerada. O binário vincula tpm2-tss, que é considerado presente no host.
  3. Anel de chaves do kernel (Linux, não hardware): a chave de dados é armazenada no anel de chaves do kernel e o AES roda no kernel via um socket AF_ALG, então a chave nunca reentra na memória do processo — mas é suportada pelo kernel, não por hardware. Requer Linux ≥ 5.4.
  4. Em memória (fallback): uma chave simples por processo, com um aviso na inicialização de que a proteção com suporte a hardware não está disponível.

No Linux, a ordem é TPM → anel de chaves → em memória. Passe --require-hardware-key para falhar de forma fechada: o proxy recusa iniciar a menos que uma camada com suporte a hardware (Secure Enclave / TPM) seja inicializada. A camada do anel de chaves do kernel não satisfaz --require-hardware-key.

Requisito de implantação (macOS): a Secure Enclave só é utilizável quando o binário distribuído está assinado com a permissão apropriada (Secure Enclave / acesso ao chaveiro). Um binário não assinado não pode gerar uma chave de enclave (Security.framework falha com OSStatus -26276) e cai para a chave no processo — ou recusa iniciar sob --require-hardware-key.

Limitações:

  • A chave de dados desencapsulada está na memória do processo transitoriamente por lote criptográfico e depois é zerada com melhor esforço.
  • O texto simples do segredo descriptografado ainda transita pela memória do processo durante a redação e digitação (fora do escopo; exigiria um processo auxiliar).
  • Custo por mensagem no caminho crítico com a Secure Enclave é de ~2–20 ms (um desencapsulamento de chave por lote de mensagens).

Testes

rake spec
rake lint