browserclaw 0.2.6 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1087,4 +1087,13 @@ declare class BrowserClaw {
1087
1087
  stop(): Promise<void>;
1088
1088
  }
1089
1089
 
1090
- export { type AriaNode, type AriaSnapshotResult, BrowserClaw, type BrowserTab, type ChromeExecutable, type ChromeKind, type ClickOptions, type ColorScheme, type ConnectOptions, type ConsoleMessage, type CookieData, CrawlPage, type DialogOptions, type DownloadResult, type FormField, type FrameEvalResult, type GeolocationOptions, type HttpCredentials, type LaunchOptions, type NetworkRequest, type PageError, type ResponseBodyResult, type RoleRefInfo, type RoleRefs, type ScreenshotOptions, type SnapshotOptions, type SnapshotResult, type SnapshotStats, type StorageKind, type TraceStartOptions, type TypeOptions, type UntrustedContentMeta, type WaitOptions };
1090
+ /**
1091
+ * Thrown when a navigation URL is blocked by SSRF policy.
1092
+ * Callers can catch this specifically to distinguish navigation blocks
1093
+ * from other errors.
1094
+ */
1095
+ declare class InvalidBrowserNavigationUrlError extends Error {
1096
+ constructor(message: string);
1097
+ }
1098
+
1099
+ export { type AriaNode, type AriaSnapshotResult, BrowserClaw, type BrowserTab, type ChromeExecutable, type ChromeKind, type ClickOptions, type ColorScheme, type ConnectOptions, type ConsoleMessage, type CookieData, CrawlPage, type DialogOptions, type DownloadResult, type FormField, type FrameEvalResult, type GeolocationOptions, type HttpCredentials, InvalidBrowserNavigationUrlError, type LaunchOptions, type NetworkRequest, type PageError, type ResponseBodyResult, type RoleRefInfo, type RoleRefs, type ScreenshotOptions, type SnapshotOptions, type SnapshotResult, type SnapshotStats, type StorageKind, type TraceStartOptions, type TypeOptions, type UntrustedContentMeta, type WaitOptions };
package/dist/index.d.ts CHANGED
@@ -1087,4 +1087,13 @@ declare class BrowserClaw {
1087
1087
  stop(): Promise<void>;
1088
1088
  }
1089
1089
 
1090
- export { type AriaNode, type AriaSnapshotResult, BrowserClaw, type BrowserTab, type ChromeExecutable, type ChromeKind, type ClickOptions, type ColorScheme, type ConnectOptions, type ConsoleMessage, type CookieData, CrawlPage, type DialogOptions, type DownloadResult, type FormField, type FrameEvalResult, type GeolocationOptions, type HttpCredentials, type LaunchOptions, type NetworkRequest, type PageError, type ResponseBodyResult, type RoleRefInfo, type RoleRefs, type ScreenshotOptions, type SnapshotOptions, type SnapshotResult, type SnapshotStats, type StorageKind, type TraceStartOptions, type TypeOptions, type UntrustedContentMeta, type WaitOptions };
1090
+ /**
1091
+ * Thrown when a navigation URL is blocked by SSRF policy.
1092
+ * Callers can catch this specifically to distinguish navigation blocks
1093
+ * from other errors.
1094
+ */
1095
+ declare class InvalidBrowserNavigationUrlError extends Error {
1096
+ constructor(message: string);
1097
+ }
1098
+
1099
+ export { type AriaNode, type AriaSnapshotResult, BrowserClaw, type BrowserTab, type ChromeExecutable, type ChromeKind, type ClickOptions, type ColorScheme, type ConnectOptions, type ConsoleMessage, type CookieData, CrawlPage, type DialogOptions, type DownloadResult, type FormField, type FrameEvalResult, type GeolocationOptions, type HttpCredentials, InvalidBrowserNavigationUrlError, type LaunchOptions, type NetworkRequest, type PageError, type ResponseBodyResult, type RoleRefInfo, type RoleRefs, type ScreenshotOptions, type SnapshotOptions, type SnapshotResult, type SnapshotStats, type StorageKind, type TraceStartOptions, type TypeOptions, type UntrustedContentMeta, type WaitOptions };
package/dist/index.js CHANGED
@@ -1378,6 +1378,12 @@ async function pressKeyViaPlaywright(opts) {
1378
1378
  ensurePageState(page);
1379
1379
  await page.keyboard.press(key, { delay: Math.max(0, Math.floor(opts.delayMs ?? 0)) });
1380
1380
  }
