autotel-devtools 7.0.0 → 8.1.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.
@@ -1,8 +1,8 @@
1
- import { D as DevtoolsServer, L as LogData, T as TraceData, b as DevtoolsData } from '../exporter-DjLkU621.cjs';
2
- export { d as DevtoolsServerOptions, a as DevtoolsSpanExporter, E as ErrorGroup, c as ErrorOccurrence, M as MetricData, S as SpanData } from '../exporter-DjLkU621.cjs';
1
+ import { D as DevtoolsServer, L as LogData, T as TraceData, b as DevtoolsData } from '../exporter-De6p4iAD.cjs';
2
+ export { d as DevtoolsServerOptions, a as DevtoolsSpanExporter, E as ErrorGroup, c as ErrorOccurrence, M as MetricData, S as SpanData } from '../exporter-De6p4iAD.cjs';
3
3
  export { DevtoolsLogExporter } from './log-exporter.cjs';
4
4
  export { DevtoolsRemoteExporter, DevtoolsRemoteExporterOptions } from './remote-exporter.cjs';
5
- export { E as ErrorAggregator } from '../error-aggregator-CbLiuot4.cjs';
5
+ export { E as ErrorAggregator } from '../error-aggregator-D1Mr221Y.cjs';
6
6
  import { Server } from 'node:http';
7
7
  import '@opentelemetry/sdk-trace-base';
8
8
  import '@opentelemetry/core';
@@ -12,9 +12,34 @@ interface HttpServerOptions {
12
12
  port?: number;
13
13
  host?: string;
14
14
  }
15
- declare function attachDevtoolsRoutes(httpServer: Server, devtools: DevtoolsServer): void;
15
+ interface DevtoolsRoutesOptions {
16
+ /** Bound to a loopback host (the default). Enables the DNS-rebinding `Host`
17
+ * check on read endpoints; an explicit non-loopback bind opts out. */
18
+ loopbackOnly?: boolean;
19
+ }
20
+ declare function attachDevtoolsRoutes(httpServer: Server, devtools: DevtoolsServer, options?: DevtoolsRoutesOptions): void;
16
21
  declare function createDevtoolsHttpServer(devtools: DevtoolsServer, _options?: HttpServerOptions): Server;
17
22
 
23
+ /** True for `localhost`, any `127.x.x.x`, and IPv6 loopback. Case-insensitive. */
24
+ declare function isLoopbackHostname(hostname: string): boolean;
25
+ /** True when the `Host` header names a loopback host. */
26
+ declare function hostHeaderIsLoopback(host: string): boolean;
27
+ /** True when an `Origin` header names a loopback origin. A malformed or opaque
28
+ * origin (e.g. the literal `null` from a sandboxed iframe) is treated as
29
+ * non-loopback. */
30
+ declare function originIsLoopback(origin: string): boolean;
31
+ interface GuardHeaders {
32
+ origin?: string;
33
+ host?: string;
34
+ }
35
+ /**
36
+ * Decide whether a request to a sensitive (read/mutate) endpoint is allowed.
37
+ * - A present, non-loopback `Origin` is always rejected (cross-origin read).
38
+ * - When `loopbackOnly`, a present, non-loopback `Host` is rejected (DNS
39
+ * rebinding). Skipped when the receiver is bound to a non-loopback host.
40
+ */
41
+ declare function allowSensitiveRequest(headers: GuardHeaders, loopbackOnly: boolean): boolean;
42
+
18
43
  declare function parseOtlpTraces(payload: unknown): TraceData[];
19
44
  declare function parseOtlpLogs(payload: unknown): LogData[];
