Security and Trust Between Site and Agent|INEMA.CLUB-PRO

In this lesson you will

  1. 1The six checks and which lesson each one comes from
  2. 2The dated report the audit writes
  3. 3A break planted on purpose and caught
  4. 4Your plan with dates and the next review

Goal: run the full audit (page, fallback, exposure, catalog, server, secrets), see a break get caught, and leave with the dated plan.

01Six checks

One per course lesson. Click each one.

Click each block in the diagram to see what it does.

Web Bot Auth (lesson 6) is not included: it is a policy decision, checked in the threat card and in politica-bots.md.

02The kit audit

With the two holes fixed (lessons 2 and 3). Writes kit/relatorio-seguranca.md with the date.

Terminal · audit
cd ~/projetos/formacao-webmcp-seguranca-v72/kit
node scripts/auditar.mjs; echo "saída: $?"
File · kit/scripts/auditar.mjs
// auditar.mjs — the security audit for the whole course in one run (lesson 8).
// 6 checks, each from one lesson; writes relatorio-seguranca.md with date and result.
//   1 page        checar.mjs: third-party text marked; consequential action asks for confirmation (lessons 2–3)
//   2 fallback    the page works without WebMCP (the case for most visitors)
//   3 exposure    every .html page that is not index sends Permissions-Policy with tools=() (lesson 4)
//   4 catalog     ameacas.mjs with no findings (lesson 7)
//   5 server      atacar-mcp.mjs seguro: 0 of 6 attacks get through (lesson 5)
//   6 secrets     segredos.mjs on the kit folder: 0 secrets (lesson 5)
// Usage: node scripts/auditar.mjs     (PAGINA=<folder> and CATALOGO=<file> for your copy)
// Exit 0 = 6/6; 1 = at least one failed.
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);
Example from the repository
== 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

The number of files read changes with what you add to the kit. What counts is the last line.

03A planted break

A forgotten file with a token inside the page folder. The block plants it, audits, and deletes it.

Terminal · break
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.mjs
Example from the repository
FALHA 6 segredos: 71 arquivos lidos · 1 segredo
AUDITORIA: 5/6 ok · relatório: relatorio-seguranca.md
saída: 1

Exit 1: you can use the audit as a gate before publishing (in CI or in a pre-push hook).

04Audit your site

1. Page

A local copy of your page that registers the tools and sets document.documentElement.dataset.webmcp at the end. PAGINA=[folder] changes the folder; CANARIO and CONFIRMAR change the canary and the selector of your dialog.

05The course map

Four deliverables, eight lessons. Click an exercise to see the "done when".

Lessons 1–2Text

injection + marking

3 exercises

Third-party text found and marked.

See the lesson
Lessons 3–4Brakes

confirmation + origin

3 exercises

An action asks for a person; only the right people see it.

See the lesson
Lessons 5–6Server

token + identity

3 exercises

6 attacks blocked and a bot policy.

See the lesson
Lessons 7–8Audit

threat card + test battery

3 exercises

Threat card 7/7 and audit 6/6.

See the lesson
At the end of the courseSite and server audited, with a dated report and the date of the next review.
24 exercises
Click an exercise to see what to do and the "done when".
  1. 1/4

    Text

    Accept that there is no filter and mark what comes from visitors.

  2. 2/4

    Brakes

    Confirmation with target and effect, measured exposure, tools=() where it isn't needed.

  3. 3/4

    Server

    Audience, scope, handle with an owner; signature verified.

  4. 4/4

    Audit

    Model the threats and run the battery after every change.

Each pair of lessons uses the fixed kit from the previous one.

06Generate your plan with dates

Pick a start date and how much time you have per week.

07Practice

The audit on the kit and on your site.

E22 · Kit audit

10 min

With the holes from lessons 2 and 3 fixed, run the audit block and open relatorio-seguranca.md.

Done when: AUDITORIA: 6/6 ok and saída: 0.

E23 · Break test

5 min

Run the break block.

Done when: FALHA 6 segredos, AUDITORIA: 5/6 ok and saída: 1; after the rm, the audit goes back to 6/6.

E24 · Your site and the date

30 min

Run the audit with PAGINA and CATALOGO from your site, generate the plan above, and mark the next review on your calendar.

Done when: PAGINA=[your folder] node scripts/auditar.mjs and then head -1 relatorio-seguranca.md → # Relatório de segurança — [today's date]; ls [your downloads folder]/plano-*.ics → the plan file.

08Lesson quiz

Question 1 of 4

The audit scored 5/6 with FALHA 6 segredos. What should you do before publishing?skill

09In three sentences

BatterySix checks, one run, dated report.
GateExit 1 holds back publishing until you fix it.
PaceRun it again every time you change a tool, a dependency, or the spec.

Going further