1381
+ var InvalidBrowserNavigationUrlError = class extends Error {
1382
+ constructor(message) {
1383
+ super(message);
1384
+ this.name = "InvalidBrowserNavigationUrlError";
1385
+ }
1386
+ };
1381
1387
  function assertSafeOutputPath(path2, allowedRoots) {
1382
1388
  if (!path2 || typeof path2 !== "string") {
1383
1389
  throw new Error("Output path is required.");
@@ -1451,7 +1457,22 @@ function extractEmbeddedIPv4(lower) {
1451
1457
  }
1452
1458
  return null;
1453
1459
  }
1460
+ function isStrictDecimalOctet(part) {
1461
+ if (!/^[0-9]+$/.test(part)) return false;
1462
+ const n = parseInt(part, 10);
1463
+ if (n < 0 || n > 255) return false;
1464
+ if (String(n) !== part) return false;
1465
+ return true;
1466
+ }
1467
+ function isUnsupportedIPv4Literal(ip) {
1468
+ if (/^[0-9]+$/.test(ip)) return true;
1469
+ const parts = ip.split(".");
1470
+ if (parts.length !== 4) return true;
1471
+ if (!parts.every(isStrictDecimalOctet)) return true;
1472
+ return false;
1473
+ }
1454
1474
  function isInternalIP(ip) {
1475
+ if (!ip.includes(":") && isUnsupportedIPv4Literal(ip)) return true;
1455
1476
  if (/^127\./.test(ip)) return true;
1456
1477
  if (/^10\./.test(ip)) return true;
1457
1478
  if (/^172\.(1[6-9]|2\d|3[01])\./.test(ip)) return true;
@@ -1507,7 +1528,7 @@ async function navigateViaPlaywright(opts) {
1507
1528
  const url = String(opts.url ?? "").trim();
1508
1529
  if (!url) throw new Error("url is required");
1509
1530
  if (!opts.allowInternal && await isInternalUrlResolved(url)) {
1510
- throw new Error(`Navigation to internal/loopback address blocked: "${url}". Set allowInternal: true if this is intentional.`);
1531
+ throw new InvalidBrowserNavigationUrlError(`Navigation to internal/loopback address blocked: "${url}". Set allowInternal: true if this is intentional.`);
1511
1532
  }
1512
1533
  const page = await getPageForTargetId({ cdpUrl: opts.cdpUrl, targetId: opts.targetId });
1513
1534
  ensurePageState(page);
@@ -1532,7 +1553,7 @@ async function listPagesViaPlaywright(opts) {
1532
1553
  async function createPageViaPlaywright(opts) {
1533
1554
  const targetUrl = (opts.url ?? "").trim() || "about:blank";
1534
1555
  if (targetUrl !== "about:blank" && !opts.allowInternal && await isInternalUrlResolved(targetUrl)) {
1535
- throw new Error(`Navigation to internal/loopback address blocked: "${targetUrl}". Set allowInternal: true if this is intentional.`);
1556
+ throw new InvalidBrowserNavigationUrlError(`Navigation to internal/loopback address blocked: "${targetUrl}". Set allowInternal: true if this is intentional.`);
1536
1557
  }
1537
1558
  const { browser } = await connectBrowser(opts.cdpUrl);
1538
1559
  const context = browser.contexts()[0] ?? await browser.newContext();
@@ -3048,6 +3069,6 @@ var BrowserClaw = class _BrowserClaw {
3048
3069
  }
3049
3070
  };
3050
3071
 
3051
- export { BrowserClaw, CrawlPage };
3072
+ export { BrowserClaw, CrawlPage, InvalidBrowserNavigationUrlError };
3052
3073
  //# sourceMappingURL=index.js.map
3053
3074
  //# sourceMappingURL=index.js.map