20
45
  /**
@@ -64,4 +89,4 @@ declare function appendWithLimit<T>(items: T[], item: T, limit: number): T[];
64
89
  declare function appendManyWithLimit<T>(items: T[], incoming: T[], limit: number): T[];
65
90
  declare function applyTelemetryLimits(data: DevtoolsData, limits: TelemetryLimits): DevtoolsData;
66
91
 
67
- export { DEVTOOLS_IDENTITY, DevtoolsData, DevtoolsServer, type HttpServerOptions, LogData, type PortHolder, type TelemetryLimits, TraceData, appendManyWithLimit, appendWithLimit, applyTelemetryLimits, attachDevtoolsRoutes, createDevtoolsHttpServer, decodeOtlpLogsRequest, decodeOtlpMetricsRequest, decodeOtlpTraceRequest, isProtobufContentType, parseOtlpLogs, parseOtlpTraces, probePortHolder, resolveTelemetryLimits };
92
+ export { DEVTOOLS_IDENTITY, DevtoolsData, type DevtoolsRoutesOptions, DevtoolsServer, type HttpServerOptions, LogData, type PortHolder, type TelemetryLimits, TraceData, allowSensitiveRequest, appendManyWithLimit, appendWithLimit, applyTelemetryLimits, attachDevtoolsRoutes, createDevtoolsHttpServer, decodeOtlpLogsRequest, decodeOtlpMetricsRequest, decodeOtlpTraceRequest, hostHeaderIsLoopback, isLoopbackHostname, isProtobufContentType, originIsLoopback, parseOtlpLogs, parseOtlpTraces, probePortHolder, resolveTelemetryLimits };
@@ -1,8 +1,8 @@
1
- import { D as DevtoolsServer, L as LogData, T as TraceData, b as DevtoolsData } from '../exporter-DjLkU621.js';
2
- export { d as DevtoolsServerOptions, a as DevtoolsSpanExporter, E as ErrorGroup, c as ErrorOccurrence, M as MetricData, S as SpanData } from '../exporter-DjLkU621.js';
1
+ import { D as DevtoolsServer, L as LogData, T as TraceData, b as DevtoolsData } from '../exporter-De6p4iAD.js';
2
+ export { d as DevtoolsServerOptions, a as DevtoolsSpanExporter, E as ErrorGroup, c as ErrorOccurrence, M as MetricData, S as SpanData } from '../exporter-De6p4iAD.js';
3
3
  export { DevtoolsLogExporter } from './log-exporter.js';
4
4
  export { DevtoolsRemoteExporter, DevtoolsRemoteExporterOptions } from './remote-exporter.js';
5
- export { E as ErrorAggregator } from '../error-aggregator-CAk_pt3Z.js';
5
+ export { E as ErrorAggregator } from '../error-aggregator-D0Uu5r38.js';
6
6
  import { Server } from 'node:http';
7
7
  import '@opentelemetry/sdk-trace-base';
8
8
  import '@opentelemetry/core';
@@ -12,9 +12,34 @@ interface HttpServerOptions {
12
12
  port?: number;
13
13
  host?: string;
14
14
  }
15
- declare function attachDevtoolsRoutes(httpServer: Server, devtools: DevtoolsServer): void;
15
+ interface DevtoolsRoutesOptions {
16
+ /** Bound to a loopback host (the default). Enables the DNS-rebinding `Host`
17
+ * check on read endpoints; an explicit non-loopback bind opts out. */
18
+ loopbackOnly?: boolean;
19
+ }
20
+ declare function attachDevtoolsRoutes(httpServer: Server, devtools: DevtoolsServer, options?: DevtoolsRoutesOptions): void;
16
21
  declare function createDevtoolsHttpServer(devtools: DevtoolsServer, _options?: HttpServerOptions): Server;
17
22
 
23
+ /** True for `localhost`, any `127.x.x.x`, and IPv6 loopback. Case-insensitive. */
24
+ declare function isLoopbackHostname(hostname: string): boolean;
25
+ /** True when the `Host` header names a loopback host. */
26
+ declare function hostHeaderIsLoopback(host: string): boolean;
27
+ /** True when an `Origin` header names a loopback origin. A malformed or opaque
28
+ * origin (e.g. the literal `null` from a sandboxed iframe) is treated as
29
+ * non-loopback. */
30
+ declare function originIsLoopback(origin: string): boolean;
31
+ interface GuardHeaders {
32
+ origin?: string;
33
+ host?: string;
34
+ }
35
+ /**
36
+ * Decide whether a request to a sensitive (read/mutate) endpoint is allowed.
37
+ * - A present, non-loopback `Origin` is always rejected (cross-origin read).
38
+ * - When `loopbackOnly`, a present, non-loopback `Host` is rejected (DNS
39
+ * rebinding). Skipped when the receiver is bound to a non-loopback host.
40
+ */
41
+ declare function allowSensitiveRequest(headers: GuardHeaders, loopbackOnly: boolean): boolean;
42
+
18
43
  declare function parseOtlpTraces(payload: unknown): TraceData[];
