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