E10 · Sete casos
5 minRode o bloco exposição.
Pronto quando: 7/7 casos conferem com a spec e saída: 0.
Aula 4 · 18 min
Por padrão, só a própria página e as de mesma origem enxergam a ferramenta. Um iframe de outra origem só aparece para o topo com três consentimentos, e um cabeçalho desliga tudo. Nesta aula você mede os sete casos no Chromium e põe Permissions-Policy: tools=() nas páginas que não precisam de WebMCP.
Começar a aula
Objetivo: medir quem enxerga cada ferramenta (mesma origem, iframe, exposedTo, fromOrigins) e desligar o WebMCP com Permissions-Policy onde ele não deve existir.
Clique em cada um. Topo = a página principal; iframe = página de outra origem dentro dela.
Medido no Chromium 156.0.8078.4 com a flag de teste do WebMCP (experimental em 19/10/2026). A seção de fronteiras de origem da spec (§6.3.4) ainda é só uma nota de pendência.
O topo roda em 127.0.0.1 numa porta e o iframe em 127.0.0.1 noutra porta. Mesma máquina, porta diferente: origem diferente.
cd ~/projetos/formacao-webmcp-seguranca-v72/kit node scripts/exposicao.mjs; echo "saída: $?"
<!doctype html>
<!-- filho.html — a página dentro do iframe (pode ser de outra origem). Tenta registrar uma ferramenta.
Parâmetro (só para o laboratório): ?exposto=<origem> vira registerTool(..., { exposedTo: [<origem>] }) -->
<meta charset="utf-8">
<title>iframe</title>
<script>
(async () => {
const q = new URLSearchParams(location.search);
const mc = document.modelContext;
let estado = 'sem WebMCP';
if (mc) {
try {
const opcoes = q.get('exposto') ? { exposedTo: [q.get('exposto')] } : {};
await mc.registerTool({ name: 'ferramenta_iframe', description: 'Ferramenta do iframe.',
inputSchema: { type: 'object', properties: {} }, execute: async () => ({ ok: true }) }, opcoes);
estado = 'registrou';
} catch (e) { estado = 'recusou: ' + e.name; }
}
parent.postMessage({ iframe: estado }, '*');
})();
</script>== Chromium 156.0.8078.4 (Playwright) · modo: nativo confere 0 · iframe da MESMA origem, sem nada → vê: mesma origem é o padrão confere A · iframe de outra origem, sem allow="tools" → iframe recusado (NotAllowedError) confere B · allow="tools", sem exposedTo → topo não vê confere C · allow + exposedTo:[topo], topo sem fromOrigins → topo não vê confere D · allow + exposedTo:[topo] + fromOrigins:[iframe] → topo VÊ a ferramenta do iframe confere E · topo com Permissions-Policy: tools=() → topo e iframe recusados confere F · exposedTo com origem http:// pública → iframe recusado (SecurityError) 7/7 casos conferem com a spec saída: 0
Só no caso D o topo vê a ferramenta do iframe, e o resultado traz a origem dela (ferramenta_iframe@http://127.0.0.1:…). O agente pode usar esse campo para não confundir de quem é a ferramenta.
Se a ferramenta é só da sua página, não use exposedTo. Mesma origem já vê, e nenhuma outra precisa.
Widget de chat, anúncio, vídeo: iframe de outra origem sem allow="tools". Assim ele não registra ferramenta nenhuma no seu documento.
Login, pagamento, privacidade: mande Permissions-Policy: tools=(). A spec (§6.4.1) diz que isso protege até de script injetado ou dependência comprometida, porque vale antes de qualquer script rodar.
Ver a ferramenta não é poder tudo. O backend continua conferindo quem é a pessoa e o que ela pode, como no botão.
O servidor do kit manda tools=() na página de privacidade e nada na página principal. Ao lado, o mesmo cabeçalho em três servidores comuns.
cd ~/projetos/formacao-webmcp-seguranca-v72/kit node scripts/servir.mjs & P=$! until curl -s -o /dev/null http://127.0.0.1:8742/; do sleep 0.3; done curl -sI http://127.0.0.1:8742/privacidade.html | grep -i '^permissions-policy' curl -sI http://127.0.0.1:8742/ | grep -ci '^permissions-policy' kill $P; echo "saída: $?"
location = /privacidade.html {
add_header Permissions-Policy "tools=()" always;
}// antes do express.static
app.use('/privacidade.html', (req, res, next) => {
res.set('Permissions-Policy', 'tools=()');
next();
});/privacidade.html Permissions-Policy: tools=()
página em http://127.0.0.1:8742/ Permissions-Policy: tools=() 0 saída: 0
A privacidade manda tools=(); a principal manda 0 cabeçalhos Permissions-Policy (precisa da API).
Medir e desligar.
Rode o bloco exposição.
Pronto quando: 7/7 casos conferem com a spec e saída: 0.
Rode o bloco cabeçalho.
Pronto quando: Permissions-Policy: tools=() na privacidade e 0 na principal.
Escolha as páginas do seu site que não registram ferramenta (login, pagamento, privacidade), configure o cabeçalho no seu servidor e confira cada uma com curl -sI [endereço da página] | grep -i permissions-policy.
Pronto quando: Cada página da lista responde com permissions-policy: tools=().
Pergunta 1 de 4
Um iframe de outra origem registrou com exposedTo apontando o topo, mas o topo não o vê. O que falta?competência
Pergunta 2 de 4
Qual página deve mandar Permissions-Policy: tools=()?
Pergunta 3 de 4
O que acontece com exposedTo: ['http://exemplo.com']?
Pergunta 4 de 4
A ferramenta aparece para o topo. Isso autoriza qualquer ação dela?
Escolha uma alternativa. A explicação aparece depois da sua tentativa.