19
44
  declare function parseOtlpLogs(payload: unknown): LogData[];
20
45
  /**
@@ -64,4 +89,4 @@ declare function appendWithLimit<T>(items: T[], item: T, limit: number): T[];
64
89
  declare function appendManyWithLimit<T>(items: T[], incoming: T[], limit: number): T[];
65
90
  declare function applyTelemetryLimits(data: DevtoolsData, limits: TelemetryLimits): DevtoolsData;
66
91
 
67
- export { DEVTOOLS_IDENTITY, DevtoolsData, DevtoolsServer, type HttpServerOptions, LogData, type PortHolder, type TelemetryLimits, TraceData, appendManyWithLimit, appendWithLimit, applyTelemetryLimits, attachDevtoolsRoutes, createDevtoolsHttpServer, decodeOtlpLogsRequest, decodeOtlpMetricsRequest, decodeOtlpTraceRequest, isProtobufContentType, parseOtlpLogs, parseOtlpTraces, probePortHolder, resolveTelemetryLimits };
92
+ export { DEVTOOLS_IDENTITY, DevtoolsData, type DevtoolsRoutesOptions, DevtoolsServer, type HttpServerOptions, LogData, type PortHolder, type TelemetryLimits, TraceData, allowSensitiveRequest, appendManyWithLimit, appendWithLimit, applyTelemetryLimits, attachDevtoolsRoutes, createDevtoolsHttpServer, decodeOtlpLogsRequest, decodeOtlpMetricsRequest, decodeOtlpTraceRequest, hostHeaderIsLoopback, isLoopbackHostname, isProtobufContentType, originIsLoopback, parseOtlpLogs, parseOtlpTraces, probePortHolder, resolveTelemetryLimits };
@@ -356,6 +356,40 @@ function applyTelemetryLimits(data, limits) {
356
356
  };
357
357
  }
358
358
 
359
+ // src/server/origin-guard.ts
360
+ var LOOPBACK_IPV6 = /* @__PURE__ */ new Set(["::1", "0:0:0:0:0:0:0:1"]);
361
+ function isLoopbackHostname(hostname) {
362
+ const h = hostname.toLowerCase().replace(/^\[|\]$/g, "");
363
+ return h === "localhost" || /^127\./.test(h) || LOOPBACK_IPV6.has(h);
364
+ }
365
+ function hostnameFromHostHeader(host) {
366
+ const h = host.trim();
367
+ if (h.startsWith("[")) {
368
+ const end = h.indexOf("]");
369
+ return end > 0 ? h.slice(1, end) : h;
370
+ }
371
+ const colon = h.indexOf(":");
372
+ return colon === -1 ? h : h.slice(0, colon);
373
+ }
374
+ function hostHeaderIsLoopback(host) {
375
+ return isLoopbackHostname(hostnameFromHostHeader(host));
376
+ }
377
+ function originIsLoopback(origin) {
378
+ try {
379
+ return isLoopbackHostname(new URL(origin).hostname);
380
+ } catch {
381
+ return false;
382
+ }
383
+ }
384
+ function allowSensitiveRequest(headers, loopbackOnly) {
385
+ const { origin, host } = headers;
386
+ if (origin && origin.length > 0 && !originIsLoopback(origin)) return false;
387
+ if (loopbackOnly && host && host.length > 0 && !hostHeaderIsLoopback(host)) {
388
+ return false;
389
+ }
390
+ return true;
391
+ }
392
+
359
393
  // src/server/server.ts
