Skip to content

Commit cf8b793

Browse files
kblokclaude
andcommitted
feat: reject BiDi URL restrictions
Implements upstream Puppeteer PR #14956. URL restrictions (blocklist/allowlist) are only enforced by the CDP target/navigation path, so we now reject them early when WebDriver BiDi is in use (including Firefox, which always defaults to BiDi). Adds a shared UrlRestrictionsValidator helper used by both LaunchAsync and ConnectAsync to keep the validation logic in one place. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1ff280a commit cf8b793

3 files changed

Lines changed: 108 additions & 10 deletions

File tree

lib/PuppeteerSharp.Tests/NetworkRestrictionTests/NetworkRestrictionsTests.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,4 +382,51 @@ public async Task ShouldThrowAnErrorForAnInvalidPattern()
382382

383383
Assert.That(error, Is.Not.Null);
384384
}
385+
386+
[Test, PuppeteerTest("BrowserConnector.test", "BrowserConnector _connectToBrowser", "should reject blocklist for WebDriver BiDi connections")]
387+
public void ShouldRejectBlocklistForWebDriverBiDiConnections()
388+
{
389+
var connectOptions = new ConnectOptions
390+
{
391+
BrowserWSEndpoint = "ws://localhost:1234",
392+
Protocol = ProtocolType.WebdriverBiDi,
393+
BlockList = ["https://example.com/*"],
394+
};
395+
396+
var error = Assert.ThrowsAsync<PuppeteerException>(async () =>
397+
await Puppeteer.ConnectAsync(connectOptions));
398+
399+
Assert.That(error.Message, Does.Contain("blocklist and allowlist are only supported with the CDP protocol"));
400+
}
401+
402+
[Test, PuppeteerTest("BrowserConnector.test", "BrowserConnector _connectToBrowser", "should reject allowlist for WebDriver BiDi connections")]
403+
public void ShouldRejectAllowlistForWebDriverBiDiConnections()
404+
{
405+
var connectOptions = new ConnectOptions
406+
{
407+
BrowserWSEndpoint = "ws://localhost:1234",
408+
Protocol = ProtocolType.WebdriverBiDi,
409+
Allowlist = ["https://example.com/*"],
410+
};
411+
412+
var error = Assert.ThrowsAsync<PuppeteerException>(async () =>
413+
await Puppeteer.ConnectAsync(connectOptions));
414+
415+
Assert.That(error.Message, Does.Contain("blocklist and allowlist are only supported with the CDP protocol"));
416+
}
417+
418+
[Test, PuppeteerTest("FirefoxLauncher.test", "FirefoxLauncher launch", "should reject blocklist for the default Firefox WebDriver BiDi protocol")]
419+
public void ShouldRejectBlocklistForDefaultFirefoxWebDriverBiDiProtocol()
420+
{
421+
var options = new LaunchOptions
422+
{
423+
Browser = SupportedBrowser.Firefox,
424+
BlockList = ["https://example.com/*"],
425+
};
426+
427+
var error = Assert.ThrowsAsync<PuppeteerException>(async () =>
428+
await Puppeteer.LaunchAsync(options));
429+
430+
Assert.That(error.Message, Does.Contain("blocklist and allowlist are only supported with the CDP protocol"));
431+
}
385432
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// * MIT License
2+
// *
3+
// * Copyright (c) Darío Kondratiuk
4+
// *
5+
// * Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// * of this software and associated documentation files (the "Software"), to deal
7+
// * in the Software without restriction, including without limitation the rights
8+
// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// * copies of the Software, and to permit persons to whom the Software is
10+
// * furnished to do so, subject to the following conditions:
11+
// *
12+
// * The above copyright notice and this permission notice shall be included in all
13+
// * copies or substantial portions of the Software.
14+
// *
15+
// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
// * SOFTWARE.
22+
23+
namespace PuppeteerSharp.Helpers
24+
{
25+
/// <summary>
26+
/// Provides validation for URL restriction options (blocklist/allowlist).
27+
/// </summary>
28+
internal static class UrlRestrictionsValidator
29+
{
30+
/// <summary>
31+
/// Validates that the URL restrictions (<paramref name="blockList"/>/<paramref name="allowList"/>)
32+
/// are supported by the given <paramref name="protocol"/>. URL restrictions are only enforced by
33+
/// the CDP target/navigation path; BiDi connections (and Firefox's default BiDi launch path) do
34+
/// not support them.
35+
/// </summary>
36+
/// <param name="protocol">The protocol that the connection or launch is using.</param>
37+
/// <param name="blockList">The blocklist URL patterns.</param>
38+
/// <param name="allowList">The allowlist URL patterns.</param>
39+
/// <exception cref="PuppeteerException">
40+
/// Thrown if both <paramref name="blockList"/> and <paramref name="allowList"/> are specified,
41+
/// or if either is specified together with <see cref="ProtocolType.WebdriverBiDi"/>.
42+
/// </exception>
43+
public static void AssertSupportedUrlRestrictions(ProtocolType protocol, string[] blockList, string[] allowList)
44+
{
45+
if (blockList != null && allowList != null)
46+
{
47+
throw new PuppeteerException("Cannot specify both blocklist and allowlist");
48+
}
49+
50+
if (protocol == ProtocolType.WebdriverBiDi && (blockList != null || allowList != null))
51+
{
52+
throw new PuppeteerException("blocklist and allowlist are only supported with the CDP protocol");
53+
}
54+
}
55+
}
56+
}

