@n8n/backend-network 1.0.0 → 1.1.1

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.
Files changed (57) hide show
  1. package/LICENSE_EE.md +27 -0
  2. package/dist/build.tsbuildinfo +1 -1
  3. package/dist/dns/dns-resolver.d.ts +13 -0
  4. package/dist/dns/dns-resolver.js +93 -0
  5. package/dist/dns/dns-resolver.js.map +1 -0
  6. package/dist/dns/in-memory-dns-cache.service.d.ts +21 -0
  7. package/dist/dns/in-memory-dns-cache.service.js +73 -0
  8. package/dist/dns/in-memory-dns-cache.service.js.map +1 -0
  9. package/dist/dns/index.d.ts +2 -0
  10. package/dist/dns/index.js +8 -0
  11. package/dist/dns/index.js.map +1 -0
  12. package/dist/http/axios-config.d.ts +1 -0
  13. package/dist/http/axios-config.js +42 -0
  14. package/dist/http/axios-config.js.map +1 -0
  15. package/dist/http/axios-utils.d.ts +24 -0
  16. package/dist/http/axios-utils.js +257 -0
  17. package/dist/http/axios-utils.js.map +1 -0
  18. package/dist/http/binary-buffer.d.ts +3 -0
  19. package/dist/http/binary-buffer.js +24 -0
  20. package/dist/http/binary-buffer.js.map +1 -0
  21. package/dist/http/binary-string.d.ts +2 -0
  22. package/dist/http/binary-string.js +16 -0
  23. package/dist/http/binary-string.js.map +1 -0
  24. package/dist/http/http-proxy.d.ts +7 -0
  25. package/dist/http/http-proxy.js +113 -0
  26. package/dist/http/http-proxy.js.map +1 -0
  27. package/dist/http/http-request.d.ts +7 -0
  28. package/dist/http/http-request.js +157 -0
  29. package/dist/http/http-request.js.map +1 -0
  30. package/dist/http/index.d.ts +8 -0
  31. package/dist/http/index.js +39 -0
  32. package/dist/http/index.js.map +1 -0
  33. package/dist/http/outbound-user-agent.d.ts +4 -0
  34. package/dist/http/outbound-user-agent.js +40 -0
  35. package/dist/http/outbound-user-agent.js.map +1 -0
  36. package/dist/http/parse-incoming-message.d.ts +16 -0
  37. package/dist/http/parse-incoming-message.js +75 -0
  38. package/dist/http/parse-incoming-message.js.map +1 -0
  39. package/dist/index.d.ts +3 -1
  40. package/dist/index.js +17 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/ssrf/hostname-matcher.d.ts +6 -0
  43. package/dist/ssrf/hostname-matcher.js +38 -0
  44. package/dist/ssrf/hostname-matcher.js.map +1 -0
  45. package/dist/ssrf/index.d.ts +3 -0
  46. package/dist/ssrf/index.js +8 -0
  47. package/dist/ssrf/index.js.map +1 -0
  48. package/dist/ssrf/ip-range-builder.d.ts +10 -0
  49. package/dist/ssrf/ip-range-builder.js +52 -0
  50. package/dist/ssrf/ip-range-builder.js.map +1 -0
  51. package/dist/ssrf/ssrf-blocked-ip.error.d.ts +6 -0
  52. package/dist/ssrf/ssrf-blocked-ip.error.js +21 -0
  53. package/dist/ssrf/ssrf-blocked-ip.error.js.map +1 -0
  54. package/dist/ssrf/ssrf-protection.service.d.ts +48 -0
  55. package/dist/ssrf/ssrf-protection.service.js +192 -0
  56. package/dist/ssrf/ssrf-protection.service.js.map +1 -0
  57. package/package.json +36 -8
