@zhixuan92/multi-model-agent-core 4.7.19 → 4.8.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/README.md +4 -4
- package/dist/config/schema.d.ts +2 -20
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +9 -80
- package/dist/config/schema.js.map +1 -1
- package/dist/events/task-envelope.d.ts +10 -1
- package/dist/events/task-envelope.d.ts.map +1 -1
- package/dist/events/task-envelope.js +4 -1
- package/dist/events/task-envelope.js.map +1 -1
- package/dist/events/wire-schema.d.ts +4 -0
- package/dist/events/wire-schema.d.ts.map +1 -1
- package/dist/events/wire-schema.js +3 -3
- package/dist/events/wire-schema.js.map +1 -1
- package/dist/journal/default-schema.d.ts +2 -0
- package/dist/journal/default-schema.d.ts.map +1 -0
- package/dist/journal/default-schema.js +27 -0
- package/dist/journal/default-schema.js.map +1 -0
- package/dist/journal/types.d.ts +22 -0
- package/dist/journal/types.d.ts.map +1 -0
- package/dist/journal/types.js +5 -0
- package/dist/journal/types.js.map +1 -0
- package/dist/lifecycle/annotate-parser.js +1 -1
- package/dist/lifecycle/annotate-parser.js.map +1 -1
- package/dist/lifecycle/derive-completion.js +1 -1
- package/dist/lifecycle/derive-completion.js.map +1 -1
- package/dist/lifecycle/handlers/annotate-stage.d.ts.map +1 -1
- package/dist/lifecycle/handlers/annotate-stage.js +9 -3
- package/dist/lifecycle/handlers/annotate-stage.js.map +1 -1
- package/dist/lifecycle/handlers/baseline-handlers.d.ts.map +1 -1
- package/dist/lifecycle/handlers/baseline-handlers.js +10 -0
- package/dist/lifecycle/handlers/baseline-handlers.js.map +1 -1
- package/dist/lifecycle/handlers/compose-commit-message.d.ts +15 -0
- package/dist/lifecycle/handlers/compose-commit-message.d.ts.map +1 -0
- package/dist/lifecycle/handlers/compose-commit-message.js +227 -0
- package/dist/lifecycle/handlers/compose-commit-message.js.map +1 -0
- package/dist/lifecycle/handlers/enrich-runtime-result.d.ts.map +1 -1
- package/dist/lifecycle/handlers/enrich-runtime-result.js +31 -0
- package/dist/lifecycle/handlers/enrich-runtime-result.js.map +1 -1
- package/dist/lifecycle/handlers/git-commit-handler.d.ts.map +1 -1
- package/dist/lifecycle/handlers/git-commit-handler.js +2 -15
- package/dist/lifecycle/handlers/git-commit-handler.js.map +1 -1
- package/dist/lifecycle/handlers/implement-stage.d.ts.map +1 -1
- package/dist/lifecycle/handlers/implement-stage.js +4 -1
- package/dist/lifecycle/handlers/implement-stage.js.map +1 -1
- package/dist/lifecycle/handlers/journal-review-prompt.d.ts +7 -0
- package/dist/lifecycle/handlers/journal-review-prompt.d.ts.map +1 -0
- package/dist/lifecycle/handlers/journal-review-prompt.js +54 -0
- package/dist/lifecycle/handlers/journal-review-prompt.js.map +1 -0
- package/dist/lifecycle/handlers/quality-review-prompt.d.ts +1 -0
- package/dist/lifecycle/handlers/quality-review-prompt.d.ts.map +1 -1
- package/dist/lifecycle/handlers/quality-review-prompt.js +8 -0
- package/dist/lifecycle/handlers/quality-review-prompt.js.map +1 -1
- package/dist/lifecycle/handlers/review-stage.d.ts.map +1 -1
- package/dist/lifecycle/handlers/review-stage.js +57 -13
- package/dist/lifecycle/handlers/review-stage.js.map +1 -1
- package/dist/lifecycle/handlers/rework-stage.d.ts.map +1 -1
- package/dist/lifecycle/handlers/rework-stage.js +3 -0
- package/dist/lifecycle/handlers/rework-stage.js.map +1 -1
- package/dist/lifecycle/handlers/spec-review-prompt.d.ts +1 -0
- package/dist/lifecycle/handlers/spec-review-prompt.d.ts.map +1 -1
- package/dist/lifecycle/handlers/spec-review-prompt.js +8 -0
- package/dist/lifecycle/handlers/spec-review-prompt.js.map +1 -1
- package/dist/lifecycle/handlers/terminal-handlers.d.ts +25 -1
- package/dist/lifecycle/handlers/terminal-handlers.d.ts.map +1 -1
- package/dist/lifecycle/handlers/terminal-handlers.js +55 -19
- package/dist/lifecycle/handlers/terminal-handlers.js.map +1 -1
- package/dist/lifecycle/perform-implementation.d.ts.map +1 -1
- package/dist/lifecycle/perform-implementation.js +7 -4
- package/dist/lifecycle/perform-implementation.js.map +1 -1
- package/dist/lifecycle/read-route-criteria.d.ts +3 -2
- package/dist/lifecycle/read-route-criteria.d.ts.map +1 -1
- package/dist/lifecycle/read-route-criteria.js +2 -0
- package/dist/lifecycle/read-route-criteria.js.map +1 -1
- package/dist/lifecycle/research-pre-loop.d.ts +5 -4
- package/dist/lifecycle/research-pre-loop.d.ts.map +1 -1
- package/dist/lifecycle/research-pre-loop.js +7 -10
- package/dist/lifecycle/research-pre-loop.js.map +1 -1
- package/dist/lifecycle/stage-io.d.ts +8 -4
- package/dist/lifecycle/stage-io.d.ts.map +1 -1
- package/dist/lifecycle/stage-io.js +2 -2
- package/dist/lifecycle/stage-io.js.map +1 -1
- package/dist/lifecycle/stage-plan-types.d.ts +1 -1
- package/dist/lifecycle/stage-plan-types.d.ts.map +1 -1
- package/dist/lifecycle/stage-progression.d.ts.map +1 -1
- package/dist/lifecycle/stage-progression.js +2 -0
- package/dist/lifecycle/stage-progression.js.map +1 -1
- package/dist/lifecycle/task-runner.d.ts.map +1 -1
- package/dist/lifecycle/task-runner.js +6 -1
- package/dist/lifecycle/task-runner.js.map +1 -1
- package/dist/lifecycle/worker-output-contract.d.ts +3 -1
- package/dist/lifecycle/worker-output-contract.d.ts.map +1 -1
- package/dist/lifecycle/worker-output-contract.js +4 -1
- package/dist/lifecycle/worker-output-contract.js.map +1 -1
- package/dist/reporting/headline-templates/journal-recall.d.ts +3 -0
- package/dist/reporting/headline-templates/journal-recall.d.ts.map +1 -0
- package/dist/reporting/headline-templates/journal-recall.js +9 -0
- package/dist/reporting/headline-templates/journal-recall.js.map +1 -0
- package/dist/reporting/headline-templates/journal.d.ts +3 -0
- package/dist/reporting/headline-templates/journal.d.ts.map +1 -0
- package/dist/reporting/headline-templates/journal.js +17 -0
- package/dist/reporting/headline-templates/journal.js.map +1 -0
- package/dist/reporting/report-parser-slots/journal-report.d.ts +8 -0
- package/dist/reporting/report-parser-slots/journal-report.d.ts.map +1 -0
- package/dist/reporting/report-parser-slots/journal-report.js +12 -0
- package/dist/reporting/report-parser-slots/journal-report.js.map +1 -0
- package/dist/reporting/terminal-report-markdown.d.ts +13 -0
- package/dist/reporting/terminal-report-markdown.d.ts.map +1 -0
- package/dist/reporting/terminal-report-markdown.js +31 -0
- package/dist/reporting/terminal-report-markdown.js.map +1 -0
- package/dist/research/adapters/index.d.ts +0 -1
- package/dist/research/adapters/index.d.ts.map +1 -1
- package/dist/research/adapters/index.js +0 -3
- package/dist/research/adapters/index.js.map +1 -1
- package/dist/research/adapters/types.d.ts +1 -1
- package/dist/research/adapters/types.d.ts.map +1 -1
- package/dist/research/evidence-pack.d.ts +19 -1
- package/dist/research/evidence-pack.d.ts.map +1 -1
- package/dist/research/evidence-pack.js +36 -1
- package/dist/research/evidence-pack.js.map +1 -1
- package/dist/research/orchestrator.d.ts +0 -4
- package/dist/research/orchestrator.d.ts.map +1 -1
- package/dist/research/orchestrator.js +4 -53
- package/dist/research/orchestrator.js.map +1 -1
- package/dist/research/query-plan.d.ts +0 -2
- package/dist/research/query-plan.d.ts.map +1 -1
- package/dist/research/query-plan.js +1 -8
- package/dist/research/query-plan.js.map +1 -1
- package/dist/research/user-agent.js +1 -1
- package/dist/research/user-agent.js.map +1 -1
- package/dist/research/web-search.d.ts +2 -1
- package/dist/research/web-search.d.ts.map +1 -1
- package/dist/research/web-search.js +31 -7
- package/dist/research/web-search.js.map +1 -1
- package/dist/stores/batch-registry.d.ts +1 -1
- package/dist/stores/batch-registry.d.ts.map +1 -1
- package/dist/stores/batch-registry.js +4 -4
- package/dist/stores/batch-registry.js.map +1 -1
- package/dist/tool-surface/register-all-tools.d.ts.map +1 -1
- package/dist/tool-surface/register-all-tools.js +4 -0
- package/dist/tool-surface/register-all-tools.js.map +1 -1
- package/dist/tools/delegate/brief-slot.d.ts +3 -0
- package/dist/tools/delegate/brief-slot.d.ts.map +1 -1
- package/dist/tools/delegate/brief-slot.js +1 -0
- package/dist/tools/delegate/brief-slot.js.map +1 -1
- package/dist/tools/delegate/tool-config.d.ts.map +1 -1
- package/dist/tools/delegate/tool-config.js +1 -0
- package/dist/tools/delegate/tool-config.js.map +1 -1
- package/dist/tools/execute-plan/tool-config.d.ts.map +1 -1
- package/dist/tools/execute-plan/tool-config.js +3 -0
- package/dist/tools/execute-plan/tool-config.js.map +1 -1
- package/dist/tools/journal/recall/brief-slot.d.ts +7 -0
- package/dist/tools/journal/recall/brief-slot.d.ts.map +1 -0
- package/dist/tools/journal/recall/brief-slot.js +5 -0
- package/dist/tools/journal/recall/brief-slot.js.map +1 -0
- package/dist/tools/journal/recall/implementer-criteria.d.ts +9 -0
- package/dist/tools/journal/recall/implementer-criteria.d.ts.map +1 -0
- package/dist/tools/journal/recall/implementer-criteria.js +23 -0
- package/dist/tools/journal/recall/implementer-criteria.js.map +1 -0
- package/dist/tools/journal/recall/schema.d.ts +54 -0
- package/dist/tools/journal/recall/schema.d.ts.map +1 -0
- package/dist/tools/journal/recall/schema.js +10 -0
- package/dist/tools/journal/recall/schema.js.map +1 -0
- package/dist/tools/journal/recall/subtypes.d.ts +4 -0
- package/dist/tools/journal/recall/subtypes.d.ts.map +1 -0
- package/dist/tools/journal/recall/subtypes.js +25 -0
- package/dist/tools/journal/recall/subtypes.js.map +1 -0
- package/dist/tools/journal/recall/tool-config.d.ts +8 -0
- package/dist/tools/journal/recall/tool-config.d.ts.map +1 -0
- package/dist/tools/journal/recall/tool-config.js +46 -0
- package/dist/tools/journal/recall/tool-config.js.map +1 -0
- package/dist/tools/journal/record/brief-slot.d.ts +14 -0
- package/dist/tools/journal/record/brief-slot.d.ts.map +1 -0
- package/dist/tools/journal/record/brief-slot.js +18 -0
- package/dist/tools/journal/record/brief-slot.js.map +1 -0
- package/dist/tools/journal/record/implementer-criteria.d.ts +6 -0
- package/dist/tools/journal/record/implementer-criteria.d.ts.map +1 -0
- package/dist/tools/journal/record/implementer-criteria.js +17 -0
- package/dist/tools/journal/record/implementer-criteria.js.map +1 -0
- package/dist/tools/journal/record/schema.d.ts +55 -0
- package/dist/tools/journal/record/schema.d.ts.map +1 -0
- package/dist/tools/journal/record/schema.js +13 -0
- package/dist/tools/journal/record/schema.js.map +1 -0
- package/dist/tools/journal/record/tool-config.d.ts +7 -0
- package/dist/tools/journal/record/tool-config.d.ts.map +1 -0
- package/dist/tools/journal/record/tool-config.js +40 -0
- package/dist/tools/journal/record/tool-config.js.map +1 -0
- package/dist/tools/research/brief-slot.d.ts +0 -2
- package/dist/tools/research/brief-slot.d.ts.map +1 -1
- package/dist/tools/research/brief-slot.js.map +1 -1
- package/dist/tools/research/implementer-criteria.d.ts +0 -1
- package/dist/tools/research/implementer-criteria.d.ts.map +1 -1
- package/dist/tools/research/implementer-criteria.js +3 -15
- package/dist/tools/research/implementer-criteria.js.map +1 -1
- package/dist/tools/research/tool-config.d.ts.map +1 -1
- package/dist/tools/research/tool-config.js +0 -1
- package/dist/tools/research/tool-config.js.map +1 -1
- package/dist/types/task-spec.d.ts +2 -1
- package/dist/types/task-spec.d.ts.map +1 -1
- package/package.json +17 -1
- package/dist/research/adapters/generic-rss.d.ts +0 -8
- package/dist/research/adapters/generic-rss.d.ts.map +0 -1
- package/dist/research/adapters/generic-rss.js +0 -26
- package/dist/research/adapters/generic-rss.js.map +0 -1
- package/dist/research/ssrf-guard.d.ts +0 -12
- package/dist/research/ssrf-guard.d.ts.map +0 -1
- package/dist/research/ssrf-guard.js +0 -209
- package/dist/research/ssrf-guard.js.map +0 -1
- package/dist/research/untrusted-content.d.ts +0 -13
- package/dist/research/untrusted-content.d.ts.map +0 -1
- package/dist/research/untrusted-content.js +0 -9
- package/dist/research/untrusted-content.js.map +0 -1
- package/dist/research/web-fetch-helpers.d.ts +0 -44
- package/dist/research/web-fetch-helpers.d.ts.map +0 -1
- package/dist/research/web-fetch-helpers.js +0 -209
- package/dist/research/web-fetch-helpers.js.map +0 -1
- package/dist/research/web-fetch.d.ts +0 -55
- package/dist/research/web-fetch.d.ts.map +0 -1
- package/dist/research/web-fetch.js +0 -236
- package/dist/research/web-fetch.js.map +0 -1
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import { isIP } from 'node:net';
|
|
2
|
-
import { promises as dns } from 'node:dns';
|
|
3
|
-
export class SsrfBlocked extends Error {
|
|
4
|
-
code;
|
|
5
|
-
constructor(code, message) {
|
|
6
|
-
super(message);
|
|
7
|
-
this.code = code;
|
|
8
|
-
this.name = 'SsrfBlocked';
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
function ipv4ToInt(ip) {
|
|
12
|
-
const parts = ip.split('.').map(Number);
|
|
13
|
-
if (parts.length !== 4 || parts.some(p => Number.isNaN(p) || p < 0 || p > 255))
|
|
14
|
-
return null;
|
|
15
|
-
return ((parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8) | parts[3]) >>> 0;
|
|
16
|
-
}
|
|
17
|
-
const inRange = (n, base, mask) => {
|
|
18
|
-
const b = ipv4ToInt(base);
|
|
19
|
-
if (b === null)
|
|
20
|
-
return false;
|
|
21
|
-
const m = mask === 0 ? 0 : (~0 << (32 - mask)) >>> 0;
|
|
22
|
-
return (n & m) === (b & m);
|
|
23
|
-
};
|
|
24
|
-
const IPV4_SPECIAL_RANGES = [
|
|
25
|
-
['0.0.0.0', 8, 'unspecified'],
|
|
26
|
-
['127.0.0.0', 8, 'loopback'],
|
|
27
|
-
['10.0.0.0', 8, 'private'],
|
|
28
|
-
['172.16.0.0', 12, 'private'],
|
|
29
|
-
['192.168.0.0', 16, 'private'],
|
|
30
|
-
['100.64.0.0', 10, 'private'], // RFC 6598 CGNAT; opt-in allowable with private hosts.
|
|
31
|
-
['169.254.0.0', 16, 'link-local-or-metadata'],
|
|
32
|
-
// IANA IPv4 special-purpose ranges that are not normal public internet destinations.
|
|
33
|
-
['192.0.0.0', 24, 'broadcast-or-reserved'],
|
|
34
|
-
['192.0.2.0', 24, 'broadcast-or-reserved'], // TEST-NET-1
|
|
35
|
-
['198.18.0.0', 15, 'broadcast-or-reserved'], // benchmarking
|
|
36
|
-
['198.51.100.0', 24, 'broadcast-or-reserved'], // TEST-NET-2
|
|
37
|
-
['203.0.113.0', 24, 'broadcast-or-reserved'], // TEST-NET-3
|
|
38
|
-
['224.0.0.0', 4, 'multicast'],
|
|
39
|
-
['240.0.0.0', 4, 'broadcast-or-reserved'],
|
|
40
|
-
];
|
|
41
|
-
/**
|
|
42
|
-
* Extract a 32-bit unsigned int from a 4-hex-group region of an expanded IPv6
|
|
43
|
-
* address (used for IPv4-mapped and 6to4 embedded-IPv4 extraction).
|
|
44
|
-
*
|
|
45
|
-
* Returns null on malformed input. The caller stringifies back to dotted-quad
|
|
46
|
-
* via classifyIP, so we don't need pretty formatting here.
|
|
47
|
-
*/
|
|
48
|
-
function expandIPv6Groups(addr) {
|
|
49
|
-
// Split on '::' (at most once); pad missing groups with '0'.
|
|
50
|
-
const halves = addr.split('::');
|
|
51
|
-
if (halves.length > 2)
|
|
52
|
-
return null;
|
|
53
|
-
const left = halves[0] ? halves[0].split(':') : [];
|
|
54
|
-
const right = halves.length === 2 && halves[1] ? halves[1].split(':') : [];
|
|
55
|
-
const fill = 8 - (left.length + right.length);
|
|
56
|
-
if (fill < 0)
|
|
57
|
-
return null;
|
|
58
|
-
if (halves.length === 1 && left.length !== 8)
|
|
59
|
-
return null;
|
|
60
|
-
return [...left, ...Array(fill).fill('0'), ...right]
|
|
61
|
-
.map((g) => g.padStart(4, '0').toLowerCase());
|
|
62
|
-
}
|
|
63
|
-
function groupsToIPv4(g, startGroup) {
|
|
64
|
-
if (g.length < startGroup + 2)
|
|
65
|
-
return null;
|
|
66
|
-
const hi = parseInt(g[startGroup], 16);
|
|
67
|
-
const lo = parseInt(g[startGroup + 1], 16);
|
|
68
|
-
if (Number.isNaN(hi) || Number.isNaN(lo))
|
|
69
|
-
return null;
|
|
70
|
-
const a = (hi >> 8) & 0xff, b = hi & 0xff, c = (lo >> 8) & 0xff, d = lo & 0xff;
|
|
71
|
-
return `${a}.${b}.${c}.${d}`;
|
|
72
|
-
}
|
|
73
|
-
export function classifyIP(ip) {
|
|
74
|
-
const lower = ip.toLowerCase();
|
|
75
|
-
// Cloud-metadata ULAs (informal cloud-provider conventions; not IANA-registered)
|
|
76
|
-
// Checked before isIP because these patterns may use non-hex tokens like 'gcp'/'az'.
|
|
77
|
-
if (/^fd00:(ec2|gcp|az):/.test(lower))
|
|
78
|
-
return 'link-local-or-metadata';
|
|
79
|
-
const v = isIP(ip);
|
|
80
|
-
if (v === 4) {
|
|
81
|
-
const n = ipv4ToInt(ip);
|
|
82
|
-
if (n === null)
|
|
83
|
-
return 'broadcast-or-reserved';
|
|
84
|
-
if (n === 0xffffffff)
|
|
85
|
-
return 'broadcast-or-reserved';
|
|
86
|
-
for (const [base, mask, klass] of IPV4_SPECIAL_RANGES) {
|
|
87
|
-
if (inRange(n, base, mask))
|
|
88
|
-
return klass;
|
|
89
|
-
}
|
|
90
|
-
return 'public';
|
|
91
|
-
}
|
|
92
|
-
if (v === 6) {
|
|
93
|
-
if (lower === '::')
|
|
94
|
-
return 'unspecified';
|
|
95
|
-
if (lower === '::1')
|
|
96
|
-
return 'loopback';
|
|
97
|
-
// IPv4-mapped IPv6 (::ffff:a.b.c.d or ::ffff:HEXHEX:HEXHEX) — recurse on embedded IPv4
|
|
98
|
-
const v4mapped = lower.match(/^::ffff:(\d+\.\d+\.\d+\.\d+)$/);
|
|
99
|
-
if (v4mapped)
|
|
100
|
-
return classifyIP(v4mapped[1]);
|
|
101
|
-
const groups = expandIPv6Groups(lower);
|
|
102
|
-
if (groups && groups[0] === '0000' && groups[1] === '0000' && groups[2] === '0000'
|
|
103
|
-
&& groups[3] === '0000' && groups[4] === '0000' && groups[5] === 'ffff') {
|
|
104
|
-
const embedded = groupsToIPv4(groups, 6);
|
|
105
|
-
if (embedded)
|
|
106
|
-
return classifyIP(embedded);
|
|
107
|
-
}
|
|
108
|
-
// 6to4 (2002::/16) — embeds IPv4 at bits 16–47 (groups 1 + 2). Recurse.
|
|
109
|
-
if (groups && groups[0] === '2002') {
|
|
110
|
-
const embedded = groupsToIPv4(groups, 1);
|
|
111
|
-
if (embedded)
|
|
112
|
-
return classifyIP(embedded);
|
|
113
|
-
}
|
|
114
|
-
// fe80::/10 link-local (covers fe80–febf when interpreted strictly).
|
|
115
|
-
if (groups && /^fe[89ab]/.test(groups[0]))
|
|
116
|
-
return 'link-local-or-metadata';
|
|
117
|
-
// Locally-assigned ULA (fc00::/8) and randomly-assigned ULA (fd00::/8) → 'private'.
|
|
118
|
-
// The opt-in policy in spec §7.1 step 8 distinguishes these two halves;
|
|
119
|
-
// classifyIP only reports membership in the conditional-reject set.
|
|
120
|
-
if (groups && (groups[0].startsWith('fc') || groups[0].startsWith('fd'))) {
|
|
121
|
-
return 'private';
|
|
122
|
-
}
|
|
123
|
-
if (lower.startsWith('ff'))
|
|
124
|
-
return 'multicast';
|
|
125
|
-
// IANA IPv6 special-purpose ranges that are not normal public internet destinations.
|
|
126
|
-
if (groups && groups[0] === '2001' && groups[1] === '0db8')
|
|
127
|
-
return 'broadcast-or-reserved';
|
|
128
|
-
if (groups && groups[0] === '2001' && /^0[0-1]/.test(groups[1] ?? ''))
|
|
129
|
-
return 'broadcast-or-reserved';
|
|
130
|
-
// Note: `fec0::/10` was a deprecated site-local block (RFC 3879). Modern
|
|
131
|
-
// unicast addresses outside fc00::/7 (e.g. `fec1::1`) are **routable**
|
|
132
|
-
// under current IANA allocations — classify as public, NOT link-local.
|
|
133
|
-
return 'public';
|
|
134
|
-
}
|
|
135
|
-
return 'broadcast-or-reserved';
|
|
136
|
-
}
|
|
137
|
-
const isNoRecordsError = (error) => {
|
|
138
|
-
const code = error?.code;
|
|
139
|
-
return code === 'ENODATA' || code === 'ENOTFOUND' || code === 'ESERVFAIL';
|
|
140
|
-
};
|
|
141
|
-
const defaultResolve = async (host) => {
|
|
142
|
-
const [v4, v6] = await Promise.allSettled([
|
|
143
|
-
dns.resolve4(host),
|
|
144
|
-
dns.resolve6(host),
|
|
145
|
-
]);
|
|
146
|
-
const results = [];
|
|
147
|
-
if (v4.status === 'fulfilled')
|
|
148
|
-
results.push(...v4.value);
|
|
149
|
-
if (v6.status === 'fulfilled')
|
|
150
|
-
results.push(...v6.value);
|
|
151
|
-
if (results.length > 0)
|
|
152
|
-
return results;
|
|
153
|
-
const failures = [v4, v6].filter((r) => r.status === 'rejected');
|
|
154
|
-
if (failures.length > 0 && failures.some((r) => !isNoRecordsError(r.reason))) {
|
|
155
|
-
throw new Error('DNS resolution failed');
|
|
156
|
-
}
|
|
157
|
-
return results;
|
|
158
|
-
};
|
|
159
|
-
const BLOCKED_CLASSES_STRICT = new Set([
|
|
160
|
-
'loopback',
|
|
161
|
-
'private',
|
|
162
|
-
'link-local-or-metadata',
|
|
163
|
-
'unspecified',
|
|
164
|
-
'multicast',
|
|
165
|
-
'broadcast-or-reserved',
|
|
166
|
-
]);
|
|
167
|
-
const BLOCKED_CLASSES_PERMISSIVE = new Set([
|
|
168
|
-
'loopback',
|
|
169
|
-
'link-local-or-metadata',
|
|
170
|
-
'unspecified',
|
|
171
|
-
'multicast',
|
|
172
|
-
'broadcast-or-reserved',
|
|
173
|
-
]);
|
|
174
|
-
function isLocallyAssignedULA(ip) {
|
|
175
|
-
if (isIP(ip) !== 6)
|
|
176
|
-
return false;
|
|
177
|
-
const groups = expandIPv6Groups(ip.toLowerCase());
|
|
178
|
-
if (!groups)
|
|
179
|
-
return false;
|
|
180
|
-
return groups[0].startsWith('fc');
|
|
181
|
-
}
|
|
182
|
-
export async function resolveAndPin(host, options) {
|
|
183
|
-
const resolve = options.resolve ?? defaultResolve;
|
|
184
|
-
let ips;
|
|
185
|
-
try {
|
|
186
|
-
ips = await resolve(host);
|
|
187
|
-
}
|
|
188
|
-
catch {
|
|
189
|
-
throw new SsrfBlocked('web_fetch_dns_resolution_failed', `web_fetch_dns_resolution_failed: DNS resolution failed for host '${host}'`);
|
|
190
|
-
}
|
|
191
|
-
if (ips.length === 0) {
|
|
192
|
-
throw new SsrfBlocked('web_fetch_no_addresses', `web_fetch_no_addresses: no addresses resolved for host '${host}'`);
|
|
193
|
-
}
|
|
194
|
-
const blocked = options.allowPrivateForHost
|
|
195
|
-
? BLOCKED_CLASSES_PERMISSIVE
|
|
196
|
-
: BLOCKED_CLASSES_STRICT;
|
|
197
|
-
for (const ip of ips) {
|
|
198
|
-
const klass = classifyIP(ip);
|
|
199
|
-
if (blocked.has(klass)) {
|
|
200
|
-
throw new SsrfBlocked('web_fetch_private_ip_blocked', `web_fetch_private_ip_blocked: resolved IP class '${klass}' is not allowed for host '${host}'`);
|
|
201
|
-
}
|
|
202
|
-
// fc00::/8 locally-assigned ULA is always-reject, even in permissive mode
|
|
203
|
-
if (isLocallyAssignedULA(ip)) {
|
|
204
|
-
throw new SsrfBlocked('web_fetch_private_ip_blocked', `web_fetch_private_ip_blocked: resolved IP is locally-assigned ULA (fc00::/8), which is never allowed for host '${host}'`);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return ips[0];
|
|
208
|
-
}
|
|
209
|
-
//# sourceMappingURL=ssrf-guard.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ssrf-guard.js","sourceRoot":"","sources":["../../src/research/ssrf-guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export interface FetchedContent {
|
|
2
|
-
url: string;
|
|
3
|
-
host: string;
|
|
4
|
-
content: string;
|
|
5
|
-
}
|
|
6
|
-
export declare function wrapFetchedContent(c: FetchedContent): string;
|
|
7
|
-
export interface SearchHit {
|
|
8
|
-
title: string;
|
|
9
|
-
url: string;
|
|
10
|
-
snippet: string;
|
|
11
|
-
}
|
|
12
|
-
export declare function wrapSearchResults(hits: readonly SearchHit[]): string;
|
|
13
|
-
//# sourceMappingURL=untrusted-content.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"untrusted-content.d.ts","sourceRoot":"","sources":["../../src/research/untrusted-content.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,CAE5D;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,GAAG,MAAM,CAEpE"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
const escapeAttr = (s) => s.replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
|
|
2
|
-
const escapeBody = (s) => s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
3
|
-
export function wrapFetchedContent(c) {
|
|
4
|
-
return `<external-content url="${escapeAttr(c.url)}" host="${escapeAttr(c.host)}" trustLevel="untrusted">${escapeBody(c.content)}</external-content>`;
|
|
5
|
-
}
|
|
6
|
-
export function wrapSearchResults(hits) {
|
|
7
|
-
return `<external-search-results trustLevel="untrusted">${escapeBody(JSON.stringify(hits))}</external-search-results>`;
|
|
8
|
-
}
|
|
9
|
-
//# sourceMappingURL=untrusted-content.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"untrusted-content.js","sourceRoot":"","sources":["../../src/research/untrusted-content.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,EAAE,CAC/B,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAE/F,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,EAAE,CAC/B,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAQvE,MAAM,UAAU,kBAAkB,CAAC,CAAiB;IAClD,OAAO,0BAA0B,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,4BAA4B,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC;AACxJ,CAAC;AAQD,MAAM,UAAU,iBAAiB,CAAC,IAA0B;IAC1D,OAAO,mDAAmD,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,4BAA4B,CAAC;AACzH,CAAC"}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { WebFetchInput, WebFetchErr } from './web-fetch.js';
|
|
2
|
-
/** Max bytes to drain from a redirect response body before giving up. */
|
|
3
|
-
export declare const REDIRECT_DRAIN_CAP: number;
|
|
4
|
-
export declare const REDIRECT_ERR_CODE_MAP: Record<string, string>;
|
|
5
|
-
export interface ValidatedURL {
|
|
6
|
-
ok: true;
|
|
7
|
-
url: URL;
|
|
8
|
-
host: string;
|
|
9
|
-
pinnedIP: string;
|
|
10
|
-
}
|
|
11
|
-
export interface ValidationFailed {
|
|
12
|
-
ok: false;
|
|
13
|
-
reasonCode: string;
|
|
14
|
-
host?: string;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Races a promise against an AbortSignal. If the signal fires first, throws
|
|
18
|
-
* a DOMException with name 'AbortError' so callers can map it to timeout.
|
|
19
|
-
*/
|
|
20
|
-
export declare function withDeadline<T>(promise: Promise<T>, signal: AbortSignal): Promise<T>;
|
|
21
|
-
export declare function validateAndPinURL(raw: string, hostAllowlist: ReadonlySet<string>, privateNetworkHosts: ReadonlySet<string>, resolveIP: WebFetchInput['resolveIP'], signal: AbortSignal): Promise<ValidatedURL | ValidationFailed>;
|
|
22
|
-
export declare function extractContentType(headers: Record<string, string | string[] | undefined>): string;
|
|
23
|
-
export declare function isRedirect(status: number): boolean;
|
|
24
|
-
export declare function extractLocation(headers: Record<string, string | string[] | undefined>): string | null;
|
|
25
|
-
export declare function extractBodyFromHTML(html: string): string;
|
|
26
|
-
export declare function stripCredentialsFromURL(url: URL): boolean;
|
|
27
|
-
/**
|
|
28
|
-
* Read a response body with a byte cap and abort-signal awareness.
|
|
29
|
-
* Stream errors (non-abort) are re-thrown so the caller can map them to
|
|
30
|
-
* web_fetch_body_read_failed rather than silently returning partial content.
|
|
31
|
-
*/
|
|
32
|
-
export declare function readBody(body: AsyncIterable<Uint8Array | string> | null, maxBytes: number, signal: AbortSignal): Promise<{
|
|
33
|
-
text: string;
|
|
34
|
-
bytesReturned: number;
|
|
35
|
-
truncated: boolean;
|
|
36
|
-
}>;
|
|
37
|
-
/**
|
|
38
|
-
* Drain a response body with a size cap and abort-signal awareness.
|
|
39
|
-
* Used for redirect responses and rejected content types.
|
|
40
|
-
*/
|
|
41
|
-
export declare function drainBody(body: AsyncIterable<unknown> | null, signal: AbortSignal): Promise<void>;
|
|
42
|
-
export declare function isUndiciTimeout(err: unknown): boolean;
|
|
43
|
-
export declare function mapRequestError(err: unknown, signal: AbortSignal, host: string): WebFetchErr;
|
|
44
|
-
//# sourceMappingURL=web-fetch-helpers.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"web-fetch-helpers.d.ts","sourceRoot":"","sources":["../../src/research/web-fetch-helpers.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAEjE,yEAAyE;AACzE,eAAO,MAAM,kBAAkB,QAAY,CAAC;AAE5C,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAOxD,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,IAAI,CAAC;IACT,GAAG,EAAE,GAAG,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,KAAK,CAAC;IACV,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAgB1F;AAED,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,EAClC,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAAC,EACxC,SAAS,EAAE,aAAa,CAAC,WAAW,CAAC,EACrC,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,YAAY,GAAG,gBAAgB,CAAC,CAsC1C;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,MAAM,CASjG;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,IAAI,CAKrG;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAiBxD;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAKzD;AAED;;;;GAIG;AACH,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,aAAa,CAAC,UAAU,GAAG,MAAM,CAAC,GAAG,IAAI,EAC/C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,CAkCtE;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,IAAI,EACnC,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,IAAI,CAAC,CAoBf;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAMrD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAW5F"}
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import { isIP } from 'node:net';
|
|
2
|
-
import { Readability } from '@mozilla/readability';
|
|
3
|
-
import { JSDOM } from 'jsdom';
|
|
4
|
-
import { resolveAndPin, SsrfBlocked } from './ssrf-guard.js';
|
|
5
|
-
/** Max bytes to drain from a redirect response body before giving up. */
|
|
6
|
-
export const REDIRECT_DRAIN_CAP = 64 * 1024;
|
|
7
|
-
export const REDIRECT_ERR_CODE_MAP = {
|
|
8
|
-
web_fetch_off_allowlist: 'web_fetch_redirect_off_allowlist',
|
|
9
|
-
web_fetch_invalid_url: 'web_fetch_redirect_invalid_url',
|
|
10
|
-
web_fetch_invalid_scheme: 'web_fetch_redirect_scheme_downgrade',
|
|
11
|
-
web_fetch_ip_literal_blocked: 'web_fetch_redirect_ip_literal_blocked',
|
|
12
|
-
web_fetch_private_ip_blocked: 'web_fetch_redirect_private_ip_blocked',
|
|
13
|
-
web_fetch_reserved_ip_blocked: 'web_fetch_redirect_reserved_ip_blocked',
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* Races a promise against an AbortSignal. If the signal fires first, throws
|
|
17
|
-
* a DOMException with name 'AbortError' so callers can map it to timeout.
|
|
18
|
-
*/
|
|
19
|
-
export async function withDeadline(promise, signal) {
|
|
20
|
-
if (signal.aborted)
|
|
21
|
-
throw new DOMException('Aborted', 'AbortError');
|
|
22
|
-
return new Promise((resolve, reject) => {
|
|
23
|
-
const onAbort = () => reject(new DOMException('Aborted', 'AbortError'));
|
|
24
|
-
signal.addEventListener('abort', onAbort, { once: true });
|
|
25
|
-
promise.then((result) => {
|
|
26
|
-
signal.removeEventListener('abort', onAbort);
|
|
27
|
-
resolve(result);
|
|
28
|
-
}, (err) => {
|
|
29
|
-
signal.removeEventListener('abort', onAbort);
|
|
30
|
-
reject(err);
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
export async function validateAndPinURL(raw, hostAllowlist, privateNetworkHosts, resolveIP, signal) {
|
|
35
|
-
let url;
|
|
36
|
-
try {
|
|
37
|
-
url = new URL(raw);
|
|
38
|
-
}
|
|
39
|
-
catch {
|
|
40
|
-
return { ok: false, reasonCode: 'web_fetch_invalid_url' };
|
|
41
|
-
}
|
|
42
|
-
if (url.protocol !== 'https:') {
|
|
43
|
-
return { ok: false, reasonCode: 'web_fetch_invalid_scheme' };
|
|
44
|
-
}
|
|
45
|
-
const stripped = url.hostname.replace(/^\[|\]$/g, '');
|
|
46
|
-
if (isIP(stripped) !== 0) {
|
|
47
|
-
return { ok: false, reasonCode: 'web_fetch_ip_literal_blocked' };
|
|
48
|
-
}
|
|
49
|
-
const host = url.hostname.toLowerCase();
|
|
50
|
-
if (!hostAllowlist.has(host)) {
|
|
51
|
-
return { ok: false, reasonCode: 'web_fetch_off_allowlist', host };
|
|
52
|
-
}
|
|
53
|
-
const allowPrivate = privateNetworkHosts.has(host);
|
|
54
|
-
let pinnedIP;
|
|
55
|
-
try {
|
|
56
|
-
pinnedIP = await withDeadline(resolveAndPin(host, {
|
|
57
|
-
resolve: resolveIP ? async (h) => [await resolveIP(h)] : undefined,
|
|
58
|
-
allowPrivateForHost: allowPrivate,
|
|
59
|
-
}), signal);
|
|
60
|
-
}
|
|
61
|
-
catch (e) {
|
|
62
|
-
if (e instanceof DOMException && e.name === 'AbortError') {
|
|
63
|
-
throw e;
|
|
64
|
-
}
|
|
65
|
-
if (e instanceof SsrfBlocked) {
|
|
66
|
-
return { ok: false, reasonCode: e.code, host };
|
|
67
|
-
}
|
|
68
|
-
return { ok: false, reasonCode: 'web_fetch_dns_resolution_failed', host };
|
|
69
|
-
}
|
|
70
|
-
return { ok: true, url, host, pinnedIP };
|
|
71
|
-
}
|
|
72
|
-
export function extractContentType(headers) {
|
|
73
|
-
const raw = headers['content-type'];
|
|
74
|
-
if (typeof raw === 'string') {
|
|
75
|
-
return raw.split(';')[0].trim().toLowerCase();
|
|
76
|
-
}
|
|
77
|
-
if (Array.isArray(raw) && raw.length > 0) {
|
|
78
|
-
return String(raw[0]).split(';')[0].trim().toLowerCase();
|
|
79
|
-
}
|
|
80
|
-
return '';
|
|
81
|
-
}
|
|
82
|
-
export function isRedirect(status) {
|
|
83
|
-
return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
|
|
84
|
-
}
|
|
85
|
-
export function extractLocation(headers) {
|
|
86
|
-
const loc = headers['location'];
|
|
87
|
-
if (typeof loc === 'string')
|
|
88
|
-
return loc;
|
|
89
|
-
if (Array.isArray(loc) && loc.length > 0)
|
|
90
|
-
return String(loc[0]);
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
export function extractBodyFromHTML(html) {
|
|
94
|
-
let dom;
|
|
95
|
-
try {
|
|
96
|
-
dom = new JSDOM(html, { url: 'https://localhost/' });
|
|
97
|
-
const reader = new Readability(dom.window.document);
|
|
98
|
-
const article = reader.parse();
|
|
99
|
-
if (article?.textContent) {
|
|
100
|
-
return article.textContent;
|
|
101
|
-
}
|
|
102
|
-
return dom.window.document.body?.textContent?.trim() ?? html;
|
|
103
|
-
}
|
|
104
|
-
catch {
|
|
105
|
-
try {
|
|
106
|
-
return dom?.window.document.body?.textContent?.trim() || html;
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
return html;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
export function stripCredentialsFromURL(url) {
|
|
114
|
-
if (!url.username && !url.password)
|
|
115
|
-
return false;
|
|
116
|
-
url.username = '';
|
|
117
|
-
url.password = '';
|
|
118
|
-
return true;
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Read a response body with a byte cap and abort-signal awareness.
|
|
122
|
-
* Stream errors (non-abort) are re-thrown so the caller can map them to
|
|
123
|
-
* web_fetch_body_read_failed rather than silently returning partial content.
|
|
124
|
-
*/
|
|
125
|
-
export async function readBody(body, maxBytes, signal) {
|
|
126
|
-
if (!body)
|
|
127
|
-
return { text: '', bytesReturned: 0, truncated: false };
|
|
128
|
-
const chunks = [];
|
|
129
|
-
let total = 0;
|
|
130
|
-
let truncated = false;
|
|
131
|
-
for await (const chunk of body) {
|
|
132
|
-
if (signal.aborted) {
|
|
133
|
-
throw new DOMException('Aborted', 'AbortError');
|
|
134
|
-
}
|
|
135
|
-
const remaining = maxBytes - total;
|
|
136
|
-
if (remaining <= 0) {
|
|
137
|
-
truncated = true;
|
|
138
|
-
break;
|
|
139
|
-
}
|
|
140
|
-
const value = typeof chunk === 'string' ? Buffer.from(chunk) : chunk;
|
|
141
|
-
if (value.length > remaining) {
|
|
142
|
-
chunks.push(value.subarray(0, remaining));
|
|
143
|
-
total += remaining;
|
|
144
|
-
truncated = true;
|
|
145
|
-
break;
|
|
146
|
-
}
|
|
147
|
-
chunks.push(value);
|
|
148
|
-
total += value.length;
|
|
149
|
-
}
|
|
150
|
-
const decoder = new TextDecoder();
|
|
151
|
-
let text = '';
|
|
152
|
-
for (const chunk of chunks) {
|
|
153
|
-
text += decoder.decode(chunk, { stream: true });
|
|
154
|
-
}
|
|
155
|
-
text += decoder.decode();
|
|
156
|
-
return { text, bytesReturned: total, truncated };
|
|
157
|
-
}
|
|
158
|
-
/**
|
|
159
|
-
* Drain a response body with a size cap and abort-signal awareness.
|
|
160
|
-
* Used for redirect responses and rejected content types.
|
|
161
|
-
*/
|
|
162
|
-
export async function drainBody(body, signal) {
|
|
163
|
-
if (!body)
|
|
164
|
-
return;
|
|
165
|
-
let drained = 0;
|
|
166
|
-
try {
|
|
167
|
-
for await (const chunk of body) {
|
|
168
|
-
if (signal.aborted)
|
|
169
|
-
break;
|
|
170
|
-
let len = 0;
|
|
171
|
-
if (typeof chunk === 'string') {
|
|
172
|
-
len = Buffer.byteLength(chunk);
|
|
173
|
-
}
|
|
174
|
-
else if (chunk instanceof Uint8Array) {
|
|
175
|
-
len = chunk.length;
|
|
176
|
-
}
|
|
177
|
-
else if (Buffer.isBuffer(chunk)) {
|
|
178
|
-
len = chunk.length;
|
|
179
|
-
}
|
|
180
|
-
drained += len;
|
|
181
|
-
if (drained > REDIRECT_DRAIN_CAP)
|
|
182
|
-
break;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
catch {
|
|
186
|
-
// drain errors are ignorable
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
export function isUndiciTimeout(err) {
|
|
190
|
-
if (!(err instanceof Error))
|
|
191
|
-
return false;
|
|
192
|
-
const code = err.code;
|
|
193
|
-
return code === 'UND_ERR_CONNECT_TIMEOUT'
|
|
194
|
-
|| code === 'UND_ERR_HEADERS_TIMEOUT'
|
|
195
|
-
|| code === 'UND_ERR_BODY_TIMEOUT';
|
|
196
|
-
}
|
|
197
|
-
export function mapRequestError(err, signal, host) {
|
|
198
|
-
if (signal.aborted) {
|
|
199
|
-
return { status: 'error', reasonCode: 'web_fetch_timeout', host, credentialsStripped: false };
|
|
200
|
-
}
|
|
201
|
-
if (err instanceof DOMException && err.name === 'AbortError') {
|
|
202
|
-
return { status: 'error', reasonCode: 'web_fetch_timeout', host, credentialsStripped: false };
|
|
203
|
-
}
|
|
204
|
-
if (isUndiciTimeout(err)) {
|
|
205
|
-
return { status: 'error', reasonCode: 'web_fetch_timeout', host, credentialsStripped: false };
|
|
206
|
-
}
|
|
207
|
-
return { status: 'error', reasonCode: 'web_fetch_request_failed', host, credentialsStripped: false };
|
|
208
|
-
}
|
|
209
|
-
//# sourceMappingURL=web-fetch-helpers.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"web-fetch-helpers.js","sourceRoot":"","sources":["../../src/research/web-fetch-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import type { LookupFunction } from 'node:net';
|
|
2
|
-
import type { ResearchConfig } from '../config/schema.js';
|
|
3
|
-
export interface WebFetchInput {
|
|
4
|
-
url: string;
|
|
5
|
-
cfg: ResearchConfig['fetch'];
|
|
6
|
-
hostAllowlist: ReadonlySet<string>;
|
|
7
|
-
privateNetworkHosts?: ReadonlySet<string>;
|
|
8
|
-
resolveIP?: (host: string) => Promise<string>;
|
|
9
|
-
/** Test seam — when present, treated as the IP that the connect callback
|
|
10
|
-
* "resolved" at request time. Production must not pass this. */
|
|
11
|
-
_testConnectResolvedIp?: string;
|
|
12
|
-
/** Test-only injection seam. When set, webFetch uses the returned dispatcher
|
|
13
|
-
* (or, if it returns undefined, no dispatcher — so undici's global MockAgent
|
|
14
|
-
* can intercept). Production never sets this: it always uses the connect-guard
|
|
15
|
-
* agent built in webFetch(). */
|
|
16
|
-
createDispatcher?: (host: string, pinnedIP: string, cfg: ResearchConfig['fetch']) => import('undici').Dispatcher | undefined;
|
|
17
|
-
}
|
|
18
|
-
export type WebFetchOk = {
|
|
19
|
-
status: 'ok';
|
|
20
|
-
body: string;
|
|
21
|
-
rawText: string;
|
|
22
|
-
host: string;
|
|
23
|
-
bytesReturned: number;
|
|
24
|
-
truncated: boolean;
|
|
25
|
-
textTruncated: boolean;
|
|
26
|
-
credentialsStripped: boolean;
|
|
27
|
-
};
|
|
28
|
-
export type WebFetchErr = {
|
|
29
|
-
status: 'error';
|
|
30
|
-
reasonCode: string;
|
|
31
|
-
host?: string;
|
|
32
|
-
credentialsStripped: boolean;
|
|
33
|
-
};
|
|
34
|
-
export type WebFetchResult = WebFetchOk | WebFetchErr;
|
|
35
|
-
/**
|
|
36
|
-
* Build the SSRF-revalidating `connect.lookup` for the guard agent.
|
|
37
|
-
*
|
|
38
|
-
* undici invokes `connect.lookup` with `{ all: true }` and expects the callback
|
|
39
|
-
* to receive an ARRAY of `{ address, family }` entries — NOT the single-result
|
|
40
|
-
* `dns.lookup(host, (err, address, family) => ...)` form. Returning a bare
|
|
41
|
-
* address string makes undici read `addresses[0].address === undefined`, throw
|
|
42
|
-
* `ERR_INVALID_IP_ADDRESS`, and surface as `web_fetch_request_failed`. Every
|
|
43
|
-
* callback path here therefore returns the array form.
|
|
44
|
-
*
|
|
45
|
-
* Typed as `net.LookupFunction` — the exact type undici's `connect.lookup`
|
|
46
|
-
* field accepts. On error paths we pass an empty address array (undici reads
|
|
47
|
-
* `err` first and never consumes the addresses), which keeps the runtime
|
|
48
|
-
* contract while satisfying the callback's required address argument.
|
|
49
|
-
*
|
|
50
|
-
* Exported for unit testing — it locks the undici lookup contract without
|
|
51
|
-
* requiring real network (see tests/research/web-fetch.test.ts).
|
|
52
|
-
*/
|
|
53
|
-
export declare function makeConnectGuardLookup(allowPrivateNetwork: boolean, testResolvedIp: string | undefined): LookupFunction;
|
|
54
|
-
export declare function webFetch(input: WebFetchInput): Promise<WebFetchResult>;
|
|
55
|
-
//# sourceMappingURL=web-fetch.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"web-fetch.d.ts","sourceRoot":"","sources":["../../src/research/web-fetch.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAW1D,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAkB,MAAM,CAAC;IAC5B,GAAG,EAAkB,cAAc,CAAC,OAAO,CAAC,CAAC;IAC7C,aAAa,EAAQ,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,mBAAmB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC1C,SAAS,CAAC,EAAW,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD;qEACiE;IACjE,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC;;;qCAGiC;IACjC,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,CAAC,OAAO,CAAC,KAAK,OAAO,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAC;CAC9H;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAC1D,aAAa,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,aAAa,EAAE,OAAO,CAAC;IAClE,mBAAmB,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,OAAO,CAAC;CAClF,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,WAAW,CAAC;AAStD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CACpC,mBAAmB,EAAE,OAAO,EAC5B,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,cAAc,CAkChB;AAeD,wBAAsB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAoJ5E"}
|