Skip to content

Commit eb39131

Browse files
authored
fix(mcp): --allowed/blocked-origins accept origins not hosts (#37408)
1 parent 6e84386 commit eb39131

File tree

2 files changed

+64
-7
lines changed

2 files changed

+64
-7
lines changed

packages/playwright/src/mcp/browser/context.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,12 @@ export class Context {
177177
await context.route('**', route => route.abort('blockedbyclient'));
178178

179179
for (const origin of this.config.network.allowedOrigins)
180-
await context.route(`*://${origin}/**`, route => route.continue());
180+
await context.route(originOrHostGlob(origin), route => route.continue());
181181
}
182182

183183
if (this.config.network?.blockedOrigins?.length) {
184184
for (const origin of this.config.network.blockedOrigins)
185-
await context.route(`*://${origin}/**`, route => route.abort('blockedbyclient'));
185+
await context.route(originOrHostGlob(origin), route => route.abort('blockedbyclient'));
186186
}
187187
}
188188

@@ -234,6 +234,18 @@ export class Context {
234234
}
235235
}
236236

237+
function originOrHostGlob(originOrHost: string) {
238+
try {
239+
const url = new URL(originOrHost);
240+
// localhost:1234 will parse as protocol 'localhost:' and 'null' origin.
241+
if (url.origin !== 'null')
242+
return `${url.origin}/**`;
243+
} catch {
244+
}
245+
// Support for legacy host-only mode.
246+
return `*://${originOrHost}/**`;
247+
}
248+
237249
export class InputRecorder {
238250
private _context: Context;
239251
private _browserContext: playwright.BrowserContext;

tests/mcp/request-blocking.spec.ts

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,23 @@ test('default to allow all', async ({ server, client }) => {
3636
expect(result).toContain('content:PPP');
3737
});
3838

39-
test('blocked works', async ({ startClient }) => {
39+
test('blocked works (hostname)', async ({ startClient }) => {
4040
const { client } = await startClient({
4141
args: ['--blocked-origins', 'microsoft.com;example.com;playwright.dev']
4242
});
4343
const result = await fetchPage(client, 'https://example.com/');
4444
expect(result).toMatch(BLOCK_MESSAGE);
4545
});
4646

47-
test('allowed works', async ({ server, startClient }) => {
47+
test('blocked works (origin)', async ({ startClient }) => {
48+
const { client } = await startClient({
49+
args: ['--blocked-origins', 'https://microsoft.com;https://example.com;https://playwright.dev']
50+
});
51+
const result = await fetchPage(client, 'https://example.com/');
52+
expect(result).toMatch(BLOCK_MESSAGE);
53+
});
54+
55+
test('allowed works (hostname)', async ({ server, startClient }) => {
4856
server.setContent('/ppp', 'content:PPP', 'text/html');
4957
const { client } = await startClient({
5058
args: ['--allowed-origins', `microsoft.com;${new URL(server.PREFIX).host};playwright.dev`]
@@ -53,7 +61,16 @@ test('allowed works', async ({ server, startClient }) => {
5361
expect(result).toContain('content:PPP');
5462
});
5563

56-
test('blocked takes precedence', async ({ startClient }) => {
64+
test('allowed works (origin)', async ({ server, startClient }) => {
65+
server.setContent('/ppp', 'content:PPP', 'text/html');
66+
const { client } = await startClient({
67+
args: ['--allowed-origins', `https://microsoft.com;${new URL(server.PREFIX).origin};https://playwright.dev`]
68+
});
69+
const result = await fetchPage(client, server.PREFIX + '/ppp');
70+
expect(result).toContain('content:PPP');
71+
});
72+
73+
test('blocked takes precedence (hostname)', async ({ startClient }) => {
5774
const { client } = await startClient({
5875
args: [
5976
'--blocked-origins', 'example.com',
@@ -64,19 +81,47 @@ test('blocked takes precedence', async ({ startClient }) => {
6481
expect(result).toMatch(BLOCK_MESSAGE);
6582
});
6683

67-
test('allowed without blocked blocks all non-explicitly specified origins', async ({ startClient }) => {
84+
test('blocked takes precedence (origin)', async ({ startClient }) => {
85+
const { client } = await startClient({
86+
args: [
87+
'--blocked-origins', 'https://example.com',
88+
'--allowed-origins', 'https://example.com',
89+
],
90+
});
91+
const result = await fetchPage(client, 'https://example.com/');
92+
expect(result).toMatch(BLOCK_MESSAGE);
93+
});
94+
95+
test('allowed without blocked blocks all non-explicitly specified origins (hostname)', async ({ startClient }) => {
6896
const { client } = await startClient({
6997
args: ['--allowed-origins', 'playwright.dev'],
7098
});
7199
const result = await fetchPage(client, 'https://example.com/');
72100
expect(result).toMatch(BLOCK_MESSAGE);
73101
});
74102

75-
test('blocked without allowed allows non-explicitly specified origins', async ({ server, startClient }) => {
103+
test('allowed without blocked blocks all non-explicitly specified origins (origin)', async ({ startClient }) => {
104+
const { client } = await startClient({
105+
args: ['--allowed-origins', 'https://playwright.dev'],
106+
});
107+
const result = await fetchPage(client, 'https://example.com/');
108+
expect(result).toMatch(BLOCK_MESSAGE);
109+
});
110+
111+
test('blocked without allowed allows non-explicitly specified origins (hostname)', async ({ server, startClient }) => {
76112
server.setContent('/ppp', 'content:PPP', 'text/html');
77113
const { client } = await startClient({
78114
args: ['--blocked-origins', 'example.com'],
79115
});
80116
const result = await fetchPage(client, server.PREFIX + '/ppp');
81117
expect(result).toContain('content:PPP');
82118
});
119+
120+
test('blocked without allowed allows non-explicitly specified origins (origin)', async ({ server, startClient }) => {
121+
server.setContent('/ppp', 'content:PPP', 'text/html');
122+
const { client } = await startClient({
123+
args: ['--blocked-origins', 'https://example.com'],
124+
});
125+
const result = await fetchPage(client, server.PREFIX + '/ppp');
126+
expect(result).toContain('content:PPP');
127+
});

0 commit comments

Comments
 (0)