@noidmejs/atomkit-http 0.1.0 → 0.2.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 CHANGED
@@ -57,11 +57,17 @@ const res = await runSource(publicSource, { params: { q: 'hi' } });
57
57
  (JSON path). `{{params.x}}` interpolates caller params; `{{secret.X}}` resolves
58
58
  **server-side only**, in the proxy.
59
59
 
60
- ## Security status (v0.1 — read this)
61
-
62
- Hostname allow-list SSRF tier + server-only secrets + prototype-pollution-guarded
63
- templating. It is **not yet pen-tested**, and it does **not** pin DNS/IPs (a
64
- resolved hostname could still point at a private IP). Do not expose it to
65
- untrusted multi-tenant input without adding IP-pinning and a security review.
60
+ ## Security status (v0.2 — read this)
61
+
62
+ Server-only secrets + a hostname **allow-list SSRF tier** that now **re-validates
63
+ every redirect hop** (an allow-listed host can't `30x`-escape to a private IP),
64
+ **strips credentials on cross-host redirects**, **redacts upstream errors** to the
65
+ client (full detail your `onError` sink), and proto-guarded templating. See
66
+ [SECURITY.md](./SECURITY.md).
67
+
68
+ It is **not yet pen-tested**, and it does **not** pin DNS/IPs — a hostname you
69
+ allow-list (or redirect to) whose DNS resolves to a private IP is still reached.
70
+ Do not expose it to untrusted multi-tenant input without adding IP-pinning and a
71
+ security review. Report vulnerabilities via a GitHub Security Advisory.
66
72
 
67
73
  MIT © noidmejs
package/dist/proxy.d.ts CHANGED
@@ -6,6 +6,14 @@ export interface ProxyConfig {
6
6
  /** Allow-listed request hosts — exact ("api.example.com") or suffix (".example.com"). */
7
7
  allowHosts: string[];
8
8
  fetchImpl?: typeof fetch;
9
+ /**
10
+ * Server-side error sink. `handleRequest` REDACTS the upstream error before it
11
+ * crosses to the client (it can leak internal hosts / secret-bearing URLs); the
12
+ * unredacted detail is handed here for your logs/telemetry instead.
13
+ */
14
+ onError?: (sourceId: string, result: RunResult) => void;
15
+ /** Max redirect hops the SSRF guard follows before failing (default 5). */
16
+ maxRedirects?: number;
9
17
  }
10
18
  /**
11
19
  * A server-side proxy: resolves a named source with secrets injected, enforcing a
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIxD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACpC,wFAAwF;IACxF,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,yFAAyF;IACzF,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAiBD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW;wBACZ,MAAM,WAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAQ,OAAO,CAAC,SAAS,CAAC;yBAahE,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC;EAqB9D"}
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAIxD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACpC,wFAAwF;IACxF,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,yFAAyF;IACzF,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC;IACxD,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA2BD;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW;wBACZ,MAAM,WAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAQ,OAAO,CAAC,SAAS,CAAC;yBAqBhE,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC;EA6B9D"}
package/dist/proxy.js CHANGED
@@ -1,5 +1,19 @@
1
1
  import { interpolate } from './template.js';
2
2
  import { runSource } from './run.js';
3
+ /** Generic, non-revealing client message for a failed status. */
4
+ function genericError(status) {
5
+ if (status === 400)
6
+ return 'bad request';
7
+ if (status === 401 || status === 403)
8
+ return 'forbidden';
9
+ if (status === 404)
10
+ return 'not found';
11
+ if (status === 429)
12
+ return 'rate limited';
13
+ if (status === 0)
14
+ return 'upstream unavailable';
15
+ return 'upstream request failed';
16
+ }
3
17
  function hostAllowed(rawUrl, allow) {
4
18
  let host;
5
19
  try {
@@ -37,7 +51,15 @@ export function createProxy(config) {
37
51
  const checkUrl = interpolate(withoutSecrets, { params, secret: {} });
38
52
  if (!hostAllowed(checkUrl, config.allowHosts))
39
53
  return { ok: false, status: 403, error: 'host not allowed' };
40
- return runSource(source, { params, secrets: config.secrets, fetchImpl: config.fetchImpl });
54
+ return runSource(source, {
55
+ params,
56
+ secrets: config.secrets,
57
+ fetchImpl: config.fetchImpl,
58
+ // Re-validate every redirect hop against the SAME allow-list so a 30x can't
59
+ // escape it to a private IP / off-list host.
60
+ allowRedirectHost: (u) => hostAllowed(u, config.allowHosts),
61
+ maxRedirects: config.maxRedirects,
62
+ });
41
63
  }
42
64
  /** Web-standard handler: POST { sourceId, params } → JSON RunResult. Mount in a
43
65
  * Next route handler, a Cloudflare Worker, an Express adapter, etc. */
@@ -56,7 +78,15 @@ export function createProxy(config) {
56
78
  });
57
79
  }
58
80
  const result = await resolve(payload.sourceId, payload.params ?? {});
59
- return new Response(JSON.stringify(result), {
81
+ // Redact before crossing to the client: the raw `error` (fetch messages,
82
+ // resolved URLs, upstream bodies) can leak internal hosts or secret-bearing
83
+ // URLs. Log the detail server-side, return a generic message.
84
+ let client = result;
85
+ if (!result.ok) {
86
+ config.onError?.(payload.sourceId, result);
87
+ client = { ok: false, status: result.status, error: genericError(result.status) };
88
+ }
89
+ return new Response(JSON.stringify(client), {
60
90
  status: result.ok ? 200 : result.status || 500,
61
91
  headers: { 'content-type': 'application/json', 'cache-control': 'no-store' },
62
92
  });
package/dist/proxy.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"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"}
package/dist/run.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA8BpE;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,GAAE,UAAe,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CA2C5G"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA8BpE;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,GAAE,UAAe,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CA2E5G"}
package/dist/run.js CHANGED
@@ -55,12 +55,68 @@ export async function runSource(source, ctx = {}) {
55
55
  const f = ctx.fetchImpl ?? fetch;
56
56
  const attempts = Math.max(1, source.retry?.attempts ?? 1);
57
57
  const backoff = source.retry?.backoffMs ?? 300;
58
+ const guardRedirects = typeof ctx.allowRedirectHost === 'function';
59
+ const maxRedirects = Math.max(0, ctx.maxRedirects ?? 5);
58
60
  let last = { ok: false, status: 0, error: 'not run' };
59
61
  for (let i = 0; i < attempts; i++) {
62
+ const ctrl = source.timeoutMs ? new AbortController() : null;
63
+ const timer = ctrl ? setTimeout(() => ctrl.abort(), source.timeoutMs) : null;
60
64
  try {
61
- const ctrl = source.timeoutMs ? new AbortController() : null;
62
- const timer = ctrl ? setTimeout(() => ctrl.abort(), source.timeoutMs) : null;
63
- const res = await f(url, { method, headers, body, signal: ctrl?.signal ?? null });
65
+ // Redirect handling. Default: let the platform follow (redirect:'follow').
66
+ // When an SSRF guard is supplied, follow MANUALLY and re-validate each hop —
67
+ // an allow-listed host can otherwise 30x-redirect to a private IP / off-list
68
+ // host and the platform would follow it, bypassing the allow-list.
69
+ const originHost = (() => { try {
70
+ return new URL(url).host;
71
+ }
72
+ catch {
73
+ return '';
74
+ } })();
75
+ let curUrl = url;
76
+ let curMethod = method;
77
+ let curHeaders = { ...headers };
78
+ let curBody = body;
79
+ let res = await f(curUrl, {
80
+ method: curMethod, headers: curHeaders, body: curBody,
81
+ signal: ctrl?.signal ?? null, redirect: guardRedirects ? 'manual' : 'follow',
82
+ });
83
+ if (guardRedirects) {
84
+ let hops = 0;
85
+ while (res.status >= 300 && res.status < 400 && res.headers.get('location')) {
86
+ if (hops++ >= maxRedirects) {
87
+ if (timer)
88
+ clearTimeout(timer);
89
+ return { ok: false, status: 0, error: 'too many redirects' };
90
+ }
91
+ let loc;
92
+ try {
93
+ loc = new URL(res.headers.get('location'), curUrl).toString();
94
+ }
95
+ catch {
96
+ if (timer)
97
+ clearTimeout(timer);
98
+ return { ok: false, status: 0, error: 'invalid redirect location' };
99
+ }
100
+ if (!ctx.allowRedirectHost(loc)) {
101
+ if (timer)
102
+ clearTimeout(timer);
103
+ return { ok: false, status: 403, error: 'redirect host not allowed' };
104
+ }
105
+ // Cross-host hop → drop credentials so bearer/cookie can't leak off-origin.
106
+ if (new URL(loc).host !== originHost) {
107
+ delete curHeaders['authorization'];
108
+ delete curHeaders['cookie'];
109
+ }
110
+ // 303 (and 301/302 on a non-idempotent method) → switch to GET, drop body;
111
+ // 307/308 preserve method + body.
112
+ if (res.status !== 307 && res.status !== 308 && curMethod !== 'GET' && curMethod !== 'HEAD') {
113
+ curMethod = 'GET';
114
+ curBody = undefined;
115
+ }
116
+ curUrl = loc;
117
+ res = await f(curUrl, { method: curMethod, headers: curHeaders, body: curBody, signal: ctrl?.signal ?? null, redirect: 'manual' });
118
+ }
119
+ }
64
120
  if (timer)
65
121
  clearTimeout(timer);
66
122
  const ct = res.headers.get('content-type') ?? '';
@@ -74,6 +130,8 @@ export async function runSource(source, ctx = {}) {
74
130
  }
75
131
  }
76
132
  catch (e) {
133
+ if (timer)
134
+ clearTimeout(timer);
77
135
  last = { ok: false, status: 0, error: e instanceof Error ? e.message : 'fetch failed' };
78
136
  }
79
137
  if (i < attempts - 1)
package/dist/run.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -40,6 +40,16 @@ export interface RunContext {
40
40
  secrets?: Record<string, string>;
41
41
  /** Override fetch (for tests / custom runtimes). */
42
42
  fetchImpl?: typeof fetch;
43
+ /**
44
+ * SSRF hardening: when provided, redirects are followed MANUALLY and every hop's
45
+ * URL is re-validated with this predicate (return `true` to allow). Without it,
46
+ * the platform default (`redirect: 'follow'`) is used and off-list redirect
47
+ * targets are NOT re-checked — so the proxy always sets this. Credentials
48
+ * (`authorization` / `cookie`) are stripped on a cross-host hop.
49
+ */
50
+ allowRedirectHost?: (url: string) => boolean;
51
+ /** Max redirect hops to follow when `allowRedirectHost` is set (default 5). */
52
+ maxRedirects?: number;
43
53
  }
44
54
  export interface RunResult<T = unknown> {
45
55
  ok: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAExF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;IACpC,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;+DAC+D;AAC/D,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,yFAAyF;IACzF,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,oDAAoD;IACpD,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAED,MAAM,WAAW,SAAS,CAAC,CAAC,GAAG,OAAO;IACpC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAExF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;IACpC,kFAAkF;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kBAAkB;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;+DAC+D;AAC/D,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,QAAQ,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,yFAAyF;IACzF,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,oDAAoD;IACpD,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAC7C,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS,CAAC,CAAC,GAAG,OAAO;IACpC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@noidmejs/atomkit-http",
3
- "version": "0.1.0",
4
- "description": "Declarative HTTP/backend connector: call any API by config (all verbs, headers, query, body, auth, retries, cache, transforms). Secrets stay server-only via a proxy with an SSRF host allow-list.",
3
+ "version": "0.2.0",
4
+ "description": "Declarative HTTP/backend connector: call any API by config (all verbs, headers, query, body, auth, retries, cache, transforms). Secrets stay server-only via a proxy with an SSRF host allow-list + per-redirect-hop re-validation.",
5
5
  "keywords": ["atomkit", "http", "connector", "declarative", "fetch", "api", "proxy", "ssrf", "no-code"],
6
6
  "license": "MIT",
7
7
  "author": "noidmejs",
@@ -19,5 +19,7 @@
19
19
  "devDependencies": { "typescript": "^5.6.0", "@types/node": "^20.0.0" },
20
20
  "publishConfig": { "access": "public" },
21
21
  "repository": { "type": "git", "url": "git+https://github.com/noidme-git/atomkit-http.git" },
22
+ "bugs": { "url": "https://github.com/noidme-git/atomkit-http/issues" },
23
+ "homepage": "https://github.com/noidme-git/atomkit-http#readme",
22
24
  "engines": { "node": ">=18" }
23
25
  }