Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

[Bug]: MCP browser_route with only `headers` bypasses --blocked-origins and --allowed-origins

Aperta Adatta ai principianti
#43,630 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@dhruv-techdev ci sta già lavorando.

Dal 24/10/2026.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
78/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
playwright, typescript

Direzione di ricerca

Il rapporto indica packages/playwright-core/src/tools/backend/route.ts e context.ts, dove la route che gestisce solo gli header aggira i filtri di origine del contesto. Leggi il gestore della route e l’ordine di registrazione dei filtri, quindi verifica se i test di route esistenti coprono questo caso. Il lavoro è completato quando il routing che gestisce solo gli header mantiene il comportamento previsto per le origini consentite e bloccate, aggiungendo al contempo l’header richiesto.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Version

1.64.1

Steps to reproduce
  1. Create an empty folder containing the repro.js below and this package.json:
    { "private": true, "dependencies": { "playwright": "1.64.1" } }
    
  2. npm install
  3. node repro.js

The script starts a local site that logs every request it receives. It then runs npx playwright mcp --headless --isolated --caps=network --blocked-origins=<site origin> and sends three MCP calls:

  1. browser_navigate to the blocked site
  2. browser_route with { "pattern": "**", "headers": ["X-Test: 1"] } (no body/status)
  3. browser_navigate to the blocked site again
repro.js
const { spawn } = require('child_process');
const http = require('http');

(async () => {
  // Local site that logs every request it actually receives.
  const site = http.createServer((req, res) => {
    console.log(`  [site] received ${req.url} (x-test: ${req.headers['x-test'] || 'none'})`);
    res.setHeader('content-type', 'text/html');
    res.end('<h1>reached</h1>');
  });
  await new Promise(r => site.listen(0, '127.0.0.1', r));
  const origin = `http://127.0.0.1:${site.address().port}`;

  const server = spawn('npx', ['playwright', 'mcp', '--headless', '--isolated', '--caps=network', `--blocked-origins=${origin}`],
      { stdio: ['pipe', 'pipe', 'inherit'] });

  // Minimal MCP client over stdio.
  let id = 0, buf = '';
  const pending = new Map();
  server.stdout.on('data', d => {
    buf += d;
    for (let i; (i = buf.indexOf('\n')) !== -1;) {
      const line = buf.slice(0, i); buf = buf.slice(i + 1);
      const msg = line.trim() && JSON.parse(line);
      if (msg && pending.has(msg.id)) { pending.get(msg.id)(msg); pending.delete(msg.id); }
    }
  });
  const rpc = (method, params) => new Promise(resolve => {
    pending.set(++id, resolve);
    server.stdin.write(JSON.stringify({ jsonrpc: '2.0', id, method, params }) + '\n');
  });
  const call = async (name, args) => (await rpc('tools/call', { name, arguments: args })).result.content.map(c => c.text).join('\n');
  const outcome = text => text.match(/net::ERR_\w+/)?.[0] || 'loaded ' + text.match(/Page URL: (.*)/)?.[1];

  await rpc('initialize', { protocolVersion: '2025-06-18', capabilities: {}, clientInfo: { name: 'repro', version: '1' } });
  server.stdin.write(JSON.stringify({ jsonrpc: '2.0', method: 'notifications/initialized' }) + '\n');

  console.log(`blocked origin: ${origin}`);
  console.log('1. browser_navigate        ->', outcome(await call('browser_navigate', { url: `${origin}/before` })));
  console.log('2. browser_route (headers) ->', (await call('browser_route', { pattern: '**', headers: ['X-Test: 1'] })).match(/Route added.*/)[0]);
  console.log('3. browser_navigate        ->', outcome(await call('browser_navigate', { url: `${origin}/after` })));

  server.kill();
  site.close();
})();
Expected behavior

Step 3 is still blocked (net::ERR_BLOCKED_BY_CLIENT), the same as step 1. Adding a header-only route should not change which origins the browser may request.

Actual behavior

Step 3 loads the blocked origin, and the site receives the request with the added header:

blocked origin: http://127.0.0.1:49726
1. browser_navigate        -> net::ERR_BLOCKED_BY_CLIENT
2. browser_route (headers) -> Route added for pattern: **
  [site] received /after (x-test: 1)
3. browser_navigate        -> loaded http://127.0.0.1:49726/after

--allowed-origins is bypassed the same way: with --allowed-origins=https://example.com instead, the output is identical.

Additional context

The origin filters are installed as context routes when the context is set up (context.ts#L432-L442). browser_route handlers are registered later (context.ts#L477), so they run first. The header-only branch then sends the request straight to the network (route.ts#L80):

await route.continue({ headers });

Using route.fallback({ headers }) there would keep the header change and still let the origin-filter routes run. In a plain Playwright check with an abort route registered first and a header route registered second, continue() loads the page and fallback() keeps it blocked.

I understand the flags are documented as not a security boundary. This report is only about them silently stopping working once a header-only route exists.

Environment
System:
  OS: macOS 27.0.1
  CPU: (10) arm64 Apple M4
  Memory: 450.25 MB / 16.00 GB
Binaries:
  Node: 22.23.1 - ~/.volta/tools/image/node/22.23.1/bin/node
  npm: 11.12.1 - ~/.volta/tools/image/npm/11.12.1/bin/npm
  pnpm: 11.14.0 - ~/.volta/bin/pnpm
IDEs:
  VSCode: 1.142.0 - /usr/local/bin/code
Languages:
  Bash: 3.2.57 - /bin/bash
npmPackages:
  playwright: ^1.64.1 => 1.64.1
Lingua principale
TypeScript
Stelle
98.5k
Fork
6.7k
Merge medio
15h 28m
PR unite (30g)
279

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di microsoft/playwright

Tutte le issue di microsoft/playwright

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.