E22 · Auditoría del kit
10 minCon los fallos de las clases 2 y 3 corregidos, ejecuta el bloque auditar y abre el relatorio-seguranca.md.
Listo cuando: AUDITORIA: 6/6 ok y saída: 0.
Clase 8 · 20 min
Seis verificaciones, una por clase, en una sola ejecución y con informe fechado. Ejecutas la auditoría en el kit, plantas un secreto para ver cómo se detecta la rotura y sales con el plan de revisión: la spec cambia, las dependencias cambian, y la auditoría se ejecuta de nuevo.
Comenzar la clase
Objetivo: ejecutar la auditoría completa (página, fallback, exposición, catálogo, servidor, secretos), ver cómo se detecta una rotura y salir con el plan fechado.
Una por clase del curso. Haz clic en cada una.
Web Bot Auth (clase 6) no entra: es una decisión de política, que se revisa en la ficha y en politica-bots.md.
Con los dos fallos corregidos (clases 2 y 3). Guarda kit/relatorio-seguranca.md con la fecha.
cd ~/projetos/formacao-webmcp-seguranca-v72/kit node scripts/auditar.mjs; echo "saída: $?"
// auditar.mjs — la auditoría de seguridad de todo el curso en una sola ejecución (clase 8).
// 6 verificaciones, cada una de una clase; guarda relatorio-seguranca.md con fecha y resultado.
// 1 página checar.mjs: texto de terceros marcado; la acción con consecuencias pide confirmación (clases 2–3)
// 2 fallback la página funciona sin WebMCP (el caso de la mayoría de los visitantes)
// 3 exposição toda página .html que no es index envía Permissions-Policy con tools=() (clase 4)
// 4 catálogo ameacas.mjs sin hallazgos (clase 7)
// 5 servidor atacar-mcp.mjs seguro: 0 de 6 ataques pasan (clase 5)
// 6 segredos segredos.mjs en la carpeta del kit: 0 secretos (clase 5)
// Uso: node scripts/auditar.mjs (PAGINA=<carpeta> y CATALOGO=<archivo> para tu copia)
// Salida 0 = 6/6; 1 = alguna falló.
import { spawnSync } from 'node:child_process';
import { readdirSync, writeFileSync } from 'node:fs';
import { resolve } from 'node:path';
import { KIT, pastaPagina, servir, abrir } from '../lib/navegador.mjs';
const node = (...args) => spawnSync(process.execPath, args, { cwd: KIT, encoding: 'utf8', timeout: 240000 });
const ultima = r => (r.stdout || r.stderr || '').trim().split('\n').at(-1);
const res = [];
const anotar = (n, nome, ok, det) => { res.push({ n, nome, ok, det }); console.log(`${ok ? 'ok ' : 'FALHA'} ${n} ${nome}: ${det}`); };
const pasta = pastaPagina();
const s0 = await abrir('sem');
console.log(`== ${s0.versao.replace(' · modo: sem', '')} · ${new Date().toISOString().slice(0, 10)}`);
let r = node('scripts/checar.mjs');
anotar(1, 'página', r.status === 0, ultima(r));
const fb = await s0.page.evaluate(() => ({ modo: document.documentElement.dataset.webmcp, itens: document.querySelectorAll('li').length }));
anotar(2, 'fallback', fb.modo === 'sem' && fb.itens > 0 && !s0.erros.length, `sem WebMCP: ${fb.itens} itens na tela, ${s0.erros.length} erros de JS`);
await s0.fechar();
const srv = await servir(pasta);
const paginas = readdirSync(pasta).filter(f => f.endsWith('.html') && f !== 'index.html');
const sem = [];
for (const p of paginas) {
const pp = (await fetch(srv.url + p)).headers.get('permissions-policy') || '';
if (!/\btools=\(\)/.test(pp)) sem.push(p);
}
await srv.fechar();
anotar(3, 'exposição', sem.length === 0, sem.length ? `sem Permissions-Policy tools=(): ${sem.join(', ')}` : `${paginas.length} página(s) sem ferramenta com tools=()`);
r = node('scripts/ameacas.mjs', process.env.CATALOGO || resolve(pasta, 'ferramentas.mjs'));
anotar(4, 'catálogo', r.status === 0, ultima(r));
r = node('scripts/atacar-mcp.mjs', 'seguro');
anotar(5, 'servidor', r.status === 0, ultima(r));
r = node('scripts/segredos.mjs', '.');
anotar(6, 'segredos', r.status === 0, ultima(r));
const okN = res.filter(x => x.ok).length;
const hoje = new Date().toISOString().slice(0, 10);
writeFileSync(resolve(KIT, 'relatorio-seguranca.md'),
`# Relatório de segurança — ${hoje}\n\nSpec WebMCP: rascunho CG de 16/10/2026 · MCP 2026-07-28\n\n| # | verificação | resultado | detalhe |\n|---|---|---|---|\n` +
res.map(x => `| ${x.n} | ${x.nome} | ${x.ok ? 'ok' : 'FALHA'} | ${x.det.replace(/\|/g, '/')} |`).join('\n') +
`\n\nTotal: ${okN}/6. Rode de novo a cada mudança de ferramenta, de dependência ou da spec.\n`);
console.log(`AUDITORIA: ${okN}/6 ok · relatório: relatorio-seguranca.md`);
process.exit(okN === 6 ? 0 : 1);== Chromium 156.0.8078.4 (Playwright) · 2026-10-19 ok 1 página: RESULTADO: 0 falhas ok 2 fallback: sem WebMCP: 4 itens na tela, 0 erros de JS ok 3 exposição: 1 página(s) sem ferramenta com tools=() ok 4 catálogo: 5 ferramentas · 0 achados ok 5 servidor: passaram: 0 de 6 ok 6 segredos: 70 arquivos lidos · 0 segredos AUDITORIA: 6/6 ok · relatório: relatorio-seguranca.md saída: 0
El número de archivos leídos cambia según lo que agregues al kit. Lo que cuenta es la última línea.
Un archivo olvidado con un token dentro de la carpeta de la página. El bloque lo planta, audita y lo borra.
cd ~/projetos/formacao-webmcp-seguranca-v72/kit
printf "export const TOKEN = '%s';\n" $(openssl rand -hex 16) > pagina/config-esquecida.mjs
node scripts/auditar.mjs | tail -2; echo "saída: ${PIPESTATUS[0]}"
rm pagina/config-esquecida.mjsFALHA 6 segredos: 71 arquivos lidos · 1 segredo AUDITORIA: 5/6 ok · relatório: relatorio-seguranca.md saída: 1
Salida 1: puedes usar la auditoría como compuerta antes de publicar (en el CI o en un hook de pre-push).
Una copia local de tu página que registre las tools y marque document.documentElement.dataset.webmcp al final. PAGINA=[carpeta] cambia la carpeta; CANARIO y CONFIRMAR cambian el canario y el selector de tu diálogo.
CATALOGO=[archivo] apunta al módulo con las definiciones, si no es ferramentas.mjs.
El atacar-mcp.mjs ataca el servidor del kit. Para el tuyo, copia los seis ataques y cambia el subir() por la URL de tu servidor de prueba, con tokens de prueba de tu proveedor.
En cada tool nueva, en cada actualización de dependencias y cuando cambie la spec. WebMCP es un borrador: el origin trial llega hasta Chrome 156 (el 19 de octubre de 2026) y la API ya cambió de nombre una vez, de navigator.modelContext a document.modelContext.
Cuatro entregas, ocho clases. Haz clic en un ejercicio para ver el "listo cuando".
confirmación + origen
3 ejercicios
Una acción pide a una persona; solo debe verla quien corresponde.
Ver la claseAcepta que no hay filtro y marca lo que viene de un visitante.
Confirmación con destino y efecto, exposición medida, tools=() donde no hace falta.
Audiencia, scope, handle con dueño; firma verificada.
Modela las amenazas y ejecuta la batería con cada cambio.
Cada par de clases usa el kit corregido de la anterior.
Elige la fecha de inicio y cuánto tiempo tienes por semana.
La auditoría en el kit y en tu sitio.
Con los fallos de las clases 2 y 3 corregidos, ejecuta el bloque auditar y abre el relatorio-seguranca.md.
Listo cuando: AUDITORIA: 6/6 ok y saída: 0.
Ejecuta el bloque rotura.
Listo cuando: FALHA 6 segredos, AUDITORIA: 5/6 ok y saída: 1; después del rm, la auditoría vuelve a 6/6.
Ejecuta la auditoría con PAGINA y CATALOGO de tu sitio, genera el plan de arriba y marca en el calendario la próxima revisión.
Listo cuando: PAGINA=[tu carpeta] node scripts/auditar.mjs y después head -1 relatorio-seguranca.md → # Relatório de segurança — [fecha de hoy]; ls [tu carpeta de descargas]/plano-*.ics → el archivo del plan.
Pregunta 1 de 4
La auditoría dio 5/6 con FALHA en segredos. ¿Qué haces antes de publicar?competencia
Pregunta 2 de 4
¿Por qué la verificación 2 abre la página SIN WebMCP?
Pregunta 3 de 4
¿Cuándo hay que volver a ejecutar la auditoría?
navigator.modelContext a document.modelContext).navigator.modelContext a document.modelContext).Repasar: Auditar tu sitioPregunta 4 de 4
¿Qué clase del curso NO verifica automáticamente la auditoría?
Elige una alternativa. La explicación aparece después de tu intento.