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.cjs +15 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +15 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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(
|
|
1414
|
+
if (await isInternalUrlResolved(rawUrl, opts.lookupFn)) {
|
|
1408
1415
|
throw new InvalidBrowserNavigationUrlError(
|
|
1409
|
-
`Navigation to internal/loopback address blocked: "${
|
|
1416
|
+
`Navigation to internal/loopback address blocked: "${rawUrl}". Use ssrfPolicy: { allowPrivateNetwork: true } if this is intentional.`
|
|
1410
1417
|
);
|
|
1411
1418
|
}
|
|
1412
1419
|
}
|