402-mcp 3.10.0 → 3.11.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 (53) hide show
  1. package/README.md +49 -33
  2. package/build/config.d.ts +3 -0
  3. package/build/config.js +9 -0
  4. package/build/config.js.map +1 -1
  5. package/build/fetch/errors.d.ts +5 -0
  6. package/build/fetch/errors.js +8 -0
  7. package/build/fetch/errors.js.map +1 -1
  8. package/build/fetch/hns-resolve.d.ts +12 -0
  9. package/build/fetch/hns-resolve.js +67 -0
  10. package/build/fetch/hns-resolve.js.map +1 -0
  11. package/build/fetch/resilient-fetch.d.ts +25 -0
  12. package/build/fetch/resilient-fetch.js +69 -7
  13. package/build/fetch/resilient-fetch.js.map +1 -1
  14. package/build/fetch/ssrf-guard.d.ts +18 -4
  15. package/build/fetch/ssrf-guard.js +55 -7
  16. package/build/fetch/ssrf-guard.js.map +1 -1
  17. package/build/fetch/transport.d.ts +12 -0
  18. package/build/fetch/transport.js +64 -0
  19. package/build/fetch/transport.js.map +1 -0
  20. package/build/index.js +9 -1
  21. package/build/index.js.map +1 -1
  22. package/build/l402/bolt11.js +2 -2
  23. package/build/l402/bolt11.js.map +1 -1
  24. package/build/store/cashu-tokens.js +1 -1
  25. package/build/store/cashu-tokens.js.map +1 -1
  26. package/build/store/credentials.js.map +1 -1
  27. package/build/store/encryption.js +11 -2
  28. package/build/store/encryption.js.map +1 -1
  29. package/build/tools/balance.js +1 -1
  30. package/build/tools/balance.js.map +1 -1
  31. package/build/tools/buy-credits.d.ts +1 -0
  32. package/build/tools/buy-credits.js +13 -0
  33. package/build/tools/buy-credits.js.map +1 -1
  34. package/build/tools/config.js +1 -1
  35. package/build/tools/config.js.map +1 -1
  36. package/build/tools/credentials.js +1 -1
  37. package/build/tools/credentials.js.map +1 -1
  38. package/build/tools/fetch.d.ts +4 -0
  39. package/build/tools/fetch.js +28 -11
  40. package/build/tools/fetch.js.map +1 -1
  41. package/build/tools/redeem-cashu.js.map +1 -1
  42. package/build/tools/safe-error.js +2 -2
  43. package/build/tools/safe-error.js.map +1 -1
  44. package/build/tools/search.d.ts +2 -2
  45. package/build/tools/search.js +9 -6
  46. package/build/tools/search.js.map +1 -1
  47. package/build/tools/store-token.js +1 -1
  48. package/build/tools/store-token.js.map +1 -1
  49. package/build/wallet/cashu.js +1 -1
  50. package/build/wallet/cashu.js.map +1 -1
  51. package/build/wallet/nwc.js +1 -1
  52. package/build/wallet/nwc.js.map +1 -1
  53. package/package.json +18 -2
package/README.md CHANGED
@@ -33,39 +33,6 @@ Ask Claude: *"Search for paid joke APIs using l402_search"* — no wallet needed
33
33
 
34
34
  Ready to make paid calls? See the [full quickstart guide](./docs/quickstart.md) to set up a wallet and watch your agent pay for its first API call.
35
35
 
36
- ## Configuration
37
-
38
- | Variable | Default | Description |
39
- |----------|---------|-------------|
40
- | `NWC_URI` | - | Nostr Wallet Connect URI for autonomous Lightning payments |
41
- | `CASHU_TOKENS` | - | Path to Cashu token store file |
42
- | `MAX_AUTO_PAY_SATS` | 1000 | Safety cap; payments above this require human confirmation |
43
- | `CREDENTIAL_STORE` | `~/.402-mcp/credentials.json` | Persistent macaroon/credential storage |
44
- | `TRANSPORT` | `stdio` | Transport mode: `stdio` or `http` |
45
- | `PORT` | 3402 | HTTP server port (when `TRANSPORT=http`) |
46
-
47
- ## Tools
48
-
49
- ### Core L402 (any server)
50
-
51
- | Tool | Description |
52
- |------|-------------|
53
- | `l402_config` | Introspect payment capabilities (wallets, limits, credential count) |
54
- | `l402_discover` | Probe an endpoint to discover pricing without paying |
55
- | `l402_fetch` | HTTP request with L402 support; auto-pays if within budget |
56
- | `l402_pay` | Pay a specific invoice (NWC, Cashu, or human-in-the-loop) |
57
- | `l402_credentials` | List stored credentials and cached balances |
58
- | `l402_balance` | Check cached credit balance for a server |
59
- | `l402_search` | Discover L402 services on Nostr relays (kind 31402 announcements) |
60
- | `l402_store_token` | Store an L402 token obtained from a payment page |
61
-
62
- ### toll-booth extensions
63
-
64
- | Tool | Description |
65
- |------|-------------|
66
- | `l402_buy_credits` | Browse and purchase volume discount tiers |
67
- | `l402_redeem_cashu` | Redeem Cashu tokens directly (avoids Lightning round-trip) |
68
-
69
36
  ## How it works