lib/PuppeteerSharp/Launcher.cs

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
using PuppeteerSharp.BrowserData;
1616
using PuppeteerSharp.Cdp;
1717
using PuppeteerSharp.Cdp.Messaging;
18+
using PuppeteerSharp.Helpers;
1819
using PuppeteerSharp.Helpers.Json;
1920
#if !CDP_ONLY
2021
using WebDriverBiDi;
@@ -62,11 +63,6 @@ public async Task<IBrowser> LaunchAsync(LaunchOptions options)
6263
throw new ArgumentNullException(nameof(options));
6364
}
6465

65-
if (options.BlockList != null && options.Allowlist != null)
66-
{
67-
throw new PuppeteerException("Cannot specify both blocklist and allowlist");
68-
}
69-
7066
EnsureSingleLaunchOrConnect();
7167
_browser = options.Browser;
7268

@@ -80,6 +76,8 @@ public async Task<IBrowser> LaunchAsync(LaunchOptions options)
8076
options.Protocol = ProtocolType.WebdriverBiDi;
8177
}
8278

79+
UrlRestrictionsValidator.AssertSupportedUrlRestrictions(options.Protocol, options.BlockList, options.Allowlist);
80+
8381
var executable = options.ExecutablePath;
8482
if (executable == null)
8583
{
@@ -277,6 +275,8 @@ public async Task<IBrowser> ConnectAsync(ConnectOptions options)
277275
throw new PuppeteerException("Exactly one of browserWSEndpoint or browserURL must be passed to puppeteer.connect");
278276
}
279277

278+
UrlRestrictionsValidator.AssertSupportedUrlRestrictions(options.Protocol, options.BlockList, options.Allowlist);
279+
280280
var browserWSEndpoint = string.IsNullOrEmpty(options.BrowserURL)
281281
? options.BrowserWSEndpoint
282282
: await GetWSEndpointAsync(options.BrowserURL).ConfigureAwait(false);
@@ -423,11 +423,6 @@ private async Task<IBrowser> ConnectBidiAsync(string browserWSEndpoint, ConnectO
423423

424424
private async Task<IBrowser> ConnectCdpAsync(string browserWSEndpoint, ConnectOptions options)
425425
{
426-
if (options.BlockList != null && options.Allowlist != null)
427-
{
428-
throw new PuppeteerException("Cannot specify both blocklist and allowlist");
429-
}
430-
431426
CdpConnection connection = null;
432427
try
433428
{

0 commit comments

Comments
 (0)