@@ -0,0 +1,13 @@
1
+ import type { LookupAddress, LookupOptions } from 'node:dns';
2
+ import { InMemoryDnsCache } from './in-memory-dns-cache.service';
3
+ export type DnsLookupOptions = Pick<LookupOptions, 'all' | 'family' | 'order' | 'verbatim' | 'hints'>;
4
+ export declare class DnsResolver {
5
+ private readonly dnsCache;
6
+ private readonly inFlightByCacheKey;
7
+ constructor(dnsCache: InMemoryDnsCache);
8
+ lookup(hostname: string, options?: DnsLookupOptions): Promise<LookupAddress[]>;
9
+ private doLookup;
10
+ private buildCacheKey;
11
+ private normalizeOptions;
12
+ private normalizeIpFamily;
13
+ }
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.DnsResolver = void 0;
13
+ const di_1 = require("@n8n/di");
14
+ const node_dns_1 = require("node:dns");
15
+ const in_memory_dns_cache_service_1 = require("./in-memory-dns-cache.service");
16
+ const LOOKUP_CACHE_TTL_SECONDS = 1;
17
+ let DnsResolver = class DnsResolver {
18
+ constructor(dnsCache) {
19
+ this.dnsCache = dnsCache;
20
+ this.inFlightByCacheKey = new Map();
21
+ }
22
+ async lookup(hostname, options = {}) {
23
+ const normalized = this.normalizeOptions(options);
24
+ const cacheKey = this.buildCacheKey(hostname, normalized);
25
+ const cached = await this.dnsCache.get(cacheKey);
26
+ if (cached)
27
+ return cached;
28
+ const existing = this.inFlightByCacheKey.get(cacheKey);
29
+ if (existing)
30
+ return await existing;
31
+ const lookupPromise = (async () => {
32
+ const addresses = await this.doLookup(hostname, normalized);
33
+ if (addresses.length > 0) {
34
+ await this.dnsCache.set(cacheKey, addresses, LOOKUP_CACHE_TTL_SECONDS);
35
+ }
36
+ return addresses;
37
+ })();
38
+ this.inFlightByCacheKey.set(cacheKey, lookupPromise);
39
+ return await lookupPromise.finally(() => {
40
+ this.inFlightByCacheKey.delete(cacheKey);
41
+ });
42
+ }
43
+ async doLookup(hostname, options) {
44
+ if (options.all) {
45
+ const records = await node_dns_1.promises.lookup(hostname, {
46
+ all: true,
47
+ family: options.family,
48
+ order: options.order,
49
+ verbatim: options.verbatim,
50
+ hints: options.hints,
51
+ });
52
+ return records;
53
+ }
54
+ const record = await node_dns_1.promises.lookup(hostname, {
55
+ all: false,
56
+ family: options.family,
57
+ order: options.order,
58
+ verbatim: options.verbatim,
59
+ hints: options.hints,
60
+ });
61
+ return [record];
62
+ }
63
+ buildCacheKey(hostname, options) {
64
+ const order = options.order ?? '-';
65
+ const verbatim = options.verbatim === undefined ? '-' : options.verbatim ? '1' : '0';
66
+ return `${hostname}|a:${options.all ? '1' : '0'}|f:${options.family}|o:${order}|v:${verbatim}|h:${options.hints ?? 0}`;
67
+ }
68
+ normalizeOptions(options) {
69
+ const all = options.all === true;
70
+ const family = this.normalizeIpFamily(options.family);
71
+ const order = options.order;
72
+ const verbatim = options.verbatim;
73
+ return { all, family, order, verbatim, hints: options.hints };
74
+ }
75
+ normalizeIpFamily(family) {
76
+ if (family === 4 || family === 6 || family === 0) {
77
+ return family;
78
+ }
79
+ if (family === 'IPv4') {
80
+ return 4;
81
+ }
82
+ if (family === 'IPv6') {
83
+ return 6;
84
+ }
85
+ return 0;
86
+ }
87
+ };
88
+ exports.DnsResolver = DnsResolver;
89
+ exports.DnsResolver = DnsResolver = __decorate([
90
+ (0, di_1.Service)(),
91
+ __metadata("design:paramtypes", [in_memory_dns_cache_service_1.InMemoryDnsCache])
92
+ ], DnsResolver);
93
+ //# sourceMappingURL=dns-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dns-resolver.js","sourceRoot":"","sources":["../../src/dns/dns-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { TypedEmitter } from '@n8n/backend-common';
2
+ import { SsrfProtectionConfig } from '@n8n/config';
3
+ import type { LookupAddress } from 'node:dns';
4
+ export type DnsCacheEventMap = {
5
+ hit: undefined;
6
+ miss: undefined;
7
+ eviction: {
8
+ size: number;
9
+ };
10
+ };
11
+ export declare class InMemoryDnsCache {
12
+ private readonly ssrfConfig;
13
+ private cache;
14
+ readonly events: TypedEmitter<DnsCacheEventMap>;
15
+ constructor(ssrfConfig: SsrfProtectionConfig);
16
+ private ensureCache;
17
+ get size(): number;
18
+ get(hostname: string): Promise<LookupAddress[] | undefined>;
19
+ set(hostname: string, ips: LookupAddress[], ttl: number): Promise<void>;
20
+ clear(): Promise<void>;
21
+ }
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.InMemoryDnsCache = void 0;
16
+ const backend_common_1 = require("@n8n/backend-common");
17
+ const config_1 = require("@n8n/config");
18
+ const constants_1 = require("@n8n/constants");
19
+ const di_1 = require("@n8n/di");
20
+ const cache_manager_1 = require("cache-manager");
21
+ const n8n_workflow_1 = require("n8n-workflow");
22
+ const node_assert_1 = __importDefault(require("node:assert"));
23
+ let InMemoryDnsCache = class InMemoryDnsCache {
24
+ constructor(ssrfConfig) {
25
+ this.ssrfConfig = ssrfConfig;
26
+ this.events = new backend_common_1.TypedEmitter();
27
+ }
28
+ async ensureCache() {
29
+ if (!this.cache) {
30
+ const sizeCalculation = (item) => {
31
+ const str = (0, n8n_workflow_1.jsonStringify)(item, { replaceCircularRefs: true });
32
+ return new TextEncoder().encode(str).length;
33
+ };
34
+ this.cache = await (0, cache_manager_1.caching)('memory', {
35
+ maxSize: this.ssrfConfig.dnsCacheMaxSize,
36
+ sizeCalculation,
37
+ ttl: 0,
38
+ ttlResolution: 0,
39
+ dispose: (_value, _key, reason) => {
40
+ if (reason === 'evict') {
41
+ this.events.emit('eviction', { size: Math.max(this.size - 1, 0) });
42
+ }
43
+ },
44
+ });
45
+ }
46
+ return this.cache;
47
+ }
48
+ get size() {
49
+ return this.cache?.store?.size ?? 0;
50
+ }
51
+ async get(hostname) {
52
+ const cache = await this.ensureCache();
53
+ const result = await cache.get(hostname);
54
+ this.events.emit(result !== undefined ? 'hit' : 'miss');
55
+ return result;
56
+ }
57
+ async set(hostname, ips, ttl) {
58
+ (0, node_assert_1.default)(ttl > 0, 'DNS cache TTL must be greater than 0');
59
+ const cache = await this.ensureCache();
60
+ const ttlMs = ttl * constants_1.Time.seconds.toMilliseconds;
61
+ await cache.set(hostname, ips, ttlMs);
62
+ }
63
+ async clear() {
64
+ const cache = await this.ensureCache();
65
+ await cache.reset();
66
+ }
67
+ };
68
+ exports.InMemoryDnsCache = InMemoryDnsCache;
69
+ exports.InMemoryDnsCache = InMemoryDnsCache = __decorate([
70
+ (0, di_1.Service)(),
71
+ __metadata("design:paramtypes", [config_1.SsrfProtectionConfig])
72
+ ], InMemoryDnsCache);
73
+ //# sourceMappingURL=in-memory-dns-cache.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-dns-cache.service.js","sourceRoot":"","sources":["../../src/dns/in-memory-dns-cache.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,wDAAmD;AACnD,wCAAmD;AACnD,8CAAsC;AACtC,gCAAkC;AAElC,iDAAwC;AACxC,+CAA6C;AAC7C,8DAAiC;AAa1B,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;IAK5B,YAA6B,UAAgC;QAAhC,eAAU,GAAV,UAAU,CAAsB;QAFpD,WAAM,GAAG,IAAI,6BAAY,EAAoB,CAAC;IAES,CAAC;IAEzD,KAAK,CAAC,WAAW;QACxB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,eAAe,GAAG,CAAC,IAAa,EAAE,EAAE;gBACzC,MAAM,GAAG,GAAG,IAAA,4BAAa,EAAC,IAAI,EAAE,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC/D,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;YAC7C,CAAC,CAAC;YAEF,IAAI,CAAC,KAAK,GAAG,MAAM,IAAA,uBAAO,EAAC,QAAQ,EAAE;gBACpC,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,eAAe;gBACxC,eAAe;gBACf,GAAG,EAAE,CAAC;gBACN,aAAa,EAAE,CAAC;gBAChB,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE;oBACjC,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;wBAGxB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;oBACpE,CAAC;gBACF,CAAC;aACD,CAAC,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC,KAAK,CAAC;IACnB,CAAC;IAED,IAAI,IAAI;QACP,OAAO,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,QAAgB;QACzB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAkB,QAAQ,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACxD,OAAO,MAAM,CAAC;IACf,CAAC;IAOD,KAAK,CAAC,GAAG,CAAC,QAAgB,EAAE,GAAoB,EAAE,GAAW;QAC5D,IAAA,qBAAM,EAAC,GAAG,GAAG,CAAC,EAAE,sCAAsC,CAAC,CAAC;QAExD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,GAAG,GAAG,gBAAI,CAAC,OAAO,CAAC,cAAc,CAAC;QAChD,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,KAAK;QACV,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACD,CAAA;AA5DY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,YAAO,GAAE;qCAMgC,6BAAoB;GALjD,gBAAgB,CA4D5B"}
@@ -0,0 +1,2 @@
1
+ export { DnsResolver } from './dns-resolver';
2
+ export { InMemoryDnsCache } from './in-memory-dns-cache.service';
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InMemoryDnsCache = exports.DnsResolver = void 0;
4
+ var dns_resolver_1 = require("./dns-resolver");
5
+ Object.defineProperty(exports, "DnsResolver", { enumerable: true, get: function () { return dns_resolver_1.DnsResolver; } });
6
+ var in_memory_dns_cache_service_1 = require("./in-memory-dns-cache.service");
7
+ Object.defineProperty(exports, "InMemoryDnsCache", { enumerable: true, get: function () { return in_memory_dns_cache_service_1.InMemoryDnsCache; } });
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dns/index.ts"],"names":[],"mappings":";;;AAAA,+CAA6C;AAApC,2GAAA,WAAW,OAAA;AACpB,6EAAiE;AAAxD,+HAAA,gBAAgB,OAAA"}
@@ -0,0 +1 @@
1
+ export declare function configureGlobalAxiosDefaults(): void;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.configureGlobalAxiosDefaults = configureGlobalAxiosDefaults;
7
+ const config_1 = require("@n8n/config");
8
+ const di_1 = require("@n8n/di");
9
+ const axios_1 = __importDefault(require("axios"));
10
+ const qs_1 = require("qs");
11
+ const axios_utils_1 = require("./axios-utils");
12
+ let configured = false;
13
+ function configureGlobalAxiosDefaults() {
14
+ if (!configured) {
15
+ configured = true;
16
+ axios_1.default.defaults.timeout = 300000;
17
+ axios_1.default.defaults.headers.post = {};
18
+ axios_1.default.defaults.headers.put = {};
19
+ axios_1.default.defaults.headers.patch = {};
20
+ axios_1.default.defaults.paramsSerializer = (params) => {
21
+ if (params instanceof URLSearchParams) {
22
+ return params.toString();
23
+ }
24
+ return (0, qs_1.stringify)(params, { arrayFormat: 'indices' });
25
+ };
26
+ axios_1.default.defaults.proxy = false;
27
+ axios_1.default.interceptors.request.use((config) => {
28
+ if (config.data === undefined) {
29
+ config.headers.setContentType(false, false);
30
+ }
31
+ (0, axios_utils_1.setAxiosAgents)(config);
32
+ applyVendorHeaders(config);
33
+ return config;
34
+ });
35
+ }
36
+ }
37
+ function applyVendorHeaders(config) {
38
+ if ([config.url, config.baseURL].some((url) => url?.startsWith('https://api.openai.com/'))) {
39
+ config.headers.set(di_1.Container.get(config_1.AiConfig).openAiDefaultHeaders, false);
40
+ }
41
+ }
42
+ //# sourceMappingURL=axios-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"axios-config.js","sourceRoot":"","sources":["../../src/http/axios-config.ts"],"names":[],"mappings":";;;;;AAeA,oEAkCC;AAjDD,wCAAuC;AACvC,gCAAoC;AACpC,kDAA0B;AAE1B,2BAA+B;AAE/B,+CAA+C;AAE/C,IAAI,UAAU,GAAG,KAAK,CAAC;AAOvB,SAAgB,4BAA4B;IAC3C,IAAI,CAAC,UAAU,EAAE,CAAC;QACjB,UAAU,GAAG,IAAI,CAAC;QAIlB,eAAK,CAAC,QAAQ,CAAC,OAAO,GAAG,MAAM,CAAC;QAEhC,eAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,GAAG,EAAE,CAAC;QACjC,eAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,GAAG,EAAE,CAAC;QAChC,eAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC;QAClC,eAAK,CAAC,QAAQ,CAAC,gBAAgB,GAAG,CAAC,MAAM,EAAE,EAAE;YAC5C,IAAI,MAAM,YAAY,eAAe,EAAE,CAAC;gBACvC,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC1B,CAAC;YACD,OAAO,IAAA,cAAS,EAAC,MAAM,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;QACtD,CAAC,CAAC;QAGF,eAAK,CAAC,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC;QAG7B,eAAK,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;YAEzC,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC/B,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC7C,CAAC;YAED,IAAA,4BAAc,EAAC,MAAM,CAAC,CAAC;YACvB,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAE3B,OAAO,MAAM,CAAC;QACf,CAAC,CAAC,CAAC;IACJ,CAAC;AACF,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAkC;IAC7D,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,UAAU,CAAC,yBAAyB,CAAC,CAAC,EAAE,CAAC;QAC5F,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,cAAS,CAAC,GAAG,CAAC,iBAAQ,CAAC,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;IACzE,CAAC;AACF,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { AxiosRequestConfig, AxiosResponse } from 'axios';
2
+ import FormData from 'form-data';
3
+ import type { AgentOptions } from 'https';
4
+ import { type IHttpRequestOptions, type IRequestOptions, type IgnoreStatusErrorConfig } from 'n8n-workflow';
5
+ import type { SsrfBridge } from '../ssrf';
6
+ export declare function throwIfDomainNotAllowed(configOrUrl: AxiosRequestConfig | string, allowedDomains?: string): void;
7
+ export declare function tryParseUrl(url: string): URL | null;
8
+ export declare function isIgnoreStatusErrorConfig(ignoreHttpStatusErrors: unknown): ignoreHttpStatusErrors is IgnoreStatusErrorConfig;
9
+ export declare function searchForHeader(config: AxiosRequestConfig, headerName: string): string | undefined;
10
+ export declare const getHostFromRequestObject: (requestObject: Partial<{
11
+ url: string;
12
+ uri: string;
13
+ baseURL: string;
14
+ }>) => string | null;
15
+ export declare const getBeforeRedirectFn: (agentOptions: AgentOptions, axiosConfig: AxiosRequestConfig, proxyConfig: IHttpRequestOptions["proxy"] | string | undefined, sendCredentialsOnCrossOriginRedirect: boolean, allowedDomains?: string, ssrfBridge?: SsrfBridge) => (redirectedRequest: Record<string, any>) => void;
16
+ export declare function digestAuthAxiosConfig(axiosConfig: AxiosRequestConfig, response: AxiosResponse, auth: AxiosRequestConfig['auth']): AxiosRequestConfig;
17
+ export declare const createFormDataObject: (data: Record<string, unknown>) => FormData;
18
+ export declare function isFormDataInstance(data: unknown): data is FormData;
19
+ export declare function generateContentLengthHeader(config: AxiosRequestConfig): Promise<void>;
20
+ export declare function getUrlFromProxyConfig(proxyConfig: IHttpRequestOptions['proxy'] | string): string | null;
21
+ export declare function buildTargetUrl(url?: string, baseURL?: string): string | undefined;
22
+ export declare function setAxiosAgents(config: AxiosRequestConfig, agentOptions?: AgentOptions, proxyConfig?: IHttpRequestOptions['proxy'] | string, secureLookup?: ReturnType<SsrfBridge['createSecureLookup']>): void;
23
+ export declare function validateUrlSsrf(url: string | undefined, ssrfBridge?: SsrfBridge): Promise<void>;
24
+ export declare function resolveLegacyRequestUrl(requestObject: IRequestOptions): string | undefined;
@@ -0,0 +1,257 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createFormDataObject = exports.getBeforeRedirectFn = exports.getHostFromRequestObject = void 0;
7
+ exports.throwIfDomainNotAllowed = throwIfDomainNotAllowed;
8
+ exports.tryParseUrl = tryParseUrl;
9
+ exports.isIgnoreStatusErrorConfig = isIgnoreStatusErrorConfig;
10
+ exports.searchForHeader = searchForHeader;
11
+ exports.digestAuthAxiosConfig = digestAuthAxiosConfig;
12
+ exports.isFormDataInstance = isFormDataInstance;
13
+ exports.generateContentLengthHeader = generateContentLengthHeader;
14
+ exports.getUrlFromProxyConfig = getUrlFromProxyConfig;
15
+ exports.buildTargetUrl = buildTargetUrl;
16
+ exports.setAxiosAgents = setAxiosAgents;
17
+ exports.validateUrlSsrf = validateUrlSsrf;
18
+ exports.resolveLegacyRequestUrl = resolveLegacyRequestUrl;
19
+ const backend_common_1 = require("@n8n/backend-common");
20
+ const di_1 = require("@n8n/di");
21
+ const axios_1 = __importDefault(require("axios"));
22
+ const crypto_1 = __importDefault(require("crypto"));
23
+ const form_data_1 = __importDefault(require("form-data"));
24
+ const n8n_workflow_1 = require("n8n-workflow");
25
+ const http_proxy_1 = require("./http-proxy");
26
+ function throwIfDomainNotAllowed(configOrUrl, allowedDomains) {
27
+ const url = typeof configOrUrl === 'string' ? configOrUrl : axios_1.default.getUri(configOrUrl);
28
+ (0, n8n_workflow_1.assertUrlAllowed)({ url, allowedDomains });
29
+ }
30
+ function tryParseUrl(url) {
31
+ try {
32
+ return new URL(url);
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ }
38
+ function isIgnoreStatusErrorConfig(ignoreHttpStatusErrors) {
39
+ return (typeof ignoreHttpStatusErrors === 'object' &&
40
+ ignoreHttpStatusErrors !== null &&
41
+ 'ignore' in ignoreHttpStatusErrors &&
42
+ ignoreHttpStatusErrors.ignore === true);
43
+ }
44
+ function searchForHeader(config, headerName) {
45
+ if (config.headers === undefined) {
46
+ return undefined;
47
+ }
48
+ const headerNames = Object.keys(config.headers);
49
+ headerName = headerName.toLowerCase();
50
+ return headerNames.find((thisHeader) => thisHeader.toLowerCase() === headerName);
51
+ }
52
+ const getHostFromRequestObject = (requestObject) => {
53
+ try {
54
+ const url = (requestObject.url ?? requestObject.uri);
55
+ return new URL(url, requestObject.baseURL).hostname;
56
+ }
57
+ catch (error) {
58
+ return null;
59
+ }
60
+ };
61
+ exports.getHostFromRequestObject = getHostFromRequestObject;
62
+ const getBeforeRedirectFn = (agentOptions, axiosConfig, proxyConfig, sendCredentialsOnCrossOriginRedirect, allowedDomains, ssrfBridge) => (redirectedRequest) => {
63
+ throwIfDomainNotAllowed(redirectedRequest.href, allowedDomains);
64
+ if (ssrfBridge) {
65
+ ssrfBridge.validateRedirectSync(redirectedRequest.href);
66
+ }
67
+ const redirectAgentOptions = {
68
+ ...agentOptions,
69
+ servername: redirectedRequest.hostname,
70
+ };
71
+ const customProxyUrl = proxyConfig ? getUrlFromProxyConfig(proxyConfig) : null;
72
+ const effectiveRedirectOptions = ssrfBridge && !customProxyUrl
73
+ ? { ...redirectAgentOptions, lookup: ssrfBridge.createSecureLookup() }
74
+ : redirectAgentOptions;
75
+ const targetUrl = redirectedRequest.href;
76
+ const httpAgent = (0, http_proxy_1.createHttpProxyAgent)(customProxyUrl, targetUrl, effectiveRedirectOptions);
77
+ const httpsAgent = (0, http_proxy_1.createHttpsProxyAgent)(customProxyUrl, targetUrl, effectiveRedirectOptions);
78
+ redirectedRequest.agent = redirectedRequest.href.startsWith('https://')
79
+ ? httpsAgent
80
+ : httpAgent;
81
+ redirectedRequest.agents = { http: httpAgent, https: httpsAgent };
82
+ const originalUrl = axiosConfig.baseURL
83
+ ? new URL(axiosConfig.url ?? '', axiosConfig.baseURL)
84
+ : new URL(axiosConfig.url ?? '');
85
+ const originalOrigin = originalUrl.origin;
86
+ const targetOrigin = new URL(targetUrl).origin;
87
+ if (originalOrigin === targetOrigin || sendCredentialsOnCrossOriginRedirect) {
88
+ if (axiosConfig.headers?.Authorization) {
89
+ redirectedRequest.headers.Authorization = axiosConfig.headers.Authorization;
90
+ }
91
+ if (axiosConfig.auth) {
92
+ redirectedRequest.auth = `${axiosConfig.auth.username}:${axiosConfig.auth.password}`;
93
+ }
94
+ }
95
+ };
96
+ exports.getBeforeRedirectFn = getBeforeRedirectFn;
97
+ function digestAuthAxiosConfig(axiosConfig, response, auth) {
98
+ const authDetails = response.headers['www-authenticate']
99
+ .split(',')
100
+ .map((v) => v.split('='));
101
+ if (authDetails) {
102
+ const nonceCount = '000000001';
103
+ const cnonce = crypto_1.default.randomBytes(24).toString('hex');
104
+ const realm = authDetails
105
+ .find((el) => el[0].toLowerCase().indexOf('realm') > -1)[1]
106
+ .replace(/"/g, '');
107
+ const opaqueKV = authDetails.find((el) => el[0].toLowerCase().indexOf('opaque') > -1);
108
+ const opaque = opaqueKV ? opaqueKV[1].replace(/"/g, '') : undefined;
109
+ const nonce = authDetails
110
+ .find((el) => el[0].toLowerCase().indexOf('nonce') > -1)[1]
111
+ .replace(/"/g, '');
112
+ const ha1 = crypto_1.default
113
+ .createHash('md5')
114
+ .update(`${auth?.username}:${realm}:${auth?.password}`)
115
+ .digest('hex');
116
+ const url = new URL(axios_1.default.getUri(axiosConfig));
117
+ const path = url.pathname + url.search;
118
+ const ha2 = crypto_1.default
119
+ .createHash('md5')
120
+ .update(`${axiosConfig.method ?? 'GET'}:${path}`)
121
+ .digest('hex');
122
+ const response = crypto_1.default
123
+ .createHash('md5')
124
+ .update(`${ha1}:${nonce}:${nonceCount}:${cnonce}:auth:${ha2}`)
125
+ .digest('hex');
126
+ let authorization = `Digest username="${auth?.username}",realm="${realm}",` +
127
+ `nonce="${nonce}",uri="${path}",qop="auth",algorithm="MD5",` +
128
+ `response="${response}",nc="${nonceCount}",cnonce="${cnonce}"`;
129
+ if (opaque) {
130
+ authorization += `,opaque="${opaque}"`;
131
+ }
132
+ if (axiosConfig.headers) {
133
+ axiosConfig.headers.authorization = authorization;
134
+ }
135
+ else {
136
+ axiosConfig.headers = { authorization };
137
+ }
138
+ }
139
+ return axiosConfig;
140
+ }
141
+ const pushFormDataValue = (form, key, value) => {
142
+ if (value?.hasOwnProperty('value') && value.hasOwnProperty('options')) {
143
+ form.append(key, value.value, value.options);
144
+ }
145
+ else {
146
+ form.append(key, value);
147
+ }
148
+ };
149
+ const createFormDataObject = (data) => {
150
+ const formData = new form_data_1.default();
151
+ const keys = Object.keys(data);
152
+ keys.forEach((key) => {
153
+ const formField = data[key];
154
+ if (formField instanceof Array) {
155
+ formField.forEach((item) => {
156
+ pushFormDataValue(formData, key, item);
157
+ });
158
+ }
159
+ else {
160
+ pushFormDataValue(formData, key, formField);
161
+ }
162
+ });
163
+ return formData;
164
+ };
165
+ exports.createFormDataObject = createFormDataObject;
166
+ function isFormDataInstance(data) {
167
+ return (data instanceof form_data_1.default ||
168
+ (typeof data === 'object' &&
169
+ data !== null &&
170
+ 'getHeaders' in data &&
171
+ typeof data.getHeaders === 'function' &&
172
+ 'append' in data &&
173
+ typeof data.append === 'function'));
174
+ }
175
+ async function generateContentLengthHeader(config) {
176
+ if (!isFormDataInstance(config.data)) {
177
+ return;
178
+ }
179
+ try {
180
+ const length = await new Promise((res, rej) => {
181
+ config.data.getLength((error, dataLength) => {
182
+ if (error)
183
+ rej(error);
184
+ else
185
+ res(dataLength);
186
+ });
187
+ });
188
+ config.headers = {
189
+ ...config.headers,
190
+ 'content-length': length,
191
+ };
192
+ }
193
+ catch (error) {
194
+ di_1.Container.get(backend_common_1.Logger).error('Unable to calculate form data length', { error });
195
+ }
196
+ }
197
+ function getUrlFromProxyConfig(proxyConfig) {
198
+ if (typeof proxyConfig === 'string') {
199
+ const isValidUrl = !!tryParseUrl(proxyConfig);
200
+ return isValidUrl ? proxyConfig : null;
201
+ }
202
+ if (!proxyConfig?.host)
203
+ return null;
204
+ const { protocol, host, port, auth } = proxyConfig;
205
+ const safeProtocol = protocol?.endsWith(':') ? protocol.slice(0, -1) : (protocol ?? 'http');
206
+ try {
207
+ const url = new URL(`${safeProtocol}://${host}`);
208
+ if (port !== undefined)
209
+ url.port = String(port);
210
+ if (auth?.username) {
211
+ url.username = auth.username;
212
+ url.password = auth.password ?? '';
213
+ }
214
+ return url.href;
215
+ }
216
+ catch {
217
+ return null;
218
+ }
219
+ }
220
+ function buildTargetUrl(url, baseURL) {
221
+ if (!url)
222
+ return undefined;
223
+ try {
224
+ return baseURL ? new URL(url, baseURL).href : url;
225
+ }
226
+ catch {
227
+ return undefined;
228
+ }
229
+ }
230
+ function setAxiosAgents(config, agentOptions, proxyConfig, secureLookup) {
231
+ if (config.httpAgent || config.httpsAgent)
232
+ return;
233
+ const customProxyUrl = getUrlFromProxyConfig(proxyConfig);
234
+ const targetUrl = buildTargetUrl(config.url, config.baseURL);
235
+ if (!targetUrl)
236
+ return;
237
+ const effectiveOptions = secureLookup && !customProxyUrl ? { ...agentOptions, lookup: secureLookup } : agentOptions;
238
+ config.httpAgent = (0, http_proxy_1.createHttpProxyAgent)(customProxyUrl, targetUrl, effectiveOptions);
239
+ config.httpsAgent = (0, http_proxy_1.createHttpsProxyAgent)(customProxyUrl, targetUrl, effectiveOptions);
240
+ }
241
+ async function validateUrlSsrf(url, ssrfBridge) {
242
+ if (!ssrfBridge || !url)
243
+ return;
244
+ const parsed = tryParseUrl(url);
245
+ if (!parsed)
246
+ return;
247
+ const result = await ssrfBridge.validateUrl(parsed);
248
+ if (!result.ok) {
249
+ throw result.error;
250
+ }
251
+ }
252
+ function resolveLegacyRequestUrl(requestObject) {
253
+ const rawUrl = requestObject.uri?.toString() ?? requestObject.url?.toString();
254
+ const baseURL = requestObject.baseURL?.toString();
255
+ return buildTargetUrl(rawUrl, baseURL) ?? rawUrl;
256
+ }
257
+ //# sourceMappingURL=axios-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"axios-utils.js","sourceRoot":"","sources":["../../src/http/axios-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { Readable } from 'stream';
2
+ export declare function streamToBuffer(stream: Readable): Promise<Buffer>;
3
+ export declare function binaryToBuffer(body: Buffer | Readable): Promise<Buffer>;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.streamToBuffer = streamToBuffer;
4
+ exports.binaryToBuffer = binaryToBuffer;
5
+ const n8n_workflow_1 = require("n8n-workflow");
6
+ async function streamToBuffer(stream) {
7
+ return await new Promise((resolve, reject) => {
8
+ const chunks = [];
9
+ stream.on('data', (chunk) => chunks.push(chunk));
10
+ stream.on('end', () => resolve(Buffer.concat(chunks)));
11
+ stream.once('error', (cause) => {
12
+ if ('code' in cause && cause.code === 'Z_DATA_ERROR')
13
+ reject(new n8n_workflow_1.UnexpectedError('Failed to decompress response', { cause }));
14
+ else
15
+ reject(cause);
16
+ });
17
+ });
18
+ }
19
+ async function binaryToBuffer(body) {
20
+ if (Buffer.isBuffer(body))
21
+ return body;
22
+ return await streamToBuffer(body);
23
+ }
24
+ //# sourceMappingURL=binary-buffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary-buffer.js","sourceRoot":"","sources":["../../src/http/binary-buffer.ts"],"names":[],"mappings":";;AAIA,wCAWC;AAGD,wCAGC;AArBD,+CAA+C;AAIxC,KAAK,UAAU,cAAc,CAAC,MAAgB;IACpD,OAAO,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACpD,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACzD,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC9B,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc;gBACnD,MAAM,CAAC,IAAI,8BAAe,CAAC,+BAA+B,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;;gBACpE,MAAM,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC;AAGM,KAAK,UAAU,cAAc,CAAC,IAAuB;IAC3D,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { Readable } from 'stream';
2
+ export declare function binaryToString(body: Buffer | Readable, encoding?: string): Promise<string>;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.binaryToString = binaryToString;
4
+ const http_1 = require("http");
5
+ const iconv_lite_1 = require("iconv-lite");
6
+ const binary_buffer_1 = require("./binary-buffer");
7
+ const parse_incoming_message_1 = require("./parse-incoming-message");
8
+ async function binaryToString(body, encoding) {
9
+ if (!encoding && body instanceof http_1.IncomingMessage) {
10
+ (0, parse_incoming_message_1.parseIncomingMessage)(body);
11
+ encoding = body.encoding;
12
+ }
13
+ const buffer = await (0, binary_buffer_1.binaryToBuffer)(body);
14
+ return (0, iconv_lite_1.decode)(buffer, encoding ?? 'utf-8');
15
+ }
16
+ //# sourceMappingURL=binary-string.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binary-string.js","sourceRoot":"","sources":["../../src/http/binary-string.ts"],"names":[],"mappings":";;AAWA,wCAOC;AAlBD,+BAAuC;AACvC,2CAAoC;AAGpC,mDAAiD;AACjD,qEAAgE;AAMzD,KAAK,UAAU,cAAc,CAAC,IAAuB,EAAE,QAAiB;IAC9E,IAAI,CAAC,QAAQ,IAAI,IAAI,YAAY,sBAAe,EAAE,CAAC;QAClD,IAAA,6CAAoB,EAAC,IAAI,CAAC,CAAC;QAC3B,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC1B,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,IAAA,8BAAc,EAAC,IAAI,CAAC,CAAC;IAC1C,OAAO,IAAA,mBAAM,EAAC,MAAM,EAAE,QAAQ,IAAI,OAAO,CAAC,CAAC;AAC5C,CAAC"}