70
37
 
71
38
  ```mermaid
@@ -100,6 +67,53 @@ Agent: "I need routing data from routing.trotters.cc"
100
67
 
101
68
  For detailed architecture and payment flow diagrams, see [docs/architecture.md](./docs/architecture.md).
102
69
 
70
+ ## Configuration
71
+
72
+ | Variable | Default | Description |
73
+ |----------|---------|-------------|
74
+ | `NWC_URI` | - | Nostr Wallet Connect URI for autonomous Lightning payments |
75
+ | `CASHU_TOKENS` | - | Path to Cashu token store file |
76
+ | `MAX_AUTO_PAY_SATS` | 1000 | Safety cap; payments above this require human confirmation |
77
+ | `CREDENTIAL_STORE` | `~/.402-mcp/credentials.json` | Persistent macaroon/credential storage |
78
+ | `TRANSPORT` | `stdio` | Transport mode: `stdio` or `http` |
79
+ | `PORT` | 3402 | HTTP server port (when `TRANSPORT=http`) |
80
+ | `TRANSPORT_PREFERENCE` | `clearnet` | Preferred network transport: `clearnet`, `tor`, or `hns` |
81
+ | `TOR_PROXY` | - | SOCKS5 proxy for `.onion` addresses (e.g. `socks5h://127.0.0.1:9050`) |
82
+ | `SOCKS_PROXY` | - | Generic SOCKS5 proxy for all requests when set |
83
+ | `HNS_GATEWAY_URL` | - | HTTP gateway for Handshake (`.hns`) domains (e.g. `https://hns.to`) |
84
+
85
+ ### Transport selection and fallback
86
+
87
+ When a kind 31402 event advertises multiple URLs (one per transport), 402-mcp selects the best one based on your configuration:
88
+
89
+ 1. **Preference first** — if `TRANSPORT_PREFERENCE=tor` and a `.onion` URL is available, it is tried first.
90
+ 2. **Availability fallback** — if the preferred transport is unreachable (proxy not configured, timeout), the client falls back to the next URL in the list.
91
+ 3. **Clearnet default** — if no preference is set, clearnet URLs are tried before `.onion` or HNS entries.
92
+
93
+ Services can announce multiple endpoints for the **same service** (same pricing, same macaroon key) on different transports. This is purely for censorship resistance; you do not need to re-authenticate when switching transports. To reach Tor or HNS endpoints you must configure the corresponding proxy/gateway env vars above.
94
+
95
+ ## Tools
96
+
97
+ ### Core L402 (any server)
98
+
99
+ | Tool | Description |
100
+ |------|-------------|
101
+ | `l402_config` | Introspect payment capabilities (wallets, limits, credential count) |
102
+ | `l402_discover` | Probe an endpoint to discover pricing without paying |
103
+ | `l402_fetch` | HTTP request with L402 support; auto-pays if within budget |
104
+ | `l402_pay` | Pay a specific invoice (NWC, Cashu, or human-in-the-loop) |
105
+ | `l402_credentials` | List stored credentials and cached balances |
106
+ | `l402_balance` | Check cached credit balance for a server |
107
+ | `l402_search` | Discover L402 services on Nostr relays (kind 31402 announcements) |
108
+ | `l402_store_token` | Store an L402 token obtained from a payment page |
109
+
110
+ ### toll-booth extensions
111
+
112
+ | Tool | Description |
113
+ |------|-------------|
114
+ | `l402_buy_credits` | Browse and purchase volume discount tiers |
115
+ | `l402_redeem_cashu` | Redeem Cashu tokens directly (avoids Lightning round-trip) |
116
+
103
117
  ## Payment methods
104
118
 
105
119
  Three payment rails, tried in priority order:
@@ -120,6 +134,8 @@ The agent can override the method per-call, or you can configure only the method
120
134
 
121
135
  ## Ecosystem
122
136
 
