@dnsid-ai/transport 0.25.0 → 0.27.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/index.cjs +23 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +23 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -46,6 +46,7 @@ var fs = __toESM(require("fs"), 1);
|
|
|
46
46
|
var https = __toESM(require("https"), 1);
|
|
47
47
|
var net2 = __toESM(require("net"), 1);
|
|
48
48
|
var tls = __toESM(require("tls"), 1);
|
|
49
|
+
var import_node_stream = require("stream");
|
|
49
50
|
var import_undici = require("undici");
|
|
50
51
|
var import_protocol2 = require("@dnsid-ai/protocol");
|
|
51
52
|
|
|
@@ -190,7 +191,8 @@ function createSsrfSafeFetch(config = {}, options = {}) {
|
|
|
190
191
|
const privateAddressHosts = (options.privateAddressHosts ?? []).map(import_protocol2.normalizePrivateAddressHost);
|
|
191
192
|
const connect2 = { lookup: createSsrfSafeLookup(config.dnsServer, privateAddressHosts) };
|
|
192
193
|
if (config.caBundlePath) connect2.ca = [...tls.rootCertificates, fs.readFileSync(config.caBundlePath, "utf8")];
|
|
193
|
-
const
|
|
194
|
+
const dispatcher = new import_undici.Agent({ connect: connect2 });
|
|
195
|
+
const fetchWithSafeLookup = createFetchWithDispatcher(dispatcher);
|
|
194
196
|
return async (input, init) => {
|
|
195
197
|
const url = new URL(input instanceof Request ? input.url : input);
|
|
196
198
|
if (isUnsafeIp(url.hostname)) {
|
|
@@ -198,6 +200,26 @@ function createSsrfSafeFetch(config = {}, options = {}) {
|
|
|
198
200
|
code: import_protocol2.VerificationCode.TLSError
|
|
199
201
|
});
|
|
200
202
|
}
|
|
203
|
+
if (options.decompress === false) {
|
|
204
|
+
const { url: target, init: normalized } = normalizeFetchArgs(input, { ...init, redirect: "manual" });
|
|
205
|
+
const request = new Request(target, normalized);
|
|
206
|
+
const targetUrl = new URL(request.url);
|
|
207
|
+
const response = await dispatcher.request({
|
|
208
|
+
origin: targetUrl.origin,
|
|
209
|
+
path: targetUrl.pathname + targetUrl.search,
|
|
210
|
+
method: request.method,
|
|
211
|
+
headers: Object.fromEntries(request.headers),
|
|
212
|
+
body: request.body ? import_node_stream.Readable.fromWeb(request.body) : void 0,
|
|
213
|
+
signal: request.signal
|
|
214
|
+
});
|
|
215
|
+
const headers = new Headers();
|
|
216
|
+
for (const [name, value] of Object.entries(response.headers)) {
|
|
217
|
+
for (const item of Array.isArray(value) ? value : value === void 0 ? [] : [value]) headers.append(name, item);
|
|
218
|
+
}
|
|
219
|
+
const noBody = request.method === "HEAD" || [204, 205, 304].includes(response.statusCode);
|
|
220
|
+
if (noBody) await response.body.dump();
|
|
221
|
+
return new Response(noBody ? null : import_node_stream.Readable.toWeb(response.body), { status: response.statusCode, statusText: response.statusText, headers });
|
|
222
|
+
}
|
|
201
223
|
return fetchWithSafeLookup(input, { ...init, redirect: "manual" });
|
|
202
224
|
};
|
|
203
225
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -33,6 +33,8 @@ interface HTTPSFetchOptions {
|
|
|
33
33
|
|
|
34
34
|
/** Explicit exceptions for trusted test/private deployments using {@link createSsrfSafeFetch}. */
|
|
35
35
|
interface SsrfSafeFetchOptions {
|
|
36
|
+
/** Set false to preserve encoded response bytes and Content-Encoding, for signed-directory verification. Default: true. */
|
|
37
|
+
decompress?: boolean;
|
|
36
38
|
/**
|
|
37
39
|
* Hostnames, or leading-dot suffixes such as `.test`, whose resolved RFC 1918/ULA private or
|
|
38
40
|
* loopback addresses may be contacted. Link-local and other unsafe ranges remain blocked, IP-literal
|
package/dist/index.d.ts
CHANGED
|
@@ -33,6 +33,8 @@ interface HTTPSFetchOptions {
|
|
|
33
33
|
|
|
34
34
|
/** Explicit exceptions for trusted test/private deployments using {@link createSsrfSafeFetch}. */
|
|
35
35
|
interface SsrfSafeFetchOptions {
|
|
36
|
+
/** Set false to preserve encoded response bytes and Content-Encoding, for signed-directory verification. Default: true. */
|
|
37
|
+
decompress?: boolean;
|
|
36
38
|
/**
|
|
37
39
|
* Hostnames, or leading-dot suffixes such as `.test`, whose resolved RFC 1918/ULA private or
|
|
38
40
|
* loopback addresses may be contacted. Link-local and other unsafe ranges remain blocked, IP-literal
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import * as fs from "fs";
|
|
|
4
4
|
import * as https from "https";
|
|
5
5
|
import * as net2 from "net";
|
|
6
6
|
import * as tls from "tls";
|
|
7
|
+
import { Readable } from "stream";
|
|
7
8
|
import { Agent as Agent2, fetch as undiciFetch } from "undici";
|
|
8
9
|
import { ArgumentError, DNSSECState as DNSSECState2, VerificationCode, VerificationError, normalizePrivateAddressHost } from "@dnsid-ai/protocol";
|
|
9
10
|
|
|
@@ -148,7 +149,8 @@ function createSsrfSafeFetch(config = {}, options = {}) {
|
|
|
148
149
|
const privateAddressHosts = (options.privateAddressHosts ?? []).map(normalizePrivateAddressHost);
|
|
149
150
|
const connect2 = { lookup: createSsrfSafeLookup(config.dnsServer, privateAddressHosts) };
|
|
150
151
|
if (config.caBundlePath) connect2.ca = [...tls.rootCertificates, fs.readFileSync(config.caBundlePath, "utf8")];
|
|
151
|
-
const
|
|
152
|
+
const dispatcher = new Agent2({ connect: connect2 });
|
|
153
|
+
const fetchWithSafeLookup = createFetchWithDispatcher(dispatcher);
|
|
152
154
|
return async (input, init) => {
|
|
153
155
|
const url = new URL(input instanceof Request ? input.url : input);
|
|
154
156
|
if (isUnsafeIp(url.hostname)) {
|
|
@@ -156,6 +158,26 @@ function createSsrfSafeFetch(config = {}, options = {}) {
|
|
|
156
158
|
code: VerificationCode.TLSError
|
|
157
159
|
});
|
|
158
160
|
}
|
|
161
|
+
if (options.decompress === false) {
|
|
162
|
+
const { url: target, init: normalized } = normalizeFetchArgs(input, { ...init, redirect: "manual" });
|
|
163
|
+
const request = new Request(target, normalized);
|
|
164
|
+
const targetUrl = new URL(request.url);
|
|
165
|
+
const response = await dispatcher.request({
|
|
166
|
+
origin: targetUrl.origin,
|
|
167
|
+
path: targetUrl.pathname + targetUrl.search,
|
|
168
|
+
method: request.method,
|
|
169
|
+
headers: Object.fromEntries(request.headers),
|
|
170
|
+
body: request.body ? Readable.fromWeb(request.body) : void 0,
|
|
171
|
+
signal: request.signal
|
|
172
|
+
});
|
|
173
|
+
const headers = new Headers();
|
|
174
|
+
for (const [name, value] of Object.entries(response.headers)) {
|
|
175
|
+
for (const item of Array.isArray(value) ? value : value === void 0 ? [] : [value]) headers.append(name, item);
|
|
176
|
+
}
|
|
177
|
+
const noBody = request.method === "HEAD" || [204, 205, 304].includes(response.statusCode);
|
|
178
|
+
if (noBody) await response.body.dump();
|
|
179
|
+
return new Response(noBody ? null : Readable.toWeb(response.body), { status: response.statusCode, statusText: response.statusText, headers });
|
|
180
|
+
}
|
|
159
181
|
return fetchWithSafeLookup(input, { ...init, redirect: "manual" });
|
|
160
182
|
};
|
|
161
183
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dnsid-ai/transport",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "Node.js DNS and HTTPS transport implementations for DNSid.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"typecheck": "tsc --noEmit"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@dnsid-ai/protocol": "^0.
|
|
41
|
+
"@dnsid-ai/protocol": "^0.27.0",
|
|
42
42
|
"dns-packet": "5.6.1",
|
|
43
43
|
"undici": "^8.11.0"
|
|
44
44
|
},
|