---
title: "Segurança de WebMCP no Angular: o agente que chama suas tools pode ser sequestrado"
description: "Um guia de segurança para o WebMCP do Angular: por que uma tool exposta age com a autoridade do usuário, por que o JSON schema não é uma fronteira de confiança, e as defesas (validação de entrada em runtime, menor privilégio, autorização no servidor, confirmação humana) antes de expor qualquer coisa que altera dado."
deck: "Uma WebMCP tool é uma função no seu app Angular publicado que um agente de IA consegue chamar sem um humano clicar. O detalhe que ninguém projeta: esse agente lê páginas, então pode ser conduzido por conteúdo que o usuário nunca confiou, e o seu `execute` roda com a sessão do usuário. O Angular [não valida as entradas do agente](https://next.angular.dev/ai/webmcp) contra o seu schema, então a superfície de tools é um endpoint autenticado com um chamador que você não controla."
author: "André Ramos"
url: "https://andreramos.dev/pt/angular/web-mcp-security-angular/"
lang: "pt-BR"
type: "article"
---

# Segurança de WebMCP no Angular: o agente que chama suas tools pode ser sequestrado

> Uma WebMCP tool é uma função no seu app Angular publicado que um agente de IA consegue chamar sem um humano clicar. O detalhe que ninguém projeta: esse agente lê páginas, então pode ser conduzido por conteúdo que o usuário nunca confiou, e o seu `execute` roda com a sessão do usuário. O Angular [não valida as entradas do agente](https://next.angular.dev/ai/webmcp) contra o seu schema, então a superfície de tools é um endpoint autenticado com um chamador que você não controla.

## O modelo de ameaça em uma frase

Uma WebMCP tool é uma capacidade que você entregou pro agente de IA que o usuário estiver rodando, e esse agente lê páginas. O risco todo sai daí. O agente pode estar carregando instruções que pegou em algum lugar que o usuário nunca checou, uma review, um comentário, uma thread de suporte, um PDF, e essas instruções podem mandar ele chamar a sua tool `findOrder` ou `cancelSubscription`. Isso é prompt injection chegando numa função de verdade do seu app, e a tool não distingue um pedido que o usuário quis de um que uma página hostil plantou.

Agora some a parte que deixa isso afiado. O seu `execute` roda no browser do usuário, dentro da sessão do usuário, com os cookies e tokens do usuário. Um agente sequestrado chamando a sua tool age com a autoridade do usuário, com instruções que o usuário nunca deu. É essa a régua de toda decisão daqui pra frente: trate cada tool exposta como um endpoint público e autenticado cujo chamador é hostil, porque, na prática, é isso que ela é.

A mecânica de registrar tools, bootstrap, rota, service ou um Signal Form, está [no guia de setup do WebMCP](/pt/angular/web-mcp-in-angular/). Isto aqui é a camada de segurança que fica em cima, e é a parte que eu não publicaria sem.

## O schema é documentação, não fronteira de confiança

O primeiro instinto é se apoiar no `inputSchema`. Não se apoie. O Angular é explícito: ele não valida que as entradas que o agente passa de fato batem com o JSON schema declarado. O schema diz ao agente como chamar a tool; ele não barra nada. Um agente sequestrado, ou só confuso, pode entregar ao seu `execute` uma string onde você declarou número, um id de um registro que este usuário não pode ver, ou um payload três campos maior do que você esperava.

Então a validação é trabalho seu, no topo de todo `execute`, antes das entradas tocarem em qualquer coisa. Faça o parse, não assuma. Recuse o que você não declarou. Confira que o id pertence a algo que este usuário tem permissão de ler. É a mesma postura que você teria com um corpo de request de um cliente não confiável, porque o agente é exatamente isso.

*Valide dentro do execute; o schema não validou*

```ts
execute: (raw) => {
  // O Angular não impõe o inputSchema. Valide antes de tudo.
  const orderId = String(raw?.orderId ?? '');
  if (!/^[A-Z0-9-]{6,20}$/.test(orderId)) {
    return { content: [{ type: 'text', text: 'Id de pedido inválido.' }] };
  }

  const orders = inject(Orders);
  // Autorize para ESTE usuário no servidor, não só aqui no browser.
  return { content: [{ type: 'text', text: orders.summaryForCurrentUser(orderId) }] };
},
```

## Menor privilégio: leia antes de escrever, confirme antes do estrago

O controle de segurança mais barato é não expor a tool. Um agente que consulta um pedido é um risco diferente de um que cancela o pedido. Comece só-leitura. Uma tool que lê e devolve dado tem um raio de impacto limitado; uma tool que altera, cobra, apaga ou concede acesso entrega a um chamador automatizado, e talvez sequestrado, uma alavanca no seu negócio.

Quando uma tool precisa alterar dado, ponha um humano no meio. O agente pode preparar a ação, preencher o formulário, dizer qual pedido cancelar, mas uma pessoa confirma antes de efetivar. Expor um [Signal Form como tool](/pt/angular/signal-forms-as-ai-agent-tools/) encaixa direitinho aqui: o agente preenche os campos e o usuário revisa e envia, em vez de o agente chamar um `execute` que dispara e esquece.

Mantenha enxuto também o que você devolve. Uma tool que responde `findUser` e devolve o registro inteiro acabou de deixar todo campo, email, telefone, flags internas, ao alcance do agente e de quem está conduzindo ele. Devolva o mínimo que a tarefa precisa, não a linha toda.

| O que a tool faz | Decisão padrão | Trava |
|---|---|---|
| Lê dado não sensível | Exponha | Mesmo assim valide a entrada e dê escopo no usuário |
| Lê PII ou dado interno | Exponha com cuidado | Devolva o mínimo; autorize por registro |
| Altera estado (update, cancel) | Humano no meio | O agente prepara, o usuário confirma antes de efetivar |
| Dinheiro, identidade, destrutivo, concede acesso | Não exponha ainda | Deixe fora da superfície WebMCP enquanto é experimental |

## Autorize no servidor, dê escopo no cliente

Dois controles, dois lugares, e eles não se substituem. No cliente, o `exposedTo` limita quais origens podem chamar uma tool, a mesma lógica do CORS, e um `AbortSignal` derruba a tool quando o contexto dela acaba. Ponha o `exposedTo` no conjunto mais estreito que você consiga justificar. Mas é uma cerca do lado do cliente, e cerca do lado do cliente não autoriza.

A autorização que vale está no servidor. O seu `execute` roda com a sessão do usuário, então a chamada chega no seu backend já autenticada como o usuário. É justamente por isso que você revê, no servidor, se este usuário pode fazer esta coisa neste registro, a cada chamada, igual a qualquer outro request. O browser não é fronteira de confiança, e um agente dentro do browser é menos ainda.

Aproveite e fique de olho no ciclo de vida. Uma tool que sobrevive à própria rota é superfície exposta que você esqueceu que tinha. O cleanup com escopo de rota é o mecanismo pra isso, e o bug aberto de tool duplicada em volta dele é um bom lembrete de testar de verdade se as tools se desregistram quando você navega pra fora, em vez de supor que sim.

## O que eu ainda não publicaria

Tudo isso está em cima de uma API experimental sobre uma spec em rascunho. O ponto de entrada já saiu de `navigator` para `document.modelContext` no meio do ciclo, e a doc avisa que as APIs podem mudar fora de major. Pra segurança isso dobra a cautela: você está endurecendo uma superfície cujo formato pode mudar debaixo de você, então o que você expõe é o que você re-audita a cada minor do Angular, não só nos majors.

Onde eu fico: faço spike de tools só-leitura atrás de uma flag, em rotas internas ou de baixo risco, e trato o trabalho de segurança como a entrega de verdade, a validação de entrada, a autorização no servidor, o padrão de humano no meio pra qualquer coisa que escreve. Isso sobrevive aos renames da API. O que eu não colocaria no app público é uma tool que mexe em dinheiro, muda identidade ou faz algo destrutivo, enquanto o chamador é um agente que pode ser convencido de qualquer coisa e a spec por baixo ainda é rascunho. A ideia é boa. O chamador é que ainda não é confiável.

## Artefato reaproveitável: Checklist de segurança WebMCP para Angular

- Trate cada tool exposta como um endpoint público e autenticado com um chamador hostil.
- Valide toda entrada do execute em runtime; o Angular não impõe o JSON schema.
- Comece só-leitura; não exponha ainda tool que mexe em dinheiro, muda identidade ou apaga dado.
- Ponha um humano no meio em qualquer alteração: o agente prepara, o usuário confirma.
- Reveja a autorização no servidor a cada chamada; a sessão do browser não é fronteira de confiança.
- Ponha o exposedTo nas origens mais estreitas, e confirme que tool com escopo de rota se desregistra mesmo.
- Devolva o mínimo de dado que a tarefa precisa; retorno largo é caminho de vazamento.
- Re-audite a superfície exposta a cada minor do Angular, não só nos majors.

## Perguntas frequentes

### Qual é o risco específico do WebMCP, além da segurança web normal?

O chamador é um agente de IA que lê páginas, então pode estar carregando instruções injetadas de conteúdo que o usuário nunca confiou. O seu `execute` roda com a sessão do usuário, então um agente sequestrado age com a autoridade do usuário, com instruções que o usuário nunca deu.

### O JSON schema basta para validar as entradas do agente?

Não. O Angular afirma que "not provide any implicit validation that the inputs provided by an agent actually match the defined JSON schema." Valide os argumentos no topo de todo `execute` e recuse qualquer coisa que você não declarou.

### O exposedTo deixa uma tool segura?

Não. O `exposedTo` limita quais origens podem chamar a tool, como o CORS, mas é um controle do lado do cliente, não autorização. Reveja no servidor se este usuário pode executar esta ação, a cada chamada.

### Dá para expor uma tool de pagamento ou de exclusão com WebMCP?

Ainda não. Enquanto a API é experimental e o chamador pode ser sequestrado por prompt injection, deixe tools que mexem em dinheiro, mudam identidade ou apagam dado fora da superfície, ou trave atrás de confirmação humana explícita.

## Fontes consultadas

- https://next.angular.dev/ai/webmcp
- https://next.angular.dev/api/core/provideExperimentalWebMcpTools
- https://webmachinelearning.github.io/webmcp/
- https://angular.dev/ai/mcp
- https://angular.dev/guide/forms/signals/overview
- https://angular.dev/reference/releases
- https://owasp.org/www-project-top-10-for-large-language-model-applications/

## Leia também

- [WebMCP no Angular: como expor tools ao agente de IA do browser (e quando esperar)](https://andreramos.dev/pt/angular/web-mcp-in-angular/)
- [WebMCP vs Angular CLI MCP server: tools em runtime vs ajuda em dev-time](https://andreramos.dev/pt/angular/webmcp-vs-angular-cli-mcp-server/)
- [Transformando Signal Forms em tools de agente de IA](https://andreramos.dev/pt/angular/signal-forms-as-ai-agent-tools/)