137
+ Browse live L402 services at [402.pub](https://402.pub) — the decentralised marketplace for payment-gated APIs.
138
+
123
139
  | Project | Role |
124
140
  |---------|------|
125
141
  | [toll-booth](https://github.com/TheCryptoDonkey/toll-booth) | Payment-rail agnostic HTTP 402 middleware |
package/build/config.d.ts CHANGED
@@ -14,6 +14,9 @@ export interface L402Config {
14
14
  ssrfAllowPrivate: boolean;
15
15
  corsOrigin: string | false;
16
16
  bindAddress: string;
17
+ transportPreference: string[];
18
+ torProxy: string | undefined;
19
+ hnsGatewayUrl: string;
17
20
  }
18
21
  /** Loads and validates configuration from environment variables, applying defaults. */
19
22
  export declare function loadConfig(): L402Config;
package/build/config.js CHANGED
@@ -26,6 +26,12 @@ export function loadConfig() {
26
26
  if (transport !== 'stdio' && transport !== 'http') {
27
27
  throw new Error(`TRANSPORT must be 'stdio' or 'http'; got '${transport}'`);
28
28
  }
29
+ const transportPref = process.env.TRANSPORT_PREFERENCE;
30
+ const transportPreference = transportPref
31
+ ? transportPref.split(',').map(s => s.trim()).filter(Boolean)
32
+ : ['onion', 'hns', 'https', 'http'];
33
+ const torProxy = process.env.TOR_PROXY || process.env.SOCKS_PROXY || undefined;
34
+ const hnsGatewayUrl = process.env.HNS_GATEWAY_URL || 'https://query.hdns.io/';
29
35
  const config = {
30
36
  nwcUri,
31
37
  cashuTokensPath: process.env.CASHU_TOKENS,
@@ -42,6 +48,9 @@ export function loadConfig() {
42
48
  ssrfAllowPrivate: process.env.SSRF_ALLOW_PRIVATE === 'true',
43
49
  corsOrigin: process.env.CORS_ORIGIN || false,
44
50
  bindAddress: process.env.BIND_ADDRESS ?? '127.0.0.1',
51
+ transportPreference,
52
+ torProxy,
53
+ hnsGatewayUrl,
45
54
  };
46
55
  assertNonNegativeInt('MAX_AUTO_PAY_SATS', config.maxAutoPaySats);
47
56
  assertNonNegativeInt('MAX_SPEND_PER_MINUTE_SATS', config.maxSpendPerMinuteSats);
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -19,3 +19,8 @@ export declare class DowngradeError extends Error {
19
19
  readonly name = "DowngradeError";
20
20
  constructor(originalUrl: string, redirectUrl: string);
21
21
  }
22
+ export declare class TransportUnavailableError extends Error {
23
+ readonly name = "TransportUnavailableError";
24
+ readonly url: string;
25
+ constructor(url: string, cause?: string);
26
+ }
@@ -30,4 +30,12 @@ export class DowngradeError extends Error {
30
30
  super(`HTTPS downgrade blocked: ${originalUrl} redirected to ${redirectUrl}`);
31
31
  }
32
32
  }
33
+ export class TransportUnavailableError extends Error {
34
+ name = 'TransportUnavailableError';
35
+ url;
36
+ constructor(url, cause) {
37
+ super(`Transport unavailable for ${url}${cause ? `: ${cause}` : ''}`);
38
+ this.url = url;
39
+ }
40
+ }
33
41
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/fetch/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,SAAU,SAAQ,KAAK;IAChB,IAAI,GAAG,WAAW,CAAA;IAEpC,YAAY,MAAc,EAAE,GAAW;QACrC,KAAK,CAAC,iBAAiB,MAAM,KAAK,GAAG,GAAG,CAAC,CAAA;IAC3C,CAAC;CACF;AAED,MAAM,OAAO,YAAa,SAAQ,KAAK;IACnB,IAAI,GAAG,cAAc,CAAA;IAEvC,YAAY,EAAU,EAAE,GAAW;QACjC,KAAK,CAAC,2BAA2B,EAAE,OAAO,GAAG,GAAG,CAAC,CAAA;IACnD,CAAC;CACF;AAED,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC1B,IAAI,GAAG,qBAAqB,CAAA;IAE9C,YAAY,QAAgB,EAAE,GAAW,EAAE,KAAY;QACrD,KAAK,CAAC,wBAAwB,QAAQ,cAAc,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;IAC1F,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC5B,IAAI,GAAG,uBAAuB,CAAA;IACvC,QAAQ,CAAQ;IAEzB,YAAY,QAAgB;QAC1B,KAAK,CAAC,0CAA0C,QAAQ,QAAQ,CAAC,CAAA;QACjE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC1B,CAAC;CACF;AAED,MAAM,OAAO,cAAe,SAAQ,KAAK;IACrB,IAAI,GAAG,gBAAgB,CAAA;IAEzC,YAAY,WAAmB,EAAE,WAAmB;QAClD,KAAK,CAAC,4BAA4B,WAAW,kBAAkB,WAAW,EAAE,CAAC,CAAA;IAC/E,CAAC;CACF"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/fetch/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,SAAU,SAAQ,KAAK;IAChB,IAAI,GAAG,WAAW,CAAA;IAEpC,YAAY,MAAc,EAAE,GAAW;QACrC,KAAK,CAAC,iBAAiB,MAAM,KAAK,GAAG,GAAG,CAAC,CAAA;IAC3C,CAAC;CACF;AAED,MAAM,OAAO,YAAa,SAAQ,KAAK;IACnB,IAAI,GAAG,cAAc,CAAA;IAEvC,YAAY,EAAU,EAAE,GAAW;QACjC,KAAK,CAAC,2BAA2B,EAAE,OAAO,GAAG,GAAG,CAAC,CAAA;IACnD,CAAC;CACF;AAED,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC1B,IAAI,GAAG,qBAAqB,CAAA;IAE9C,YAAY,QAAgB,EAAE,GAAW,EAAE,KAAY;QACrD,KAAK,CAAC,wBAAwB,QAAQ,cAAc,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAA;IAC1F,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC5B,IAAI,GAAG,uBAAuB,CAAA;IACvC,QAAQ,CAAQ;IAEzB,YAAY,QAAgB;QAC1B,KAAK,CAAC,0CAA0C,QAAQ,QAAQ,CAAC,CAAA;QACjE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;IAC1B,CAAC;CACF;AAED,MAAM,OAAO,cAAe,SAAQ,KAAK;IACrB,IAAI,GAAG,gBAAgB,CAAA;IAEzC,YAAY,WAAmB,EAAE,WAAmB;QAClD,KAAK,CAAC,4BAA4B,WAAW,kBAAkB,WAAW,EAAE,CAAC,CAAA;IAC/E,CAAC;CACF;AAED,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAChC,IAAI,GAAG,2BAA2B,CAAA;IAC3C,GAAG,CAAQ;IAEpB,YAAY,GAAW,EAAE,KAAc;QACrC,KAAK,CAAC,6BAA6B,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;QACrE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;IAChB,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ export interface ResolvedAddress {
2
+ address: string;
3
+ family: 4 | 6;
4
+ }
5
+ /**
6
+ * Resolve a Handshake (HNS) hostname via a DNS-over-HTTPS gateway.
7
+ *
8
+ * Tries an A record first; falls back to AAAA if no A records are returned.
9
+ * Throws if neither resolves, the gateway returns an error, or the request
10
+ * times out.
11
+ */
12
+ export declare function resolveHns(hostname: string, gatewayUrl: string, timeoutMs?: number): Promise<ResolvedAddress>;
@@ -0,0 +1,67 @@
1
+ // Strict IPv4: exactly four decimal octets 0-255 (rejects octal, hex, shorthand)
2
+ const IPV4_RE = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
3
+ // IPv6: hex digits, colons, and dots (dots appear in mixed notation like ::ffff:93.184.216.34)
4
+ const IPV6_RE = /^[0-9a-fA-F:.]+$/;
5
+ function isValidIpFormat(address, family) {
6
+ if (family === 4) {
7
+ const m = IPV4_RE.exec(address);
8
+ if (!m)
9
+ return false;
10
+ return [m[1], m[2], m[3], m[4]].every(octet => {
11
+ const n = Number(octet);
12
+ // Reject leading zeros (octal ambiguity: "0177" vs "177")
13
+ return n >= 0 && n <= 255 && String(n) === octet;
14
+ });
15
+ }
16
+ // IPv6: basic format check — hex digits and colons only, at least one colon
17
+ return IPV6_RE.test(address) && address.includes(':');
18
+ }
19
+ async function queryDns(hostname, gatewayUrl, type, signal) {
20
+ const url = `${gatewayUrl}dns-query?name=${encodeURIComponent(hostname)}&type=${type}`;
21
+ const response = await fetch(url, {
22
+ headers: { Accept: 'application/dns-json' },
23
+ signal,
24
+ redirect: 'error', // Prevent gateway redirects to internal services
25
+ });
26
+ if (!response.ok) {
27
+ throw new Error(`DNS query failed: HTTP ${response.status} for ${hostname} (${type})`);
28
+ }
29
+ const data = (await response.json());
30
+ return data.Answer ?? [];
31
+ }
32
+ /**
33
+ * Resolve a Handshake (HNS) hostname via a DNS-over-HTTPS gateway.
34
+ *
35
+ * Tries an A record first; falls back to AAAA if no A records are returned.
36
+ * Throws if neither resolves, the gateway returns an error, or the request
37
+ * times out.
38
+ */
39
+ export async function resolveHns(hostname, gatewayUrl, timeoutMs = 5000) {
40
+ const controller = new AbortController();
41
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
42
+ try {
43
+ // Try A record first
44
+ const aAnswers = await queryDns(hostname, gatewayUrl, 'A', controller.signal);
45
+ const aRecord = aAnswers.find(a => a.type === 1);
46
+ if (aRecord) {
47
+ if (!isValidIpFormat(aRecord.data, 4)) {
48
+ throw new Error(`HNS gateway returned invalid IPv4 address for ${hostname}`);
49
+ }
50
+ return { address: aRecord.data, family: 4 };
51
+ }
52
+ // Fall back to AAAA
53
+ const aaaaAnswers = await queryDns(hostname, gatewayUrl, 'AAAA', controller.signal);
54
+ const aaaaRecord = aaaaAnswers.find(a => a.type === 28);
55
+ if (aaaaRecord) {
56
+ if (!isValidIpFormat(aaaaRecord.data, 6)) {
57
+ throw new Error(`HNS gateway returned invalid IPv6 address for ${hostname}`);
58
+ }
59
+ return { address: aaaaRecord.data, family: 6 };
60
+ }
61
+ throw new Error(`No DNS records found for ${hostname}`);
62
+ }
63
+ finally {
64
+ clearTimeout(timeoutId);
65
+ }
66
+ }
67
+ //# sourceMappingURL=hns-resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hns-resolve.js","sourceRoot":"","sources":["../../src/fetch/hns-resolve.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { type ValidateUrlOptions } from './ssrf-guard.js';
1
2
  export interface ResilientFetchOptions {
2
3
  timeoutMs?: number;
3
4
  retries?: number;
@@ -11,6 +12,10 @@ export interface ResilientFetchConfig {
11
12
  backoffMs?: number;
12
13
  maxResponseBytes?: number;
13
14
  ssrfAllowPrivate?: boolean;
15
+ /** HNS (Handshake) resolver — called on NXDOMAIN to resolve alternative TLDs */
16
+ resolveHns?: ValidateUrlOptions['resolveHns'];
17
+ /** Whether a Tor SOCKS proxy is configured — enables .onion URL routing */
18
+ hasTorProxy?: boolean;
14
19
  }
15
20
  /**
16
21
  * Create a resilient fetch function with SSRF protection, timeout, and retry.
@@ -19,3 +24,23 @@ export interface ResilientFetchConfig {
19
24
  * with two args, and accepts an optional third arg for per-call overrides.
20
25
  */
21
26
  export declare function createResilientFetch(fetchFn: typeof fetch, config?: ResilientFetchConfig): (url: string | URL, init?: RequestInit, options?: ResilientFetchOptions) => Promise<Response>;
27
+ /**
28
+ * Returns true when the error is a transport-level failure that should trigger
29
+ * a fallback to the next URL rather than surfacing to the caller.
30
+ *
31
+ * - `TransportUnavailableError` — thrown by ssrf-guard for .onion without Tor, etc.
32
+ * - Node error codes: ECONNREFUSED, ETIMEDOUT, ENOTFOUND, UND_ERR_CONNECT_TIMEOUT
33
+ * - ECONNRESET is intentionally excluded — a mid-response reset is not a transport
34
+ * failure that can be resolved by trying a different URL.
35
+ */
36
+ export declare function isTransportError(err: unknown): boolean;
37
+ /**
38
+ * Try each URL in order, falling back on transport-level failures.
39
+ *
40
+ * - Connection failures (ECONNREFUSED, ETIMEDOUT, ENOTFOUND, UND_ERR_CONNECT_TIMEOUT,
41
+ * TransportUnavailableError) are swallowed and the next URL is tried.
42
+ * - Any other error (HTTP-level, SSRF block, decode error) is re-thrown immediately
43
+ * without trying the remaining URLs.
44
+ * - Throws the last transport error if all URLs are exhausted.
45
+ */
46
+ export declare function withTransportFallback(urls: string[], init: RequestInit, fetchFn: (url: string | URL, init?: RequestInit, options?: ResilientFetchOptions) => Promise<Response>, options?: ResilientFetchOptions): Promise<Response>;
@@ -1,5 +1,5 @@
1
1
  import { validateUrl } from './ssrf-guard.js';
2
- import { SsrfError, TimeoutError, RetryExhaustedError, DowngradeError, ResponseTooLargeError } from './errors.js';
2
+ import { SsrfError, TimeoutError, RetryExhaustedError, DowngradeError, ResponseTooLargeError, TransportUnavailableError } from './errors.js';
3
3
  const MAX_REDIRECTS = 5;
4
4
  const DEFAULT_TIMEOUT_MS = 30_000;
5
5
  const DEFAULT_RETRIES = 2;
@@ -57,6 +57,10 @@ export function createResilientFetch(fetchFn, config = {}) {
57
57
  const globalBackoff = config.backoffMs ?? DEFAULT_BACKOFF_MS;
58
58
  const globalMaxResponseBytes = config.maxResponseBytes ?? 0;
59
59
  const allowPrivate = config.ssrfAllowPrivate ?? false;
60
+ const ssrfOptions = {
61
+ resolveHns: config.resolveHns,
62
+ hasTorProxy: config.hasTorProxy ?? false,
63
+ };
60
64
  return async function resilientFetch(url, init, options) {
61
65
  const timeoutMs = options?.timeoutMs ?? globalTimeout;
62
66
  const retries = options?.retries ?? globalRetries;
@@ -66,7 +70,7 @@ export function createResilientFetch(fetchFn, config = {}) {
66
70
  // SSRF check on the initial URL (never retried).
67
71
  // The resolved address is used to pin HTTP connections to the validated IP,
68
72
  // closing the DNS rebinding TOCTOU window.
69
- const resolved = await validateUrl(urlStr, allowPrivate);
73
+ const resolved = await validateUrl(urlStr, allowPrivate, ssrfOptions);
70
74
  const totalAttempts = 1 + retries;
71
75
  let lastError;
72
76
  for (let attempt = 0; attempt < totalAttempts; attempt++) {
@@ -75,7 +79,7 @@ export function createResilientFetch(fetchFn, config = {}) {
75
79
  await sleep(delay);
76
80
  }
77
81
  try {
78
- let response = await fetchWithTimeoutAndRedirects(fetchFn, urlStr, init, timeoutMs, allowPrivate, urlStr, resolved);
82
+ let response = await fetchWithTimeoutAndRedirects(fetchFn, urlStr, init, timeoutMs, allowPrivate, urlStr, resolved, ssrfOptions);
79
83
  // If retryable status and we have retries left, drain body and continue
80
84
  if (retryOn(response.status) && attempt < totalAttempts - 1) {
81
85
  try {
@@ -131,12 +135,15 @@ export function createResilientFetch(fetchFn, config = {}) {
131
135
  }
132
136
  }
133
137
  // Final attempt failed
134
- if (retries === 0)
135
- throw lastError;
138
+ if (retries === 0) {
139
+ if (lastError)
140
+ throw lastError;
141
+ throw new Error('Request failed');
142
+ }
136
143
  throw new RetryExhaustedError(totalAttempts, urlStr, lastError);
137
144
  };
138
145
  }
139
- async function fetchWithTimeoutAndRedirects(fetchFn, url, init, timeoutMs, allowPrivate, originalUrl, resolved) {
146
+ async function fetchWithTimeoutAndRedirects(fetchFn, url, init, timeoutMs, allowPrivate, originalUrl, resolved, ssrfOptions = {}) {
140
147
  let currentUrl = url;
141
148
  let currentInit = init ? { ...init } : {};
142
149
  let redirectCount = 0;
@@ -196,7 +203,16 @@ async function fetchWithTimeoutAndRedirects(fetchFn, url, init, timeoutMs, allow
196
203
  throw new DowngradeError(originalUrl, currentUrl);
197
204
  }
198
205
  // SSRF check on redirect target; capture the resolved address for pinning
199
- currentResolved = await validateUrl(currentUrl, allowPrivate);
206
+ currentResolved = await validateUrl(currentUrl, allowPrivate, ssrfOptions);
207
+ // Strip Authorization header on cross-origin redirects to prevent credential leakage.
208
+ // Per Fetch spec, credentials should not follow cross-origin redirects.
209
+ const redirectOrigin = new URL(currentUrl).origin;
210
+ const originalOrigin = new URL(originalUrl).origin;
211
+ if (redirectOrigin !== originalOrigin && currentInit.headers) {
212
+ const headers = new Headers(currentInit.headers);
213
+ headers.delete('Authorization');
214
+ currentInit = { ...currentInit, headers };
215
+ }
200
216
  // 301/302/303 change POST to GET and drop body
201
217
  if ([301, 302, 303].includes(response.status)) {
202
218
  const method = currentInit.method?.toUpperCase();
@@ -207,4 +223,50 @@ async function fetchWithTimeoutAndRedirects(fetchFn, url, init, timeoutMs, allow
207
223
  // 307/308 preserve method and body (no change needed)
208
224
  }
209
225
  }
226
+ /** Error codes that indicate a transport-level failure (connect refused, DNS, timeout). */
227
+ const TRANSPORT_ERROR_CODES = new Set(['ECONNREFUSED', 'ETIMEDOUT', 'ENOTFOUND', 'UND_ERR_CONNECT_TIMEOUT']);
228
+ /**
229
+ * Returns true when the error is a transport-level failure that should trigger
230
+ * a fallback to the next URL rather than surfacing to the caller.
231
+ *
232
+ * - `TransportUnavailableError` — thrown by ssrf-guard for .onion without Tor, etc.
233
+ * - Node error codes: ECONNREFUSED, ETIMEDOUT, ENOTFOUND, UND_ERR_CONNECT_TIMEOUT
234
+ * - ECONNRESET is intentionally excluded — a mid-response reset is not a transport
235
+ * failure that can be resolved by trying a different URL.
236
+ */
237
+ export function isTransportError(err) {
238
+ if (err instanceof TransportUnavailableError)
239
+ return true;
240
+ if (err instanceof Error) {
241
+ const code = err.code;
242
+ if (code && TRANSPORT_ERROR_CODES.has(code))
243
+ return true;
244
+ }
245
+ return false;
246
+ }
247
+ /**
248
+ * Try each URL in order, falling back on transport-level failures.
249
+ *
250
+ * - Connection failures (ECONNREFUSED, ETIMEDOUT, ENOTFOUND, UND_ERR_CONNECT_TIMEOUT,
251
+ * TransportUnavailableError) are swallowed and the next URL is tried.
252
+ * - Any other error (HTTP-level, SSRF block, decode error) is re-thrown immediately
253
+ * without trying the remaining URLs.
254
+ * - Throws the last transport error if all URLs are exhausted.
255
+ */
256
+ export async function withTransportFallback(urls, init, fetchFn, options) {
257
+ let lastError;
258
+ for (const url of urls) {
259
+ try {
260
+ return await fetchFn(url, init, options);
261
+ }
262
+ catch (err) {
263
+ if (isTransportError(err)) {
264
+ lastError = err;
265
+ continue;
266
+ }
267
+ throw err;
268
+ }
269
+ }
270
+ throw lastError ?? new Error('All transports exhausted');
271
+ }
210
272
  //# sourceMappingURL=resilient-fetch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resilient-fetch.js","sourceRoot":"","sources":["../../src/fetch/resilient-fetch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resilient-fetch.js","sourceRoot":"","sources":["../../src/fetch/resilient-fetch.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,10 @@
1
- export interface ResolvedAddress {
2
- address: string;
3
- family: number;
1
+ import type { ResolvedAddress } from './hns-resolve.js';
2
+ export type { ResolvedAddress };
3
+ export interface ValidateUrlOptions {
4
+ /** Resolver for HNS (Handshake) names — called on NXDOMAIN (ENOTFOUND) */
5
+ resolveHns?: (hostname: string) => Promise<ResolvedAddress>;
6
+ /** Whether a Tor SOCKS proxy is available — required for .onion URLs */
7
+ hasTorProxy?: boolean;
4
8
  }
5
9
  /**
6
10
  * Validate a URL against SSRF rules and return the resolved IP address.
@@ -14,5 +18,15 @@ export interface ResolvedAddress {
14
18
  *
15
19
  * When `allowPrivate` is true, no resolution or validation is performed and
16
20
  * `undefined` is returned.
21
+ *
22
+ * `.onion` hostnames:
23
+ * - If `options.hasTorProxy` is true, returns `undefined` (route via SOCKS proxy; skip SSRF).
24
+ * - Otherwise throws `TransportUnavailableError`.
25
+ *
26
+ * HNS fallback:
27
+ * - If standard DNS fails with NXDOMAIN (ENOTFOUND) and `options.resolveHns` is provided,
28
+ * it is tried as a fallback. The resolved IP still goes through blocked-range checks.
29
+ * - Non-NXDOMAIN DNS errors propagate unchanged.
30
+ * - If both DNS and HNS fail, throws `TransportUnavailableError`.
17
31
  */
18
- export declare function validateUrl(url: string, allowPrivate?: boolean): Promise<ResolvedAddress | undefined>;
32
+ export declare function validateUrl(url: string, allowPrivate?: boolean, options?: ValidateUrlOptions): Promise<ResolvedAddress | undefined>;
@@ -1,5 +1,5 @@
1
1
  import { promises as dns } from 'node:dns';
2
- import { SsrfError } from './errors.js';
2
+ import { SsrfError, TransportUnavailableError } from './errors.js';
3
3
  function isBlockedIp(address, family) {
4
4
  if (family === 6) {
5
5
  const lower = address.toLowerCase();
@@ -79,6 +79,16 @@ function isBlockedIp(address, family) {
79
79
  return 'broadcast';
80
80
  return null;
81
81
  }
82
+ /**
83
+ * Validate a single resolved address against blocked ranges.
84
+ * Throws SsrfError if the address is in a blocked range.
85
+ */
86
+ function assertNotBlocked(address, family, url) {
87
+ const reason = isBlockedIp(address, family);
88
+ if (reason) {
89
+ throw new SsrfError(reason, url);
90
+ }
91
+ }
82
92
  /**
83
93
  * Validate a URL against SSRF rules and return the resolved IP address.
84
94
  *
@@ -91,8 +101,18 @@ function isBlockedIp(address, family) {
91
101
  *
92
102
  * When `allowPrivate` is true, no resolution or validation is performed and
93
103
  * `undefined` is returned.
104
+ *
105
+ * `.onion` hostnames:
106
+ * - If `options.hasTorProxy` is true, returns `undefined` (route via SOCKS proxy; skip SSRF).
107
+ * - Otherwise throws `TransportUnavailableError`.
108
+ *
109
+ * HNS fallback:
110
+ * - If standard DNS fails with NXDOMAIN (ENOTFOUND) and `options.resolveHns` is provided,
111
+ * it is tried as a fallback. The resolved IP still goes through blocked-range checks.
112
+ * - Non-NXDOMAIN DNS errors propagate unchanged.
113
+ * - If both DNS and HNS fail, throws `TransportUnavailableError`.
94
114
  */
95
- export async function validateUrl(url, allowPrivate = false) {
115
+ export async function validateUrl(url, allowPrivate = false, options = {}) {
96
116
  if (allowPrivate)
97
117
  return undefined;
98
118
  let parsed;
@@ -108,19 +128,47 @@ export async function validateUrl(url, allowPrivate = false) {
108
128
  // Strip bracket notation and IPv6 zone/scope IDs (e.g. fe80::1%25eth0)
109
129
  // so the guard is self-contained rather than relying on upstream normalisation.
110
130
  const hostname = parsed.hostname.replace(/^\[/, '').replace(/\]$/, '').split('%')[0];
131
+ // .onion: route via Tor SOCKS proxy — never attempt DNS resolution
132
+ if (hostname.endsWith('.onion')) {
133
+ if (options.hasTorProxy)
134
+ return undefined;
135
+ throw new TransportUnavailableError(url, 'Tor proxy required for .onion addresses');
136
+ }
111
137
  // Resolve ALL addresses to prevent multi-homed bypass where one A/AAAA
112
138
  // record is public but another resolves to a private/blocked IP.
113
- const results = await dns.lookup(hostname, { all: true });
139
+ let results;
140
+ try {
141
+ results = await dns.lookup(hostname, { all: true });
142
+ }
143
+ catch (err) {
144
+ const dnsError = err;
145
+ // NXDOMAIN — try HNS fallback
146
+ if (dnsError.code === 'ENOTFOUND') {
147
+ if (options.resolveHns) {
148
+ let hnsResult;
149
+ try {
150
+ hnsResult = await options.resolveHns(hostname);
151
+ }
152
+ catch {
153
+ throw new TransportUnavailableError(url, 'DNS and HNS resolution both failed');
154
+ }
155
+ // Validate the HNS-resolved IP against blocked ranges
156
+ assertNotBlocked(hnsResult.address, hnsResult.family, url);
157
+ return hnsResult;
158
+ }
159
+ throw new TransportUnavailableError(url, 'NXDOMAIN and no HNS resolver configured');
160
+ }
161
+ // Non-NXDOMAIN errors (EAI_AGAIN, ESERVFAIL, etc.) propagate unchanged
162
+ throw err;
163
+ }
114
164
  if (results.length === 0) {
115
165
  throw new SsrfError('DNS resolution returned no addresses', url);
116
166
  }
117
167
  for (const { address: addr, family: fam } of results) {
118
- const reason = isBlockedIp(addr, fam);
119
- if (reason) {
120
- throw new SsrfError(reason, url);
121
- }
168
+ assertNotBlocked(addr, fam, url);
122
169
  }
123
170
  // Return the first result for IP pinning (all have been validated)
171
+ // dns.lookup returns family as number (4 or 6); cast to the narrower union type
124
172
  return { address: results[0].address, family: results[0].family };
125
173
  }
126
174
  //# sourceMappingURL=ssrf-guard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ssrf-guard.js","sourceRoot":"","sources":["../../src/fetch/ssrf-guard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ssrf-guard.js","sourceRoot":"","sources":["../../src/fetch/ssrf-guard.ts"],"names":[],"mappings":"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"}