@plurnk/plurnk-schemes-http 1.3.12 → 1.4.0

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/Browser.d.ts CHANGED
@@ -3,15 +3,7 @@ interface PwResponse {
3
3
  statusText(): string;
4
4
  headers(): Record<string, string>;
5
5
  }
6
- interface PwRoute {
7
- request(): {
8
- url(): string;
9
- };
10
- continue(): Promise<void>;
11
- abort(): Promise<void>;
12
- }
13
6
  interface PwPage {
14
- route(pattern: string, handler: (route: PwRoute) => Promise<void>): Promise<void>;
15
7
  goto(url: string, opts: {
16
8
  waitUntil: "networkidle";
17
9
  timeout: number;
@@ -70,14 +62,13 @@ export default class Browser {
70
62
  #private;
71
63
  constructor(factory?: ChromiumFactory);
72
64
  ready(): Promise<PlaywrightMethod>;
73
- render(url: string, { workerId, signal, headers, guard, timeout }: {
65
+ render(url: string, { workerId, signal, headers, timeout }: {
74
66
  workerId: number;
75
67
  signal?: AbortSignal;
76
68
  headers?: ReadonlyArray<readonly [string, string]>;
77
- guard?: (url: string) => Promise<boolean>;
78
69
  timeout?: number;
79
70
  }): Promise<RenderResult>;
80
- closeContext(workerId: number): void;
71
+ closeContext(workerId: number): Promise<void>;
81
72
  close(): Promise<void>;
82
73
  }
83
74
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"Browser.d.ts","sourceRoot":"","sources":["../src/Browser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Browser.d.ts","sourceRoot":"","sources":["../src/Browser.ts"],"names":[],"mappings":"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"}
package/dist/Browser.js CHANGED
@@ -1,7 +1,6 @@
1
- // Browser — the headless-Chromium render foundation (SPEC §render-lifecycle),
2
- // ported from rummy.web's WebFetcher (@possumtech/rummy.web, MIT, same author). A
3
- // STANDALONE foundation, not Http-private: the render scheme drives it now,
4
- // and a future plurnk browser-troubleshooting MCP sits on the same warm pool.
1
+ // Headless-Chromium render foundation {§render-lifecycle}, derived from
2
+ // @possumtech/rummy.web's MIT WebFetcher by the same author. It is a standalone
3
+ // package surface whose initialization and shutdown follow {§handler-lifecycle}.
5
4
  //
6
5
  // Scope here is render-ONLY: navigate, let JS run + hydration settle, serialize
7
6
  // the final DOM. It returns the true rendered page; it never cleans, strips,
@@ -13,13 +12,8 @@
13
12
  // a minimal structural seam (`ChromiumEngine`) so it can be injected — fakes
14
13
  // in unit tests, and a remote CDP endpoint (Lightpanda/browserless/shared
15
14
  // chromium) swapped in via env with zero code change.
16
- // Mobile device emulation (a Pixel-5-class profile). Responsive sites serve a
17
- // lighter, less-chrome layout to a mobile viewport/UA — a general generation
18
- // hint, not a per-host rewrite (schemes-http#4). Default ON; set
19
- // PLURNK_SCHEMES_HTTP_MOBILE=0 to render as desktop (escape hatch for the tail
20
- // of sites that serve degraded/blocked mobile content). NOTE: Wikipedia gates
21
- // mobile on the domain, not the UA, so this is a no-op there — by design; its
22
- // desktop page already extracts clean.
15
+ // Mobile device emulation (a Pixel-5-class profile) is the configured default;
16
+ // PLURNK_SCHEMES_HTTP_MOBILE=0 selects a desktop context {§http-config}.
23
17
  // The ONE browser identity both acquisition paths present (render context AND
24
18
  // the byte-path fetch) — ordinary Chrome traffic, never an automated-client or
25
19
  // plurnk fingerprint. Model-supplied {User-Agent: …} target blocks override it.
@@ -31,20 +25,16 @@ const MOBILE_CONTEXT = Object.freeze({
31
25
  isMobile: true,
32
26
  hasTouch: true,
33
27
  });
34
- // Floor-set knob (schemes#31): the assembled .env.defaults floor guarantees it,
35
- // so an unset value is a config crash, not a silent default. "0" = desktop.
28
+ // Required floor-set knob; unset is a configuration failure {§http-config}.
36
29
  const mobileEmulation = () => {
37
30
  const raw = process.env.PLURNK_SCHEMES_HTTP_MOBILE;
38
31
  if (raw === undefined)
39
32
  throw new Error("Browser: required env PLURNK_SCHEMES_HTTP_MOBILE is unset — see .env.defaults");
40
33
  return raw === "0" ? undefined : MOBILE_CONTEXT;
41
34
  };
42
- // Required numeric knob — `.env.defaults` is the canonical list (schemes#31:
43
- // the file IS the docs and the daemon floor-sets it at boot; no in-code
44
- // default hides a magic number). An
45
- // unset or non-numeric value fails hard at first use, naming the var. All
46
- // three numerics are render-path-only, so a byte-fetch-only deployment never
47
- // pays them — but a rendering one must configure them.
35
+ // Required numeric lookup. `.env.defaults` owns values; call sites own when a
36
+ // value becomes necessary, and no in-code fallback hides its absence
37
+ // {§http-config}.
48
38
  export const requireNumEnv = (key) => {
49
39
  const raw = process.env[key];
50
40
  if (raw === undefined)
@@ -56,10 +46,7 @@ export const requireNumEnv = (key) => {
56
46
  };
57
47
  // Default factory: lazy-import the real chromium. The cast bridges Playwright's
58
48
  // full type to our structural view at the single trusted library boundary.
59
- const defaultFactory = async () => {
60
- process.env.PLAYWRIGHT_BROWSERS_PATH ??= "0";
61
- return (await import("playwright")).chromium;
62
- };
49
+ const defaultFactory = async () => (await import("playwright")).chromium;
63
50
  const requireBoolEnv = (key) => {
64
51
  const raw = process.env[key];
65
52
  if (raw !== "0" && raw !== "1")
@@ -115,9 +102,9 @@ export default class Browser {
115
102
  #factory;
116
103
  #browser = null;
117
104
  #launching = null;
118
- // One BrowserContext per worker — cookies / cache / storage scoped to the worker
119
- // that opened it, no cross-worker bleed. Closed by closeContext() on run end
120
- // or abort. The browser process stays warm across all of them.
105
+ // One atomically acquired BrowserContext per worker — cookies / cache /
106
+ // storage scoped to the worker that opened it, no cross-worker bleed.
107
+ // Promises make overlapping first renders share the same acquisition.
121
108
  #contexts = new Map();
122
109
  #idleTimer = null;
123
110
  // Inject a factory in tests; production lazy-imports playwright.
@@ -133,44 +120,60 @@ export default class Browser {
133
120
  // Render a URL to its final serialized DOM. Opens a page in the worker's
134
121
  // context, navigates with the settle+salvage strategy, serializes, closes
135
122
  // the page. Throws on navigation failure (the caller maps it to a status).
136
- async render(url, { workerId, signal, headers, guard, timeout = requireNumEnv("PLURNK_SCHEMES_HTTP_FETCH_TIMEOUT") }) {
123
+ async render(url, { workerId, signal, headers, timeout = requireNumEnv("PLURNK_SCHEMES_HTTP_FETCH_TIMEOUT") }) {
137
124
  const context = await this.#getContext(workerId);
138
125
  const page = await context.newPage();
139
- // SSRF interception (WebFetcher, #454): re-guard every navigation AND
140
- // subresource — a rendered public page must not reach private space.
141
- // Aborted requests surface as a nav/subresource failure, which the
142
- // caller reads as dead. Only wired when a guard is supplied (the general
143
- // READ render path passes none — unchanged).
144
- if (guard)
145
- await page.route("**", async (r) => { (await guard(r.request().url())) ? await r.continue() : await r.abort(); });
146
- // Request headers (auth/accept) apply to the navigation too, so an authed
147
- // HTML page renders authenticated. Ordered pairs collapse to a record here
148
- // — Playwright's per-page header API is single-valued (dup names not a
149
- // render concern; the byte-path fetch preserves them).
150
- if (headers && headers.length > 0)
151
- await page.setExtraHTTPHeaders(Object.fromEntries(headers));
152
- // Abort cascades by closing the page — an in-flight goto rejects with
153
- // "Target closed", surfacing promptly instead of blocking on timeout.
154
- const onAbort = () => { page.close().catch(() => { }); };
126
+ let closeFailure;
127
+ let closePromise;
128
+ // {§render-lifecycle} Abort and final settlement share one immediately
129
+ // observed close promise, so neither a duplicate call nor an unhandled
130
+ // rejection can escape the render boundary.
131
+ const closePage = () => {
132
+ closePromise ??= Promise.resolve()
133
+ .then(() => page.close())
134
+ .catch((cause) => { closeFailure = { cause }; });
135
+ return closePromise;
136
+ };
137
+ const onAbort = () => { void closePage(); };
155
138
  signal?.addEventListener("abort", onAbort, { once: true });
156
- // Already aborted before the page opened: the listener won't fire
157
- // retroactively, so close now — the navigation must not proceed.
158
- if (signal?.aborted)
159
- onAbort();
139
+ let outcome;
160
140
  try {
141
+ if (signal?.aborted) {
142
+ onAbort();
143
+ signal.throwIfAborted();
144
+ }
145
+ // Playwright's page header API is single-valued; byte acquisition preserves duplicates.
146
+ if (headers && headers.length > 0)
147
+ await page.setExtraHTTPHeaders(Object.fromEntries(headers));
161
148
  const response = await this.#safeGoto(page, url, timeout);
162
149
  const html = await page.content();
163
- return {
164
- status: response?.status() ?? 200,
165
- statusText: response?.statusText() ?? "",
166
- headers: response ? Object.entries(response.headers()) : [],
167
- html,
150
+ outcome = {
151
+ result: {
152
+ status: response?.status() ?? 200,
153
+ statusText: response?.statusText() ?? "",
154
+ headers: response ? Object.entries(response.headers()) : [],
155
+ html,
156
+ },
168
157
  };
169
158
  }
159
+ catch (cause) {
160
+ outcome = { cause };
161
+ }
170
162
  finally {
171
163
  signal?.removeEventListener("abort", onAbort);
172
- await page.close().catch(() => { });
164
+ await closePage();
165
+ }
166
+ if (outcome === undefined)
167
+ throw new Error("Browser render settled without an outcome");
168
+ if ("cause" in outcome) {
169
+ if (closeFailure !== undefined) {
170
+ throw new AggregateError([outcome.cause, closeFailure.cause], "Browser render and page close failed");
171
+ }
172
+ throw outcome.cause;
173
173
  }
174
+ if (closeFailure !== undefined)
175
+ throw closeFailure.cause;
176
+ return outcome.result;
174
177
  }
175
178
  // page.goto with the salvage path. networkidle timing out while the DOM has
176
179
  // already rendered substantive body text is the chatty-page case: the
@@ -230,27 +233,40 @@ export default class Browser {
230
233
  // PLURNK_SCHEMES_HTTP_MOBILE=0.
231
234
  async #getContext(workerId) {
232
235
  this.#touchIdle();
233
- const existing = this.#contexts.get(workerId);
234
- if (existing)
235
- return existing;
236
- const browser = await this.#getBrowser();
237
- const context = await browser.newContext(mobileEmulation());
238
- this.#contexts.set(workerId, context);
239
- return context;
236
+ let context = this.#contexts.get(workerId);
237
+ if (context === undefined) {
238
+ context = (async () => {
239
+ const browser = await this.#getBrowser();
240
+ return browser.newContext(mobileEmulation());
241
+ })();
242
+ this.#contexts.set(workerId, context);
243
+ }
244
+ try {
245
+ return await context;
246
+ }
247
+ catch (error) {
248
+ if (this.#contexts.get(workerId) === context)
249
+ this.#contexts.delete(workerId);
250
+ throw error;
251
+ }
240
252
  }
241
253
  // Drop the worker's context (run end or abort). Closing it cascades to any
242
- // in-flight page in that context. Fire-and-forget.
243
- closeContext(workerId) {
254
+ // in-flight page in that context.
255
+ async closeContext(workerId) {
244
256
  const context = this.#contexts.get(workerId);
245
257
  if (!context)
246
258
  return;
247
259
  this.#contexts.delete(workerId);
248
- context.close().catch(() => { });
260
+ await (await context).close();
249
261
  }
250
262
  #touchIdle() {
251
263
  if (this.#idleTimer)
252
264
  clearTimeout(this.#idleTimer);
253
- this.#idleTimer = setTimeout(() => { this.close().catch(() => { }); }, requireNumEnv("PLURNK_SCHEMES_HTTP_IDLE_TIMEOUT"));
265
+ this.#idleTimer = setTimeout(() => {
266
+ void this.close().catch((error) => {
267
+ console.error("Browser idle cleanup failed", { error });
268
+ });
269
+ }, requireNumEnv("PLURNK_SCHEMES_HTTP_IDLE_TIMEOUT"));
254
270
  this.#idleTimer.unref?.();
255
271
  }
256
272
  // Tear everything down: per-worker contexts then the browser. In CDP mode
@@ -262,12 +278,18 @@ export default class Browser {
262
278
  }
263
279
  const contexts = [...this.#contexts.values()];
264
280
  this.#contexts.clear();
265
- await Promise.allSettled(contexts.map((c) => c.close()));
266
- if (this.#browser) {
267
- await this.#browser.close().catch(() => { });
268
- this.#browser = null;
269
- }
281
+ const contextResults = await Promise.allSettled(contexts.map(async (context) => (await context).close()));
282
+ const browser = this.#browser;
283
+ this.#browser = null;
270
284
  this.#launching = null;
285
+ const browserResults = browser === null ? [] : await Promise.allSettled([browser.close()]);
286
+ const errors = [...contextResults, ...browserResults]
287
+ .filter((result) => result.status === "rejected")
288
+ .flatMap((result) => result.reason instanceof AggregateError
289
+ ? [...result.reason.errors]
290
+ : [result.reason]);
291
+ if (errors.length > 0)
292
+ throw new AggregateError(errors, "Browser shutdown failed");
271
293
  }
272
294
  }
273
295
  //# sourceMappingURL=Browser.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Browser.js","sourceRoot":"","sources":["../src/Browser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Browser.js","sourceRoot":"","sources":["../src/Browser.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,gFAAgF;AAChF,iFAAiF;AACjF,EAAE;AACF,gFAAgF;AAChF,6EAA6E;AAC7E,8EAA8E;AAC9E,2CAA2C;AAC3C,EAAE;AACF,+EAA+E;AAC/E,8EAA8E;AAC9E,6EAA6E;AAC7E,0EAA0E;AAC1E,sDAAsD;AAiEtD,+EAA+E;AAC/E,yEAAyE;AACzE,8EAA8E;AAC9E,+EAA+E;AAC/E,gFAAgF;AAChF,MAAM,CAAC,MAAM,UAAU,GAAG,uHAAuH,CAAC;AAElJ,MAAM,cAAc,GAAqB,MAAM,CAAC,MAAM,CAAC;IACnD,SAAS,EAAE,UAAU;IACrB,QAAQ,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;IACrC,iBAAiB,EAAE,IAAI;IACvB,QAAQ,EAAE,IAAI;IACd,QAAQ,EAAE,IAAI;CACjB,CAAC,CAAC;AACH,4EAA4E;AAC5E,MAAM,eAAe,GAAG,GAAiC,EAAE;IACvD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC;IACnD,IAAI,GAAG,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,+EAA+E,CAAC,CAAC;IACxH,OAAO,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC;AACpD,CAAC,CAAC;AAEF,8EAA8E;AAC9E,qEAAqE;AACrE,kBAAkB;AAClB,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAW,EAAU,EAAE;IACjD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,GAAG,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,+BAA+B,CAAC,CAAC;IACpG,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,YAAY,GAAG,IAAI,GAAG,kBAAkB,CAAC,CAAC;IAC/E,OAAO,CAAC,CAAC;AACb,CAAC,CAAC;AAEF,gFAAgF;AAChF,2EAA2E;AAC3E,MAAM,cAAc,GAAoB,KAAK,IAAI,EAAE,CAC/C,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,QAAqC,CAAC;AAEvE,MAAM,cAAc,GAAG,CAAC,GAAW,EAAW,EAAE;IAC5C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,qCAAqC,CAAC,CAAC;IACnH,OAAO,GAAG,KAAK,GAAG,CAAC;AACvB,CAAC,CAAC;AAQF,MAAM,aAAa,GAAG,GAAkB,EAAE;IACtC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC;IAC9D,IAAI,GAAG,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,0FAA0F,CAAC,CAAC;IACnI,IAAI,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,kDAAkD,GAAG,uDAAuD,CAAC,CAAC;IAClI,CAAC;IACD,MAAM,MAAM,GAAG,GAAuB,CAAC;IACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC;IACrE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC;IACnE,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC;IAClF,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,YAAY,MAAM,mDAAmD,CAAC,CAAC;IAC3F,CAAC;IACD,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,gBAAgB,IAAI,QAAQ,EAAE,CAAC;QAClE,MAAM,IAAI,KAAK,CAAC,yEAAyE,MAAM,EAAE,CAAC,CAAC;IACvG,CAAC;IACD,IAAI,MAAM,KAAK,QAAQ,IAAI,CAAC,OAAO,IAAI,cAAc,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,yEAAyE,MAAM,EAAE,CAAC,CAAC;IACvG,CAAC;IACD,IAAI,OAAO,IAAI,cAAc,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,2HAA2H,CAAC,CAAC;IACjJ,CAAC;IACD,IAAI,MAAM,KAAK,UAAU;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAC7C,MAAM,OAAO,GAAG,aAAa,CAAC,wCAAwC,CAAC,CAAC;IACxE,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,gBAAgB,EAAE,CAAC;QACtD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAS,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC;IACjE,CAAC;IACD,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC;IAChE,IAAI,MAAM;QAAE,IAAI,CAAC,IAAI,CAAC,mCAAmC,MAAM,EAAE,CAAC,CAAC;IACnE,OAAO;QACH,MAAM;QACN,OAAO,EAAE;YACL,QAAQ,EAAE,cAAc,CAAC,yCAAyC,CAAC;YACnE,eAAe,EAAE,cAAc,CAAC,iDAAiD,CAAC;YAClF,OAAO;YACP,IAAI;YACJ,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/B,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChD;KACJ,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,OAAO;IACxB,QAAQ,CAAkB;IAC1B,QAAQ,GAAqB,IAAI,CAAC;IAClC,UAAU,GAA8B,IAAI,CAAC;IAC7C,wEAAwE;IACxE,sEAAsE;IACtE,sEAAsE;IACtE,SAAS,GAAG,IAAI,GAAG,EAA8B,CAAC;IAClD,UAAU,GAAyC,IAAI,CAAC;IAExD,iEAAiE;IACjE,YAAY,OAAO,GAAoB,cAAc;QACjD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,KAAK;QACP,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAAC;QACnC,IAAI,MAAM,KAAK,UAAU;YAAE,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACpD,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,yEAAyE;IACzE,0EAA0E;IAC1E,2EAA2E;IAC3E,KAAK,CAAC,MAAM,CACR,GAAW,EACX,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,aAAa,CAAC,mCAAmC,CAAC,EAC2B;QAEpH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QACrC,IAAI,YAA4C,CAAC;QACjD,IAAI,YAAuC,CAAC;QAC5C,uEAAuE;QACvE,uEAAuE;QACvE,4CAA4C;QAC5C,MAAM,SAAS,GAAG,GAAkB,EAAE;YAClC,YAAY,KAAK,OAAO,CAAC,OAAO,EAAE;iBAC7B,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;iBACxB,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,GAAG,YAAY,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9D,OAAO,YAAY,CAAC;QACxB,CAAC,CAAC;QACF,MAAM,OAAO,GAAG,GAAG,EAAE,GAAG,KAAK,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3D,IAAI,OAAkE,CAAC;QACvE,IAAI,CAAC;YACD,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBAClB,OAAO,EAAE,CAAC;gBACV,MAAM,CAAC,cAAc,EAAE,CAAC;YAC5B,CAAC;YACD,wFAAwF;YACxF,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;YAC/F,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;YAC1D,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,OAAO,GAAG;gBACN,MAAM,EAAE;oBACJ,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,GAAG;oBACjC,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE;oBACxC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;oBAC3D,IAAI;iBACP;aACJ,CAAC;QACN,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,GAAG,EAAE,KAAK,EAAE,CAAC;QACxB,CAAC;gBAAS,CAAC;YACP,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,MAAM,SAAS,EAAE,CAAC;QACtB,CAAC;QACD,IAAI,OAAO,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QACxF,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;YACrB,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;gBAC7B,MAAM,IAAI,cAAc,CACpB,CAAC,OAAO,CAAC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EACnC,sCAAsC,CACzC,CAAC;YACN,CAAC;YACD,MAAM,OAAO,CAAC,KAAK,CAAC;QACxB,CAAC;QACD,IAAI,YAAY,KAAK,SAAS;YAAE,MAAM,YAAY,CAAC,KAAK,CAAC;QACzD,OAAO,OAAO,CAAC,MAAM,CAAC;IAC1B,CAAC;IAED,4EAA4E;IAC5E,sEAAsE;IACtE,wEAAwE;IACxE,wEAAwE;IACxE,oEAAoE;IACpE,2EAA2E;IAC3E,2EAA2E;IAC3E,+CAA+C;IAC/C,KAAK,CAAC,SAAS,CAAC,IAAY,EAAE,GAAW,EAAE,OAAe;QACtD,IAAI,CAAC;YACD,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,IAAI,CAAC,CAAC,GAAG,YAAY,KAAK,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc;gBAAE,MAAM,GAAG,CAAC;YACtE,MAAM,OAAO,GAAG,MAAM,IAAI;iBACrB,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC,CAAC;iBACtD,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;YACpB,IAAI,OAAO,GAAG,aAAa,CAAC,4CAA4C,CAAC;gBAAE,MAAM,GAAG,CAAC;YACrF,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IAED,0EAA0E;IAC1E,qCAAqC;IACrC,4EAA4E;IAC5E,sDAAsD;IACtD,KAAK,CAAC,WAAW;QACb,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC,QAAQ,CAAC;QACxC,IAAI,CAAC,UAAU,KAAK,CAAC,KAAK,IAAI,EAAE;YAC5B,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;YAC/B,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU;gBAAE,MAAM,IAAI,KAAK,CAAC,uFAAuF,CAAC,CAAC;YAC3I,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YACvC,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS;gBAAE,OAAO,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;YAC1F,IAAI,MAAM,CAAC,MAAM,KAAK,gBAAgB;gBAAE,OAAO,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;YACxG,OAAO,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC3C,CAAC,CAAC,EAAE,CAAC;QACL,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC;QACtC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,OAAO,CAAC,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE;YAC5B,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;gBAC5B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACrB,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;YAC3B,CAAC;QACL,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,OAAO,OAAO,CAAC;IACnB,CAAC;IAED,2EAA2E;IAC3E,yEAAyE;IACzE,gCAAgC;IAChC,KAAK,CAAC,WAAW,CAAC,QAAgB;QAC9B,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC3C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,GAAG,CAAC,KAAK,IAAI,EAAE;gBAClB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;gBACzC,OAAO,OAAO,CAAC,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;YACjD,CAAC,CAAC,EAAE,CAAC;YACL,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC1C,CAAC;QACD,IAAI,CAAC;YACD,OAAO,MAAM,OAAO,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,OAAO;gBAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9E,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;IAED,2EAA2E;IAC3E,kCAAkC;IAClC,KAAK,CAAC,YAAY,CAAC,QAAgB;QAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChC,MAAM,CAAC,MAAM,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC;IAED,UAAU;QACN,IAAI,IAAI,CAAC,UAAU;YAAE,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACnD,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBACvC,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;YAC5D,CAAC,CAAC,CAAC;QACP,CAAC,EAAE,aAAa,CAAC,kCAAkC,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC;IAC9B,CAAC;IAED,0EAA0E;IAC1E,yEAAyE;IACzE,KAAK,CAAC,KAAK;QACP,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAAC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QAAC,CAAC;QAC/E,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACvB,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC1G,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,MAAM,cAAc,GAAG,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC3F,MAAM,MAAM,GAAG,CAAC,GAAG,cAAc,EAAE,GAAG,cAAc,CAAC;aAChD,MAAM,CAAC,CAAC,MAAM,EAAmC,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC;aACjF,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,YAAY,cAAc;YACxD,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;YAC3B,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC3B,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,cAAc,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;IACvF,CAAC;CACJ"}
@@ -0,0 +1,2 @@
1
+ export declare const responseMimetype: (contentType: string | null) => string;
2
+ //# sourceMappingURL=ContentType.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContentType.d.ts","sourceRoot":"","sources":["../src/ContentType.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,gBAAgB,gBAAiB,MAAM,GAAG,IAAI,KAAG,MAO7D,CAAC"}
@@ -0,0 +1,15 @@
1
+ // HTTP response media-type normalization {§http-text-decoding}. Classification
2
+ // consumes the WHATWG MIME essence; invalid or absent metadata is not text proof.
3
+ import { MIMEType } from "node:util";
4
+ const UNKNOWN_RESPONSE_MIMETYPE = "application/octet-stream";
5
+ export const responseMimetype = (contentType) => {
6
+ if (contentType === null)
7
+ return UNKNOWN_RESPONSE_MIMETYPE;
8
+ try {
9
+ return new MIMEType(contentType).essence;
10
+ }
11
+ catch {
12
+ return UNKNOWN_RESPONSE_MIMETYPE;
13
+ }
14
+ };
15
+ //# sourceMappingURL=ContentType.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContentType.js","sourceRoot":"","sources":["../src/ContentType.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,kFAAkF;AAElF,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,MAAM,yBAAyB,GAAG,0BAA0B,CAAC;AAE7D,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,WAA0B,EAAU,EAAE;IACnE,IAAI,WAAW,KAAK,IAAI;QAAE,OAAO,yBAAyB,CAAC;IAC3D,IAAI,CAAC;QACD,OAAO,IAAI,QAAQ,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,yBAAyB,CAAC;IACrC,CAAC;AACL,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare const ERROR_DETAIL_LIMIT = "PLURNK_SCHEMES_HTTP_ERROR_DETAIL_LIMIT";
2
+ export default class ErrorDetail {
3
+ static configuredLimit(): number;
4
+ static preview(value: unknown, limit: number): string;
5
+ }
6
+ //# sourceMappingURL=ErrorDetail.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorDetail.d.ts","sourceRoot":"","sources":["../src/ErrorDetail.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,2CAA2C,CAAC;AAE3E,MAAM,CAAC,OAAO,OAAO,WAAW;IAC5B,MAAM,CAAC,eAAe,IAAI,MAAM,CAU/B;IAED,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGpD;CACJ"}
@@ -0,0 +1,19 @@
1
+ export const ERROR_DETAIL_LIMIT = "PLURNK_SCHEMES_HTTP_ERROR_DETAIL_LIMIT";
2
+ export default class ErrorDetail {
3
+ static configuredLimit() {
4
+ const raw = process.env[ERROR_DETAIL_LIMIT];
5
+ if (raw === undefined || raw === "") {
6
+ throw new Error(`${ERROR_DETAIL_LIMIT} must be set.`);
7
+ }
8
+ const limit = Number(raw);
9
+ if (!Number.isSafeInteger(limit) || limit < 0) {
10
+ throw new Error(`${ERROR_DETAIL_LIMIT} must be a non-negative integer.`);
11
+ }
12
+ return limit;
13
+ }
14
+ static preview(value, limit) {
15
+ const text = value instanceof Error ? value.message : String(value);
16
+ return text.length > limit ? `${text.slice(0, limit)}...` : text;
17
+ }
18
+ }
19
+ //# sourceMappingURL=ErrorDetail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorDetail.js","sourceRoot":"","sources":["../src/ErrorDetail.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG,wCAAwC,CAAC;AAE3E,MAAM,CAAC,OAAO,OAAO,WAAW;IAC5B,MAAM,CAAC,eAAe;QAClB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAC5C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,GAAG,kBAAkB,eAAe,CAAC,CAAC;QAC1D,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,KAAK,CAAC,GAAG,kBAAkB,kCAAkC,CAAC,CAAC;QAC7E,CAAC;QACD,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,KAAc,EAAE,KAAa;QACxC,MAAM,IAAI,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IACrE,CAAC;CACJ"}
package/dist/Guard.d.ts CHANGED
@@ -8,7 +8,7 @@ export default class Guard {
8
8
  static fetch(raw: string, init: {
9
9
  method: string;
10
10
  body: string | undefined;
11
- headers: Array<[string, string]>;
11
+ headers: ReadonlyArray<readonly [string, string]>;
12
12
  }, signal: AbortSignal): Promise<Response>;
13
13
  }
14
14
  //# sourceMappingURL=Guard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Guard.d.ts","sourceRoot":"","sources":["../src/Guard.ts"],"names":[],"mappings":"AAeA,qBAAa,iBAAkB,SAAQ,KAAK;IACxC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,YAAY,GAAG,EAAE,MAAM,EAItB;CACJ;AAED,MAAM,CAAC,OAAO,OAAO,KAAK;IAItB,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAiB1C;IAMD,OAAa,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAatD;IAOD,OAAa,KAAK,CACd,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;KAAE,EACpF,MAAM,EAAE,WAAW,GACpB,OAAO,CAAC,QAAQ,CAAC,CAkBnB;CACJ"}
1
+ {"version":3,"file":"Guard.d.ts","sourceRoot":"","sources":["../src/Guard.ts"],"names":[],"mappings":"AA+DA,qBAAa,iBAAkB,SAAQ,KAAK;IACxC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,YAAY,GAAG,EAAE,MAAM,EAKtB;CACJ;AAED,MAAM,CAAC,OAAO,OAAO,KAAK;IAGtB,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAM1C;IAID,OAAa,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CActD;IAOD,OAAa,KAAK,CACd,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;KAAE,EACrG,MAAM,EAAE,WAAW,GACpB,OAAO,CAAC,QAAQ,CAAC,CA4BnB;CACJ"}
package/dist/Guard.js CHANGED
@@ -1,59 +1,83 @@
1
- // SSRF guard for the fetch path (#456; ported from execs-search Pages.ts, which
2
- // deletes its copy as prefetch delegates here — execs #387). Every request —
3
- // the initial target AND every redirect hop — must resolve to a PUBLIC address:
4
- // a public URL redirecting into private space is the classic SSRF, so redirects
5
- // are followed MANUALLY and re-guarded per hop. The residual DNS-rebinding
6
- // sliver (the runtime re-resolves after our check) is accepted day-one, same as
7
- // the reference. Byte path only day-one; the chromium render navigation is a
8
- // separate surface tracked on #456.
1
+ // {§automatic-fetch-check} — WebFetcher's initial byte target and every
2
+ // redirect hop must resolve only to ordinary globally reachable unicast
3
+ // addresses. Redirects are followed manually so checking and Fetch-standard
4
+ // request transitions share one automatic-acquisition seam.
9
5
  import dns from "node:dns/promises";
10
6
  import net from "node:net";
11
7
  import { requireNumEnv } from "./Browser.js";
12
- // A target (or a redirect hop) that resolved to a non-public address. Http maps
13
- // it to a 403 dead-signal, distinct from a network 502.
8
+ const BLOCKED = new net.BlockList();
9
+ for (const [network, prefix] of [
10
+ ["0.0.0.0", 8],
11
+ ["10.0.0.0", 8],
12
+ ["100.64.0.0", 10],
13
+ ["127.0.0.0", 8],
14
+ ["169.254.0.0", 16],
15
+ ["172.16.0.0", 12],
16
+ ["192.0.0.0", 24],
17
+ ["192.0.2.0", 24],
18
+ ["192.88.99.0", 24],
19
+ ["192.168.0.0", 16],
20
+ ["198.18.0.0", 15],
21
+ ["198.51.100.0", 24],
22
+ ["203.0.113.0", 24],
23
+ ["224.0.0.0", 4],
24
+ ["240.0.0.0", 4],
25
+ ])
26
+ BLOCKED.addSubnet(network, prefix, "ipv4");
27
+ for (const [network, prefix] of [
28
+ ["2001::", 23],
29
+ ["2001:db8::", 32],
30
+ ["2002::", 16],
31
+ ["3fff::", 20],
32
+ ])
33
+ BLOCKED.addSubnet(network, prefix, "ipv6");
34
+ const IPV4_MAPPED = new net.BlockList();
35
+ IPV4_MAPPED.addSubnet("0.0.0.0", 0, "ipv4");
36
+ const GLOBAL_IPV6 = new net.BlockList();
37
+ GLOBAL_IPV6.addSubnet("2000::", 3, "ipv6");
38
+ const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
39
+ const BODY_HEADERS = new Set(["content-encoding", "content-language", "content-location", "content-type"]);
40
+ const AUTHORIZATION_HEADERS = new Set(["authorization"]);
41
+ const withoutHeaders = (headers, names) => headers
42
+ .filter(([name]) => !names.has(name.toLowerCase()))
43
+ .map(([name, value]) => [name, value]);
44
+ const safeUrl = (raw) => {
45
+ try {
46
+ const url = new URL(raw);
47
+ url.username = "";
48
+ url.password = "";
49
+ return url.href;
50
+ }
51
+ catch {
52
+ return raw;
53
+ }
54
+ };
55
+ // A target (or redirect hop) that automatic acquisition cannot follow.
56
+ // WebFetcher collapses this with other unavailable-page outcomes to `null`.
14
57
  export class GuardBlockedError extends Error {
15
58
  url;
16
59
  constructor(url) {
17
- super(`SSRF guard: ${url} is not a public http(s) target`);
60
+ const sanitized = safeUrl(url);
61
+ super(`Automatic fetch check: ${sanitized} is not a public http(s) target`);
18
62
  this.name = "GuardBlockedError";
19
- this.url = url;
63
+ this.url = sanitized;
20
64
  }
21
65
  }
22
66
  export default class Guard {
23
- // RFC-reserved ranges (protocol constants, never tunables): loopback,
24
- // RFC1918, link-local/metadata (169.254), CGNAT (100.64/10), unspecified,
25
- // 0.0.0.0/8; v6 ULA + link-local + v4-mapped re-checked as v4.
67
+ // Static protocol ranges, not operator policy. IPv4-mapped IPv6 is checked
68
+ // against the same v4 block list after WHATWG URL canonicalization.
26
69
  static isPublicAddress(ip) {
27
- if (net.isIP(ip) === 4) {
28
- const [a, b] = ip.split(".").map(Number);
29
- if (a === 0 || a === 10 || a === 127)
30
- return false;
31
- if (a === 169 && b === 254)
32
- return false;
33
- if (a === 172 && b >= 16 && b <= 31)
34
- return false;
35
- if (a === 192 && b === 168)
36
- return false;
37
- if (a === 100 && b >= 64 && b <= 127)
38
- return false;
39
- return true;
40
- }
41
- const v6 = ip.toLowerCase();
42
- if (v6 === "::" || v6 === "::1")
43
- return false;
44
- if (v6.startsWith("fc") || v6.startsWith("fd"))
45
- return false;
46
- if (/^fe[89ab]/.test(v6))
70
+ const family = net.isIP(ip);
71
+ if (family === 0)
47
72
  return false;
48
- const mapped = /^::ffff:(\d+\.\d+\.\d+\.\d+)$/.exec(v6);
49
- if (mapped !== null)
50
- return Guard.isPublicAddress(mapped[1]);
51
- return true;
73
+ if (family === 4)
74
+ return !BLOCKED.check(ip, "ipv4");
75
+ if (IPV4_MAPPED.check(ip, "ipv6"))
76
+ return !BLOCKED.check(ip, "ipv6");
77
+ return GLOBAL_IPV6.check(ip, "ipv6") && !BLOCKED.check(ip, "ipv6");
52
78
  }
53
- // http(s)/ws(s) only, no localhost, and EVERY resolved address public. An IP
79
+ // http(s) only, no localhost, and EVERY resolved address public. An IP
54
80
  // literal skips DNS; a hostname resolves and every A/AAAA must be public.
55
- // ws:/wss: ride the same range check — a WebSocket into private space is the
56
- // same SSRF as a fetch (the Ws scheme guards its target through here).
57
81
  static async isPublicUrl(raw) {
58
82
  let url;
59
83
  try {
@@ -62,7 +86,9 @@ export default class Guard {
62
86
  catch {
63
87
  return false;
64
88
  }
65
- if (!["http:", "https:", "ws:", "wss:"].includes(url.protocol))
89
+ if (!["http:", "https:"].includes(url.protocol))
90
+ return false;
91
+ if (url.username !== "" || url.password !== "")
66
92
  return false;
67
93
  const host = url.hostname.toLowerCase().replace(/^\[|\]$/g, "");
68
94
  if (host === "localhost" || host.endsWith(".localhost"))
@@ -77,31 +103,46 @@ export default class Guard {
77
103
  return false; // unresolvable is dead anyway
78
104
  }
79
105
  }
80
- // Guarded fetch: re-guard every hop, follow up to PLURNK_SCHEMES_HTTP_REDIRECTS
81
- // manually (floor-set knob — unset crashes). Method/body downgrade follows the
82
- // fetch spec (301/302 on a non-GET/HEAD and any 303 → GET, body dropped;
83
- // 307/308 preserve). Throws GuardBlockedError on a private hop; hands back the
84
- // final response (incl. a terminal 3xx when hops run out) otherwise.
106
+ // Automatic fetch: re-check every hop, follow up to PLURNK_SCHEMES_HTTP_REDIRECTS
107
+ // manually (floor-set knob — unset crashes). Method, body, body headers, and
108
+ // cross-origin Authorization follow WHATWG HTTP-redirect fetch. Throws
109
+ // GuardBlockedError on a non-public hop; hands back the final response
110
+ // (including a terminal redirect when hops run out) otherwise.
85
111
  static async fetch(raw, init, signal) {
86
112
  let target = raw;
87
113
  let method = init.method;
88
114
  let body = init.body;
115
+ let headers = init.headers.map(([name, value]) => [name, value]);
89
116
  let hops = requireNumEnv("PLURNK_SCHEMES_HTTP_REDIRECTS");
90
117
  while (true) {
91
- if (!(await Guard.isPublicUrl(target)))
118
+ let current;
119
+ try {
120
+ current = new URL(target);
121
+ }
122
+ catch {
92
123
  throw new GuardBlockedError(target);
93
- const response = await fetch(target, { method, body, headers: init.headers, signal, redirect: "manual" });
94
- if (response.status < 300 || response.status >= 400)
124
+ }
125
+ if (!["http:", "https:"].includes(current.protocol) || !(await Guard.isPublicUrl(current.href))) {
126
+ throw new GuardBlockedError(current.href);
127
+ }
128
+ const response = await fetch(current.href, { method, body, headers, signal, redirect: "manual" });
129
+ if (!REDIRECT_STATUSES.has(response.status))
95
130
  return response;
96
131
  const location = response.headers.get("location");
97
132
  if (location === null || hops <= 0)
98
133
  return response;
134
+ await response.body?.cancel();
99
135
  hops -= 1;
100
- target = new URL(location, target).href;
101
- if (response.status === 303 || ((response.status === 301 || response.status === 302) && method !== "GET" && method !== "HEAD")) {
136
+ const next = new URL(location, current);
137
+ if (((response.status === 301 || response.status === 302) && method === "POST")
138
+ || (response.status === 303 && method !== "GET" && method !== "HEAD")) {
102
139
  method = "GET";
103
140
  body = undefined;
141
+ headers = withoutHeaders(headers, BODY_HEADERS);
104
142
  }
143
+ if (current.origin !== next.origin)
144
+ headers = withoutHeaders(headers, AUTHORIZATION_HEADERS);
145
+ target = next.href;
105
146
  }
106
147
  }
107
148
  }