360
394
  var DevtoolsServer = class {
361
395
  wss;
@@ -375,7 +409,12 @@ var DevtoolsServer = class {
375
409
  this._port = options.port ?? 4318;
376
410
  this.onData = options.onData;
377
411
  this.httpServer = options.server ?? createServer();
378
- this.wss = new WebSocketServer({ server: this.httpServer, path: options.path ?? "/ws" });
412
+ const loopbackOnly = options.host == null || hostHeaderIsLoopback(options.host);
413
+ this.wss = new WebSocketServer({
414
+ server: this.httpServer,
415
+ path: options.path ?? "/ws",
416
+ verifyClient: ({ origin, req }) => allowSensitiveRequest({ origin, host: req.headers.host }, loopbackOnly)
417
+ });
379
418
  this.wss.on("error", (err) => {
380
419
  if (this.httpServer.listening) throw err;
381
420
  });
@@ -1474,7 +1513,8 @@ function getWidgetJs() {
1474
1513
  }
1475
1514
  return cachedWidgetJs;
1476
1515
  }
1477
- function attachDevtoolsRoutes(httpServer, devtools) {
1516
+ function attachDevtoolsRoutes(httpServer, devtools, options = {}) {
1517
+ const loopbackOnly = options.loopbackOnly ?? true;
1478
1518
  httpServer.on("request", async (req, res) => {
1479
1519
  res.setHeader("Access-Control-Allow-Origin", "*");
1480
1520
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
@@ -1508,11 +1548,19 @@ function attachDevtoolsRoutes(httpServer, devtools) {
1508
1548
  return;
1509
1549
  }
1510
1550
  if (req.method === "GET" && url === "/v1/traces") {
1551
+ if (!allowSensitiveRequest(req.headers, loopbackOnly)) {
1552
+ sendJson(res, 403, { error: "Forbidden" });
1553
+ return;
1554
+ }
1511
1555
  const data = devtools.getCurrentData();
1512
1556
  sendJson(res, 200, { traces: data.traces, count: data.traces.length });
1513
1557
  return;
1514
1558
  }
1515
1559
  if (req.method === "DELETE" && url === "/v1/traces") {
1560
+ if (!allowSensitiveRequest(req.headers, loopbackOnly)) {
1561
+ sendJson(res, 403, { error: "Forbidden" });
1562
+ return;
1563
+ }
1516
1564
  devtools.clearData();
1517
1565
  sendJson(res, 200, { cleared: true });
1518
1566
  return;
@@ -1558,6 +1606,6 @@ function createDevtoolsHttpServer(devtools, _options = {}) {
1558
1606
  return server;
1559
1607
  }
1560
1608
 
1561
- export { DEVTOOLS_IDENTITY, DevtoolsLogExporter, DevtoolsRemoteExporter, DevtoolsServer, DevtoolsSpanExporter, ErrorAggregator, appendManyWithLimit, appendWithLimit, applyTelemetryLimits, attachDevtoolsRoutes, createDevtoolsHttpServer, decodeOtlpLogsRequest, decodeOtlpMetricsRequest, decodeOtlpTraceRequest, isProtobufContentType, parseOtlpLogs, parseOtlpTraces, probePortHolder, resolveTelemetryLimits };
1609
+ export { DEVTOOLS_IDENTITY, DevtoolsLogExporter, DevtoolsRemoteExporter, DevtoolsServer, DevtoolsSpanExporter, ErrorAggregator, allowSensitiveRequest, appendManyWithLimit, appendWithLimit, applyTelemetryLimits, attachDevtoolsRoutes, createDevtoolsHttpServer, decodeOtlpLogsRequest, decodeOtlpMetricsRequest, decodeOtlpTraceRequest, hostHeaderIsLoopback, isLoopbackHostname, isProtobufContentType, originIsLoopback, parseOtlpLogs, parseOtlpTraces, probePortHolder, resolveTelemetryLimits };
1562
1610
  //# sourceMappingURL=index.js.map
1563
1611
  //# sourceMappingURL=index.js.map