browserclaw 0.3.1 → 0.3.2

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.js CHANGED
@@ -1387,7 +1387,20 @@ var InvalidBrowserNavigationUrlError = class extends Error {
1387
1387
  function withBrowserNavigationPolicy(ssrfPolicy) {
1388
1388
  return { ssrfPolicy };
1389
1389
  }
1390
+ var NETWORK_NAVIGATION_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:"]);
1391
+ var SAFE_NON_NETWORK_URLS = /* @__PURE__ */ new Set(["about:blank"]);
1390
1392
  async function assertBrowserNavigationAllowed(opts) {
1393
+ const rawUrl = String(opts.url ?? "").trim();
1394
+ let parsed;
1395
+ try {
1396
+ parsed = new URL(rawUrl);
1397
+ } catch {
1398
+ throw new InvalidBrowserNavigationUrlError(`Invalid URL: "${rawUrl}"`);
1399
+ }
1400
+ if (!NETWORK_NAVIGATION_PROTOCOLS.has(parsed.protocol)) {
1401
+ if (SAFE_NON_NETWORK_URLS.has(parsed.href)) return;
1402
+ throw new InvalidBrowserNavigationUrlError(`Navigation blocked: unsupported protocol "${parsed.protocol}"`);
1403
+ }
1391
1404
  const policy = opts.ssrfPolicy;
1392
1405
  if (policy?.allowPrivateNetwork) return;
1393
1406
  const allowedHostnames = [
@@ -1395,18 +1408,12 @@ async function assertBrowserNavigationAllowed(opts) {
1395
1408
  ...policy?.hostnameAllowlist ?? []
1396
1409
  ];
1397
1410
  if (allowedHostnames.length) {
1398
- let parsed;
1399
- try {
1400
- parsed = new URL(opts.url);
1401
- } catch {
1402
- throw new InvalidBrowserNavigationUrlError(`Invalid URL: "${opts.url}"`);
1403
- }
1404
1411
  const hostname = parsed.hostname.toLowerCase();
1405
1412
  if (allowedHostnames.some((h) => h.toLowerCase() === hostname)) return;
1406
1413
  }
1407
- if (await isInternalUrlResolved(opts.url, opts.lookupFn)) {
1414
+ if (await isInternalUrlResolved(rawUrl, opts.lookupFn)) {
1408
1415
  throw new InvalidBrowserNavigationUrlError(
1409
- `Navigation to internal/loopback address blocked: "${opts.url}". Use ssrfPolicy: { allowPrivateNetwork: true } if this is intentional.`
1416
+ `Navigation to internal/loopback address blocked: "${rawUrl}". Use ssrfPolicy: { allowPrivateNetwork: true } if this is intentional.`
1410
1417
  );
1411
1418
  }
1412
1419
  }