@easynet/agent-tool 1.0.80 → 1.0.82

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 (88) hide show
  1. package/README.md +5 -15
  2. package/dist/api/adapters/LangChainToolsHub.d.ts +1 -1
  3. package/dist/api/createAgentTools.d.ts +8 -24
  4. package/dist/api/createAgentTools.d.ts.map +1 -1
  5. package/dist/api/expose/index.d.ts +1 -1
  6. package/dist/api/main.cjs +11 -65
  7. package/dist/api/main.cjs.map +1 -1
  8. package/dist/api/main.d.ts +3 -56
  9. package/dist/api/main.d.ts.map +1 -1
  10. package/dist/api/main.js +13 -4
  11. package/dist/api/main.js.map +1 -1
  12. package/dist/api/runtimeFromConfig.d.ts +1 -1
  13. package/dist/api/runtimeFromConfig.d.ts.map +1 -1
  14. package/dist/build.cjs +5 -6
  15. package/dist/build.js +2 -3
  16. package/dist/{chunk-Q6W32HAP.js → chunk-3D7XYAZO.js} +7 -30
  17. package/dist/chunk-3D7XYAZO.js.map +1 -0
  18. package/dist/{chunk-GXFDYM3O.cjs → chunk-6NBQAFVB.cjs} +19 -43
  19. package/dist/chunk-6NBQAFVB.cjs.map +1 -0
  20. package/dist/{chunk-VYULM6NC.js → chunk-6ORA3MNX.js} +3 -3
  21. package/dist/{chunk-VYULM6NC.js.map → chunk-6ORA3MNX.js.map} +1 -1
  22. package/dist/{chunk-42UNSIZJ.js → chunk-EHFXS4WP.js} +7 -28
  23. package/dist/chunk-EHFXS4WP.js.map +1 -0
  24. package/dist/{chunk-5QH7YY4Z.cjs → chunk-F4HS7H7K.cjs} +4 -5
  25. package/dist/chunk-F4HS7H7K.cjs.map +1 -0
  26. package/dist/{chunk-DVYM6VRD.js → chunk-GYN3JAMK.js} +6 -26
  27. package/dist/chunk-GYN3JAMK.js.map +1 -0
  28. package/dist/{chunk-JZ6LKSAS.js → chunk-NEMGE573.js} +4 -4
  29. package/dist/chunk-NEMGE573.js.map +1 -0
  30. package/dist/{chunk-TBDSFXNG.cjs → chunk-QCHMXVWZ.cjs} +7 -7
  31. package/dist/{chunk-TBDSFXNG.cjs.map → chunk-QCHMXVWZ.cjs.map} +1 -1
  32. package/dist/{chunk-33N4Y6IS.cjs → chunk-V2RD4BHT.cjs} +7 -33
  33. package/dist/chunk-V2RD4BHT.cjs.map +1 -0
  34. package/dist/{chunk-EIIHED57.cjs → chunk-XPQZLO4A.cjs} +12 -35
  35. package/dist/chunk-XPQZLO4A.cjs.map +1 -0
  36. package/dist/config/ref.d.ts.map +1 -1
  37. package/dist/core/index.cjs +0 -1
  38. package/dist/core/index.js +0 -1
  39. package/dist/core/runtime.cjs +0 -1
  40. package/dist/core/runtime.js +0 -1
  41. package/dist/extension.cjs +257 -42
  42. package/dist/extension.cjs.map +1 -1
  43. package/dist/extension.js +243 -3
  44. package/dist/extension.js.map +1 -1
  45. package/dist/index.cjs +11 -149
  46. package/dist/index.cjs.map +1 -1
  47. package/dist/index.d.ts +2 -55
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +9 -90
  50. package/dist/index.js.map +1 -1
  51. package/dist/observability/Logger.d.ts +1 -1
  52. package/dist/observability/Logger.d.ts.map +1 -1
  53. package/dist/security.cjs +178 -11
  54. package/dist/security.cjs.map +1 -1
  55. package/dist/security.js +179 -2
  56. package/dist/security.js.map +1 -1
  57. package/dist/tools/skill/SkillMdParser.d.ts.map +1 -1
  58. package/dist/utils/cli/index.cjs +17 -17
  59. package/dist/utils/cli/index.js +3 -3
  60. package/package.json +2 -34
  61. package/dist/chunk-33N4Y6IS.cjs.map +0 -1
  62. package/dist/chunk-42UNSIZJ.js.map +0 -1
  63. package/dist/chunk-5QH7YY4Z.cjs.map +0 -1
  64. package/dist/chunk-DEDDPMBU.js +0 -3
  65. package/dist/chunk-DEDDPMBU.js.map +0 -1
  66. package/dist/chunk-DGE2AHYT.cjs +0 -261
  67. package/dist/chunk-DGE2AHYT.cjs.map +0 -1
  68. package/dist/chunk-DVYM6VRD.js.map +0 -1
  69. package/dist/chunk-EIIHED57.cjs.map +0 -1
  70. package/dist/chunk-FWWN4D2F.js +0 -3
  71. package/dist/chunk-FWWN4D2F.js.map +0 -1
  72. package/dist/chunk-GXFDYM3O.cjs.map +0 -1
  73. package/dist/chunk-ICHSEIZN.cjs +0 -4
  74. package/dist/chunk-ICHSEIZN.cjs.map +0 -1
  75. package/dist/chunk-JZ6LKSAS.js.map +0 -1
  76. package/dist/chunk-NKYFYALQ.js +0 -181
  77. package/dist/chunk-NKYFYALQ.js.map +0 -1
  78. package/dist/chunk-NOGGIM7B.cjs +0 -4
  79. package/dist/chunk-NOGGIM7B.cjs.map +0 -1
  80. package/dist/chunk-Q6W32HAP.js.map +0 -1
  81. package/dist/chunk-R55NXJIH.cjs +0 -184
  82. package/dist/chunk-R55NXJIH.cjs.map +0 -1
  83. package/dist/chunk-S4X4NJIP.js +0 -244
  84. package/dist/chunk-S4X4NJIP.js.map +0 -1
  85. package/dist/chunk-YL6RC7HQ.cjs +0 -4
  86. package/dist/chunk-YL6RC7HQ.cjs.map +0 -1
  87. package/dist/chunk-YLWTSNTT.js +0 -3
  88. package/dist/chunk-YLWTSNTT.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,93 +1,12 @@
1
- import './chunk-FWWN4D2F.js';
2
- import { createContextRunner, createDynamicImportAdapter, getGroupNamePrefixes, overrideWithConfig, resolveExtensionPackageRoot, registerExtension, generateExtensionManifest, generateManifest, createExtension } from './chunk-S4X4NJIP.js';
3
- import { isIpInBlockedCidrs, validateUrl } from './chunk-NKYFYALQ.js';
4
- import './chunk-YLWTSNTT.js';
5
- import './chunk-DEDDPMBU.js';
6
- export { createLangChainAgentTools, createMcpServer, createOpenAPIServer, langchainApi, mcpApi, openApi, runtimeApi } from './chunk-DVYM6VRD.js';
7
- import { loadToolYaml, loadExtensionManifest, registerToolsFromManifest } from './chunk-JZ6LKSAS.js';
8
- import { runMCPServer, buildMCPPackage, initProject } from './chunk-VYULM6NC.js';
9
- import { loadToolConfig } from './chunk-42UNSIZJ.js';
10
- export { createMCPServer, createMCPServerStreamableHttp, createMCPStreamableHttpHandler, createRuntimeFromConfig, createRuntimeFromConfigSync, runMCPServerOverStdio } from './chunk-42UNSIZJ.js';
1
+ export { createMcpServer, createOpenAPIServer } from './chunk-GYN3JAMK.js';
2
+ import './chunk-NEMGE573.js';
3
+ import './chunk-EHFXS4WP.js';
11
4
  import './chunk-NTWOVFEY.js';
12
- import './chunk-Q6W32HAP.js';
13
- import { scan, scanForTools } from './chunk-HEVWKBBQ.js';
14
- import { setSandboxValidationEnabled, resolveSandboxedPath } from './chunk-QXQ4477T.js';
15
- import { ToolRegistry } from './chunk-WUMLZERG.js';
16
- export { ToolRegistry } from './chunk-WUMLZERG.js';
17
- import { isRetryable, withRetry, createTaggedError } from './chunk-RZTTO5MQ.js';
18
- export { createTaggedError, isRetryable, withRetry } from './chunk-RZTTO5MQ.js';
19
- import { DEFAULT_OUTPUT_SCHEMA, DEFAULT_INPUT_SCHEMA, createToolSpec } from './chunk-ODEHUAR4.js';
20
- import { resolve } from 'path';
21
- import { deepMerge } from '@easynet/agent-common';
22
-
23
- // src/config/ref.ts
24
- function asObject(input) {
25
- return typeof input === "object" && input !== null ? input : void 0;
26
- }
27
- function normalizeAgentToolConfigRef(raw) {
28
- if (typeof raw === "string" && raw.trim().length > 0) return { ref: raw.trim() };
29
- const obj = asObject(raw);
30
- if (!obj) return {};
31
- const out = {};
32
- if (typeof obj.ref === "string" && obj.ref.trim().length > 0) out.ref = obj.ref.trim();
33
- if (typeof obj.development === "string" && obj.development.trim().length > 0) out.development = obj.development.trim();
34
- if (typeof obj.production === "string" && obj.production.trim().length > 0) out.production = obj.production.trim();
35
- return out;
36
- }
37
-
38
- // src/config/index.ts
39
- function loadToolRuntimeConfig(options = {}) {
40
- const configPath = resolve(options.configPath ?? "config/tool.yaml");
41
- return loadToolConfig(configPath);
42
- }
43
- function createToolConfig(options = {}) {
44
- const base = loadToolRuntimeConfig(options);
45
- if (!options.overrides) return base;
46
- return deepMerge({}, base, options.overrides);
47
- }
48
-
49
- // src/index.ts
50
- var platformApi = {
51
- build: {
52
- initProject,
53
- buildMCPPackage,
54
- runMCPServer,
55
- scanForTools,
56
- scan
57
- },
58
- extension: {
59
- createExtension,
60
- generateManifest,
61
- generateExtensionManifest,
62
- registerExtension,
63
- registerToolsFromManifest,
64
- loadExtensionManifest,
65
- loadToolYaml,
66
- resolveExtensionPackageRoot,
67
- overrideWithConfig,
68
- getGroupNamePrefixes,
69
- createDynamicImportAdapter,
70
- createContextRunner
71
- },
72
- security: {
73
- resolveSandboxedPath,
74
- setSandboxValidationEnabled,
75
- validateUrl,
76
- isIpInBlockedCidrs
77
- },
78
- core: {
79
- createToolSpec,
80
- DEFAULT_INPUT_SCHEMA,
81
- DEFAULT_OUTPUT_SCHEMA
82
- },
83
- runtime: {
84
- createTaggedError,
85
- withRetry,
86
- isRetryable,
87
- ToolRegistry
88
- }
89
- };
90
-
91
- export { createToolConfig, loadToolRuntimeConfig, normalizeAgentToolConfigRef, platformApi };
5
+ import './chunk-3D7XYAZO.js';
6
+ import './chunk-HEVWKBBQ.js';
7
+ import './chunk-QXQ4477T.js';
8
+ import './chunk-WUMLZERG.js';
9
+ import './chunk-RZTTO5MQ.js';
10
+ import './chunk-ODEHUAR4.js';
92
11
  //# sourceMappingURL=index.js.map
93
12
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config/ref.ts","../src/config/index.ts","../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAOA,SAAS,SAAS,KAAA,EAAqD;AACrE,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,OAAQ,KAAA,GAAoC,MAAA;AAC5F;AAGO,SAAS,4BAA4B,GAAA,EAA2C;AACrF,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,CAAI,IAAA,EAAK,CAAE,MAAA,GAAS,CAAA,EAAG,OAAO,EAAE,GAAA,EAAK,GAAA,CAAI,MAAK,EAAE;AAC/E,EAAA,MAAM,GAAA,GAAM,SAAS,GAAG,CAAA;AACxB,EAAA,IAAI,CAAC,GAAA,EAAK,OAAO,EAAC;AAElB,EAAA,MAAM,MAAmC,EAAC;AAC1C,EAAA,IAAI,OAAO,GAAA,CAAI,GAAA,KAAQ,QAAA,IAAY,IAAI,GAAA,CAAI,IAAA,EAAK,CAAE,MAAA,GAAS,CAAA,EAAG,GAAA,CAAI,GAAA,GAAM,GAAA,CAAI,IAAI,IAAA,EAAK;AACrF,EAAA,IAAI,OAAO,GAAA,CAAI,WAAA,KAAgB,QAAA,IAAY,IAAI,WAAA,CAAY,IAAA,EAAK,CAAE,MAAA,GAAS,CAAA,EAAG,GAAA,CAAI,WAAA,GAAc,GAAA,CAAI,YAAY,IAAA,EAAK;AACrH,EAAA,IAAI,OAAO,GAAA,CAAI,UAAA,KAAe,QAAA,IAAY,IAAI,UAAA,CAAW,IAAA,EAAK,CAAE,MAAA,GAAS,CAAA,EAAG,GAAA,CAAI,UAAA,GAAa,GAAA,CAAI,WAAW,IAAA,EAAK;AACjH,EAAA,OAAO,GAAA;AACT;;;ACPO,SAAS,qBAAA,CAAsB,OAAA,GAAiC,EAAC,EAAkB;AACxF,EAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,OAAA,CAAQ,UAAA,IAAc,kBAAkB,CAAA;AACnE,EAAA,OAAO,eAAe,UAAU,CAAA;AAClC;AAEO,SAAS,gBAAA,CAAiB,OAAA,GAAmC,EAAC,EAAkB;AACrF,EAAA,MAAM,IAAA,GAAO,sBAAsB,OAAO,CAAA;AAC1C,EAAA,IAAI,CAAC,OAAA,CAAQ,SAAA,EAAW,OAAO,IAAA;AAC/B,EAAA,OAAO,SAAA,CAAU,EAAC,EAAoB,IAAA,EAAM,QAAQ,SAAS,CAAA;AAC/D;;;ACgEO,IAAM,WAAA,GAAc;AAAA,EACzB,KAAA,EAAO;AAAA,IACL,WAAA;AAAA,IACA,eAAA;AAAA,IACA,YAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,SAAA,EAAW;AAAA,IACT,eAAA;AAAA,IACA,gBAAA;AAAA,IACA,yBAAA;AAAA,IACA,iBAAA;AAAA,IACA,yBAAA;AAAA,IACA,qBAAA;AAAA,IACA,YAAA;AAAA,IACA,2BAAA;AAAA,IACA,kBAAA;AAAA,IACA,oBAAA;AAAA,IACA,0BAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,QAAA,EAAU;AAAA,IACR,oBAAA;AAAA,IACA,2BAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,cAAA;AAAA,IACA,oBAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,OAAA,EAAS;AAAA,IACP,iBAAA;AAAA,IACA,SAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA;AAEJ","file":"index.js","sourcesContent":["/** Agent-level reference to tool config files by environment. */\nexport interface AgentToolConfigRef {\n ref?: string;\n development?: string;\n production?: string;\n}\n\nfunction asObject(input: unknown): Record<string, unknown> | undefined {\n return typeof input === \"object\" && input !== null ? (input as Record<string, unknown>) : undefined;\n}\n\n/** Normalize unknown value to AgentToolConfigRef. */\nexport function normalizeAgentToolConfigRef(raw: unknown): Partial<AgentToolConfigRef> {\n if (typeof raw === \"string\" && raw.trim().length > 0) return { ref: raw.trim() };\n const obj = asObject(raw);\n if (!obj) return {};\n\n const out: Partial<AgentToolConfigRef> = {};\n if (typeof obj.ref === \"string\" && obj.ref.trim().length > 0) out.ref = obj.ref.trim();\n if (typeof obj.development === \"string\" && obj.development.trim().length > 0) out.development = obj.development.trim();\n if (typeof obj.production === \"string\" && obj.production.trim().length > 0) out.production = obj.production.trim();\n return out;\n}\n","import { resolve } from \"node:path\";\nimport { deepMerge } from \"@easynet/agent-common\";\nimport { loadToolConfig, type ToolYamlShape } from \"../tools/util/toolConfig.js\";\n\nexport { normalizeAgentToolConfigRef } from \"./ref.js\";\nexport type { AgentToolConfigRef } from \"./ref.js\";\n\nexport interface LoadToolConfigOptions {\n configPath?: string;\n}\n\nexport interface CreateToolConfigOptions extends LoadToolConfigOptions {\n overrides?: Partial<ToolYamlShape>;\n}\n\nexport function loadToolRuntimeConfig(options: LoadToolConfigOptions = {}): ToolYamlShape {\n const configPath = resolve(options.configPath ?? \"config/tool.yaml\");\n return loadToolConfig(configPath);\n}\n\nexport function createToolConfig(options: CreateToolConfigOptions = {}): ToolYamlShape {\n const base = loadToolRuntimeConfig(options);\n if (!options.overrides) return base;\n return deepMerge({} as ToolYamlShape, base, options.overrides);\n}\n","/**\n * Minimal public API for @easynet/agent-tool.\n * Keep root exports focused on high-level runtime/server creation.\n */\n\n// High-level API (most users should import from @easynet/agent-tool/api)\nexport {\n createLangChainAgentTools,\n createMcpServer,\n createOpenAPIServer,\n createMCPServer,\n runMCPServerOverStdio,\n createMCPStreamableHttpHandler,\n createMCPServerStreamableHttp,\n createRuntimeFromConfig,\n createRuntimeFromConfigSync,\n langchainApi,\n runtimeApi,\n mcpApi,\n openApi,\n} from \"./api/main.js\";\nexport type {\n CreateAgentToolsOptions,\n CreateRuntimeOptions,\n CreateRuntimeResult,\n MCPServerOptions,\n MCPServerResult,\n McpServer,\n CreateMCPServerStreamableHttpOptions,\n MCPServerStreamableHttpResult,\n CreateHttpServiceOptions,\n HttpServiceResult,\n OpenAPIExpressApp,\n OpenAPIHttpServerOptions,\n} from \"./api/main.js\";\nexport type { AgentToolConfigRef } from \"./config/index.js\";\nexport {\n normalizeAgentToolConfigRef,\n loadToolRuntimeConfig,\n createToolConfig,\n} from \"./config/index.js\";\nexport type { LoadToolConfigOptions, CreateToolConfigOptions } from \"./config/index.js\";\n\n// Backward compatibility: older extensions import runtime helpers from package root.\nexport { createTaggedError, withRetry, isRetryable, ToolRegistry } from \"./core/runtime.js\";\n\nimport {\n initProject,\n buildMCPPackage,\n runMCPServer,\n scanForTools,\n scan,\n} from \"./build.js\";\nimport {\n createExtension,\n generateManifest,\n generateExtensionManifest,\n registerExtension,\n registerToolsFromManifest,\n loadExtensionManifest,\n loadToolYaml,\n resolveExtensionPackageRoot,\n overrideWithConfig,\n getGroupNamePrefixes,\n createDynamicImportAdapter,\n createContextRunner,\n} from \"./extension.js\";\nimport {\n resolveSandboxedPath,\n setSandboxValidationEnabled,\n validateUrl,\n isIpInBlockedCidrs,\n} from \"./security.js\";\nimport {\n createToolSpec,\n DEFAULT_INPUT_SCHEMA,\n DEFAULT_OUTPUT_SCHEMA,\n} from \"./core/index.js\";\nimport {\n createTaggedError,\n withRetry,\n isRetryable,\n ToolRegistry,\n} from \"./core/runtime.js\";\n\n/**\n * Facade: grouped utilities beyond runtime/server creation.\n */\nexport const platformApi = {\n build: {\n initProject,\n buildMCPPackage,\n runMCPServer,\n scanForTools,\n scan,\n },\n extension: {\n createExtension,\n generateManifest,\n generateExtensionManifest,\n registerExtension,\n registerToolsFromManifest,\n loadExtensionManifest,\n loadToolYaml,\n resolveExtensionPackageRoot,\n overrideWithConfig,\n getGroupNamePrefixes,\n createDynamicImportAdapter,\n createContextRunner,\n },\n security: {\n resolveSandboxedPath,\n setSandboxValidationEnabled,\n validateUrl,\n isIpInBlockedCidrs,\n },\n core: {\n createToolSpec,\n DEFAULT_INPUT_SCHEMA,\n DEFAULT_OUTPUT_SCHEMA,\n },\n runtime: {\n createTaggedError,\n withRetry,\n isRetryable,\n ToolRegistry,\n },\n} as const;\n"]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -1,3 +1,4 @@
1
+ export { summarizeForLog } from "@easynet/agent-common";
1
2
  export type LogLevel = "silent" | "error" | "warn" | "info" | "debug" | "trace";
2
3
  export interface DebugOptions {
3
4
  enabled?: boolean;
@@ -29,5 +30,4 @@ export interface Logger {
29
30
  export declare function createLogger(options?: DebugOptions): Logger;
30
31
  export declare function resolveDebugOptions(options?: DebugOptions): ResolvedDebugOptions;
31
32
  export declare function sanitizeForLog(value: unknown, maxLen?: number): string;
32
- export declare function summarizeForLog(value: unknown, maxLen?: number): string;
33
33
  //# sourceMappingURL=Logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../../src/observability/Logger.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAEhF,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,QAAQ,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC;IACpC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC9D;AAWD,wBAAgB,YAAY,CAAC,OAAO,GAAE,YAAiB,GAAG,MAAM,CAoC/D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,YAAiB,GAAG,oBAAoB,CAgBpF;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,SAAM,GAAG,MAAM,CAMnE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,SAAM,GAAG,MAAM,CAkBpE"}
1
+ {"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../../src/observability/Logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAEhF,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,QAAQ,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,oBAAoB,CAAC;IAC9B,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC;IACpC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC9D;AAWD,wBAAgB,YAAY,CAAC,OAAO,GAAE,YAAiB,GAAG,MAAM,CAoC/D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,YAAiB,GAAG,oBAAoB,CAgBpF;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,SAAM,GAAG,MAAM,CAMnE"}
package/dist/security.cjs CHANGED
@@ -1,19 +1,184 @@
1
1
  'use strict';
2
2
 
3
- var chunkR55NXJIH_cjs = require('./chunk-R55NXJIH.cjs');
4
3
  var chunkZDSZHEQU_cjs = require('./chunk-ZDSZHEQU.cjs');
5
- require('./chunk-XPGHS4W7.cjs');
4
+ var chunkXPGHS4W7_cjs = require('./chunk-XPGHS4W7.cjs');
5
+ var promises = require('dns/promises');
6
6
 
7
+ async function validateUrl(url, options) {
8
+ let parsed;
9
+ try {
10
+ parsed = new URL(url);
11
+ } catch {
12
+ throw chunkXPGHS4W7_cjs.createTaggedError(
13
+ "HTTP_DISALLOWED_HOST",
14
+ `Invalid URL: ${url}`,
15
+ { url }
16
+ );
17
+ }
18
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
19
+ throw chunkXPGHS4W7_cjs.createTaggedError(
20
+ "HTTP_DISALLOWED_HOST",
21
+ `Protocol not allowed: ${parsed.protocol}. Only http: and https: are supported.`,
22
+ { url, protocol: parsed.protocol }
23
+ );
24
+ }
25
+ const hostname = parsed.hostname;
26
+ if (!isHostAllowed(hostname, options.allowedHosts)) {
27
+ throw chunkXPGHS4W7_cjs.createTaggedError(
28
+ "HTTP_DISALLOWED_HOST",
29
+ `Host "${hostname}" is not in the allowed hosts list`,
30
+ { url, hostname, allowedHosts: options.allowedHosts }
31
+ );
32
+ }
33
+ if (isHostBlocked(hostname, options.blockedHosts)) {
34
+ throw chunkXPGHS4W7_cjs.createTaggedError(
35
+ "HTTP_DISALLOWED_HOST",
36
+ `Host "${hostname}" is in the blocked hosts list`,
37
+ { url, hostname, blockedHosts: options.blockedHosts }
38
+ );
39
+ }
40
+ try {
41
+ const { address } = await promises.lookup(hostname);
42
+ if (isIpInBlockedCidrs(address, options.blockedCidrs)) {
43
+ throw chunkXPGHS4W7_cjs.createTaggedError(
44
+ "HTTP_DISALLOWED_HOST",
45
+ `Host "${hostname}" resolves to blocked IP: ${address}`,
46
+ { url, hostname, resolvedIp: address }
47
+ );
48
+ }
49
+ } catch (err) {
50
+ if (err instanceof Error && err.kind === "HTTP_DISALLOWED_HOST") {
51
+ throw err;
52
+ }
53
+ throw chunkXPGHS4W7_cjs.createTaggedError(
54
+ "HTTP_DISALLOWED_HOST",
55
+ `DNS resolution failed for host "${hostname}": ${err instanceof Error ? err.message : String(err)}`,
56
+ { url, hostname }
57
+ );
58
+ }
59
+ return parsed;
60
+ }
61
+ function isHostAllowed(hostname, allowedHosts) {
62
+ for (const pattern of allowedHosts) {
63
+ if (pattern === "*") {
64
+ return true;
65
+ }
66
+ if (pattern.startsWith("*.")) {
67
+ const suffix = pattern.slice(1);
68
+ if (hostname.endsWith(suffix) || hostname === pattern.slice(2)) {
69
+ return true;
70
+ }
71
+ } else if (hostname === pattern) {
72
+ return true;
73
+ }
74
+ }
75
+ return false;
76
+ }
77
+ function isHostBlocked(hostname, blockedHosts) {
78
+ for (const pattern of blockedHosts) {
79
+ if (pattern === "*") {
80
+ return true;
81
+ }
82
+ if (pattern.startsWith("*.")) {
83
+ const suffix = pattern.slice(1);
84
+ if (hostname.endsWith(suffix) || hostname === pattern.slice(2)) {
85
+ return true;
86
+ }
87
+ } else if (hostname === pattern) {
88
+ return true;
89
+ }
90
+ }
91
+ return false;
92
+ }
93
+ function isIpInBlockedCidrs(ip, cidrs) {
94
+ const normalizedIp = normalizeIp(ip);
95
+ if (!normalizedIp) return false;
96
+ for (const cidr of cidrs) {
97
+ if (cidr.includes(":")) {
98
+ if (!ip.includes(":")) continue;
99
+ if (isIpv6InCidr(ip, cidr)) return true;
100
+ } else {
101
+ if (isIpv4InCidr(normalizedIp, cidr)) return true;
102
+ }
103
+ }
104
+ return false;
105
+ }
106
+ function normalizeIp(ip) {
107
+ if (ip.startsWith("::ffff:")) {
108
+ return ip.slice(7);
109
+ }
110
+ if (/^\d+\.\d+\.\d+\.\d+$/.test(ip)) {
111
+ return ip;
112
+ }
113
+ return null;
114
+ }
115
+ function isIpv4InCidr(ip, cidr) {
116
+ const [cidrIp, prefixStr] = cidr.split("/");
117
+ if (!cidrIp || !prefixStr) return false;
118
+ const prefix = parseInt(prefixStr, 10);
119
+ if (isNaN(prefix) || prefix < 0 || prefix > 32) return false;
120
+ const ipNum = ipv4ToNum(ip);
121
+ const cidrNum = ipv4ToNum(cidrIp);
122
+ if (ipNum === null || cidrNum === null) return false;
123
+ const mask = prefix === 0 ? 0 : -1 << 32 - prefix >>> 0;
124
+ return (ipNum & mask) === (cidrNum & mask);
125
+ }
126
+ function ipv4ToNum(ip) {
127
+ const parts = ip.split(".");
128
+ if (parts.length !== 4) return null;
129
+ let num = 0;
130
+ for (const part of parts) {
131
+ const n = parseInt(part, 10);
132
+ if (isNaN(n) || n < 0 || n > 255) return null;
133
+ num = num << 8 | n;
134
+ }
135
+ return num >>> 0;
136
+ }
137
+ function isIpv6InCidr(ip, cidr) {
138
+ const [cidrIp, prefixStr] = cidr.split("/");
139
+ if (!cidrIp || !prefixStr) return false;
140
+ const prefix = parseInt(prefixStr, 10);
141
+ if (isNaN(prefix)) return false;
142
+ const ipBytes = expandIpv6(ip);
143
+ const cidrBytes = expandIpv6(cidrIp);
144
+ if (!ipBytes || !cidrBytes) return false;
145
+ const fullBytes = Math.floor(prefix / 8);
146
+ for (let i = 0; i < fullBytes && i < 16; i++) {
147
+ if (ipBytes[i] !== cidrBytes[i]) return false;
148
+ }
149
+ const remainingBits = prefix % 8;
150
+ if (remainingBits > 0 && fullBytes < 16) {
151
+ const mask = -1 << 8 - remainingBits & 255;
152
+ if ((ipBytes[fullBytes] & mask) !== (cidrBytes[fullBytes] & mask)) return false;
153
+ }
154
+ return true;
155
+ }
156
+ function expandIpv6(ip) {
157
+ const zoneIdx = ip.indexOf("%");
158
+ if (zoneIdx !== -1) ip = ip.slice(0, zoneIdx);
159
+ const parts = ip.split("::");
160
+ if (parts.length > 2) return null;
161
+ const bytes = new Array(16).fill(0);
162
+ const expandGroup = (group) => {
163
+ if (!group) return [];
164
+ return group.split(":").flatMap((hex) => {
165
+ const val = parseInt(hex || "0", 16);
166
+ return [val >> 8 & 255, val & 255];
167
+ });
168
+ };
169
+ if (parts.length === 1) {
170
+ const expanded = expandGroup(parts[0]);
171
+ if (expanded.length !== 16) return null;
172
+ return expanded;
173
+ }
174
+ const left = expandGroup(parts[0]);
175
+ const right = expandGroup(parts[1]);
176
+ if (left.length + right.length > 16) return null;
177
+ for (let i = 0; i < left.length; i++) bytes[i] = left[i];
178
+ for (let i = 0; i < right.length; i++) bytes[16 - right.length + i] = right[i];
179
+ return bytes;
180
+ }
7
181
 
8
-
9
- Object.defineProperty(exports, "isIpInBlockedCidrs", {
10
- enumerable: true,
11
- get: function () { return chunkR55NXJIH_cjs.isIpInBlockedCidrs; }
12
- });
13
- Object.defineProperty(exports, "validateUrl", {
14
- enumerable: true,
15
- get: function () { return chunkR55NXJIH_cjs.validateUrl; }
16
- });
17
182
  Object.defineProperty(exports, "resolveSandboxedPath", {
18
183
  enumerable: true,
19
184
  get: function () { return chunkZDSZHEQU_cjs.resolveSandboxedPath; }
@@ -22,5 +187,7 @@ Object.defineProperty(exports, "setSandboxValidationEnabled", {
22
187
  enumerable: true,
23
188
  get: function () { return chunkZDSZHEQU_cjs.setSandboxValidationEnabled; }
24
189
  });
190
+ exports.isIpInBlockedCidrs = isIpInBlockedCidrs;
191
+ exports.validateUrl = validateUrl;
25
192
  //# sourceMappingURL=security.cjs.map
26
193
  //# sourceMappingURL=security.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"security.cjs"}
1
+ {"version":3,"sources":["../src/security/ssrf.ts"],"names":["createTaggedError","lookup"],"mappings":"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","file":"security.cjs","sourcesContent":["import { lookup } from \"node:dns/promises\";\nimport { createTaggedError } from \"../core/runtime/Retry.js\";\n\n/**\n * Options for validateUrl. Unified rule: allow iff host is in allowedHosts AND not in blockedHosts.\n * - \"Default allow all + blocklist\": allowedHosts: [\"*\"], blockedHosts: [\"*.internal\", ...]\n * - \"Default disallow all + allowlist\": allowedHosts: [\"api.github.com\", ...], blockedHosts: []\n */\nexport interface ValidateUrlOptions {\n /** Allow only these hosts. Use [\"*\"] for allow-all. Supports \"*.example.com\", exact host. */\n allowedHosts: string[];\n /** Block these hosts even if allowed. Supports \"*.internal\", exact host. Merged with allowlist. */\n blockedHosts: string[];\n /** CIDR ranges to block (resolved IP). */\n blockedCidrs: string[];\n}\n\n/**\n * Validate a URL: allow iff (host in allowedHosts) AND (host not in blockedHosts). Then check blockedCidrs on resolved IP.\n *\n * @throws HTTP_DISALLOWED_HOST if the URL is blocked\n */\nexport async function validateUrl(url: string, options: ValidateUrlOptions): Promise<URL> {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Invalid URL: ${url}`,\n { url },\n );\n }\n\n // Only allow http/https\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Protocol not allowed: ${parsed.protocol}. Only http: and https: are supported.`,\n { url, protocol: parsed.protocol },\n );\n }\n\n const hostname = parsed.hostname;\n\n if (!isHostAllowed(hostname, options.allowedHosts)) {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Host \"${hostname}\" is not in the allowed hosts list`,\n { url, hostname, allowedHosts: options.allowedHosts },\n );\n }\n if (isHostBlocked(hostname, options.blockedHosts)) {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Host \"${hostname}\" is in the blocked hosts list`,\n { url, hostname, blockedHosts: options.blockedHosts },\n );\n }\n\n // DNS resolve and check against blocked CIDRs\n try {\n const { address } = await lookup(hostname);\n if (isIpInBlockedCidrs(address, options.blockedCidrs)) {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Host \"${hostname}\" resolves to blocked IP: ${address}`,\n { url, hostname, resolvedIp: address },\n );\n }\n } catch (err) {\n // Re-throw our tagged errors\n if (err instanceof Error && (err as any).kind === \"HTTP_DISALLOWED_HOST\") {\n throw err;\n }\n // DNS resolution failure — block by default\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `DNS resolution failed for host \"${hostname}\": ${err instanceof Error ? err.message : String(err)}`,\n { url, hostname },\n );\n }\n\n return parsed;\n}\n\n/**\n * Check if a hostname matches any entry in the allowed hosts list.\n * Supports: exact \"*\" (allow any host), wildcard prefix (e.g. \"*.github.com\"), or exact host.\n */\nfunction isHostAllowed(hostname: string, allowedHosts: string[]): boolean {\n for (const pattern of allowedHosts) {\n if (pattern === \"*\") {\n return true;\n }\n if (pattern.startsWith(\"*.\")) {\n const suffix = pattern.slice(1); // \".github.com\"\n if (hostname.endsWith(suffix) || hostname === pattern.slice(2)) {\n return true;\n }\n } else if (hostname === pattern) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if a hostname matches any entry in the blocked hosts list (same pattern rules as allowlist).\n */\nfunction isHostBlocked(hostname: string, blockedHosts: string[]): boolean {\n for (const pattern of blockedHosts) {\n if (pattern === \"*\") {\n return true;\n }\n if (pattern.startsWith(\"*.\")) {\n const suffix = pattern.slice(1);\n if (hostname.endsWith(suffix) || hostname === pattern.slice(2)) {\n return true;\n }\n } else if (hostname === pattern) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if an IPv4 address falls within any blocked CIDR range.\n */\nexport function isIpInBlockedCidrs(ip: string, cidrs: string[]): boolean {\n // Handle IPv4-mapped IPv6\n const normalizedIp = normalizeIp(ip);\n if (!normalizedIp) return false;\n\n for (const cidr of cidrs) {\n if (cidr.includes(\":\")) {\n // IPv6 CIDR — skip for IPv4 addresses\n if (!ip.includes(\":\")) continue;\n if (isIpv6InCidr(ip, cidr)) return true;\n } else {\n if (isIpv4InCidr(normalizedIp, cidr)) return true;\n }\n }\n return false;\n}\n\nfunction normalizeIp(ip: string): string | null {\n // Handle IPv4-mapped IPv6 (e.g. \"::ffff:127.0.0.1\")\n if (ip.startsWith(\"::ffff:\")) {\n return ip.slice(7);\n }\n // Pure IPv4\n if (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(ip)) {\n return ip;\n }\n return null;\n}\n\nfunction isIpv4InCidr(ip: string, cidr: string): boolean {\n const [cidrIp, prefixStr] = cidr.split(\"/\");\n if (!cidrIp || !prefixStr) return false;\n\n const prefix = parseInt(prefixStr, 10);\n if (isNaN(prefix) || prefix < 0 || prefix > 32) return false;\n\n const ipNum = ipv4ToNum(ip);\n const cidrNum = ipv4ToNum(cidrIp);\n if (ipNum === null || cidrNum === null) return false;\n\n const mask = prefix === 0 ? 0 : (~0 << (32 - prefix)) >>> 0;\n return (ipNum & mask) === (cidrNum & mask);\n}\n\nfunction ipv4ToNum(ip: string): number | null {\n const parts = ip.split(\".\");\n if (parts.length !== 4) return null;\n let num = 0;\n for (const part of parts) {\n const n = parseInt(part, 10);\n if (isNaN(n) || n < 0 || n > 255) return null;\n num = (num << 8) | n;\n }\n return num >>> 0;\n}\n\nfunction isIpv6InCidr(ip: string, cidr: string): boolean {\n // Simplified IPv6 CIDR matching for common cases (::1, fc00::, fe80::)\n const [cidrIp, prefixStr] = cidr.split(\"/\");\n if (!cidrIp || !prefixStr) return false;\n\n const prefix = parseInt(prefixStr, 10);\n if (isNaN(prefix)) return false;\n\n const ipBytes = expandIpv6(ip);\n const cidrBytes = expandIpv6(cidrIp);\n if (!ipBytes || !cidrBytes) return false;\n\n // Compare prefix bits\n const fullBytes = Math.floor(prefix / 8);\n for (let i = 0; i < fullBytes && i < 16; i++) {\n if (ipBytes[i] !== cidrBytes[i]) return false;\n }\n\n const remainingBits = prefix % 8;\n if (remainingBits > 0 && fullBytes < 16) {\n const mask = (~0 << (8 - remainingBits)) & 0xff;\n if ((ipBytes[fullBytes]! & mask) !== (cidrBytes[fullBytes]! & mask)) return false;\n }\n\n return true;\n}\n\nfunction expandIpv6(ip: string): number[] | null {\n // Remove zone ID\n const zoneIdx = ip.indexOf(\"%\");\n if (zoneIdx !== -1) ip = ip.slice(0, zoneIdx);\n\n const parts = ip.split(\"::\");\n if (parts.length > 2) return null;\n\n const bytes: number[] = new Array(16).fill(0);\n\n const expandGroup = (group: string): number[] => {\n if (!group) return [];\n return group.split(\":\").flatMap((hex) => {\n const val = parseInt(hex || \"0\", 16);\n return [(val >> 8) & 0xff, val & 0xff];\n });\n };\n\n if (parts.length === 1) {\n const expanded = expandGroup(parts[0]!);\n if (expanded.length !== 16) return null;\n return expanded;\n }\n\n const left = expandGroup(parts[0]!);\n const right = expandGroup(parts[1]!);\n\n if (left.length + right.length > 16) return null;\n\n for (let i = 0; i < left.length; i++) bytes[i] = left[i]!;\n for (let i = 0; i < right.length; i++) bytes[16 - right.length + i] = right[i]!;\n\n return bytes;\n}\n"]}
package/dist/security.js CHANGED
@@ -1,5 +1,182 @@
1
- export { isIpInBlockedCidrs, validateUrl } from './chunk-NKYFYALQ.js';
2
1
  export { resolveSandboxedPath, setSandboxValidationEnabled } from './chunk-QXQ4477T.js';
3
- import './chunk-RZTTO5MQ.js';
2
+ import { createTaggedError } from './chunk-RZTTO5MQ.js';
3
+ import { lookup } from 'dns/promises';
4
+
5
+ async function validateUrl(url, options) {
6
+ let parsed;
7
+ try {
8
+ parsed = new URL(url);
9
+ } catch {
10
+ throw createTaggedError(
11
+ "HTTP_DISALLOWED_HOST",
12
+ `Invalid URL: ${url}`,
13
+ { url }
14
+ );
15
+ }
16
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
17
+ throw createTaggedError(
18
+ "HTTP_DISALLOWED_HOST",
19
+ `Protocol not allowed: ${parsed.protocol}. Only http: and https: are supported.`,
20
+ { url, protocol: parsed.protocol }
21
+ );
22
+ }
23
+ const hostname = parsed.hostname;
24
+ if (!isHostAllowed(hostname, options.allowedHosts)) {
25
+ throw createTaggedError(
26
+ "HTTP_DISALLOWED_HOST",
27
+ `Host "${hostname}" is not in the allowed hosts list`,
28
+ { url, hostname, allowedHosts: options.allowedHosts }
29
+ );
30
+ }
31
+ if (isHostBlocked(hostname, options.blockedHosts)) {
32
+ throw createTaggedError(
33
+ "HTTP_DISALLOWED_HOST",
34
+ `Host "${hostname}" is in the blocked hosts list`,
35
+ { url, hostname, blockedHosts: options.blockedHosts }
36
+ );
37
+ }
38
+ try {
39
+ const { address } = await lookup(hostname);
40
+ if (isIpInBlockedCidrs(address, options.blockedCidrs)) {
41
+ throw createTaggedError(
42
+ "HTTP_DISALLOWED_HOST",
43
+ `Host "${hostname}" resolves to blocked IP: ${address}`,
44
+ { url, hostname, resolvedIp: address }
45
+ );
46
+ }
47
+ } catch (err) {
48
+ if (err instanceof Error && err.kind === "HTTP_DISALLOWED_HOST") {
49
+ throw err;
50
+ }
51
+ throw createTaggedError(
52
+ "HTTP_DISALLOWED_HOST",
53
+ `DNS resolution failed for host "${hostname}": ${err instanceof Error ? err.message : String(err)}`,
54
+ { url, hostname }
55
+ );
56
+ }
57
+ return parsed;
58
+ }
59
+ function isHostAllowed(hostname, allowedHosts) {
60
+ for (const pattern of allowedHosts) {
61
+ if (pattern === "*") {
62
+ return true;
63
+ }
64
+ if (pattern.startsWith("*.")) {
65
+ const suffix = pattern.slice(1);
66
+ if (hostname.endsWith(suffix) || hostname === pattern.slice(2)) {
67
+ return true;
68
+ }
69
+ } else if (hostname === pattern) {
70
+ return true;
71
+ }
72
+ }
73
+ return false;
74
+ }
75
+ function isHostBlocked(hostname, blockedHosts) {
76
+ for (const pattern of blockedHosts) {
77
+ if (pattern === "*") {
78
+ return true;
79
+ }
80
+ if (pattern.startsWith("*.")) {
81
+ const suffix = pattern.slice(1);
82
+ if (hostname.endsWith(suffix) || hostname === pattern.slice(2)) {
83
+ return true;
84
+ }
85
+ } else if (hostname === pattern) {
86
+ return true;
87
+ }
88
+ }
89
+ return false;
90
+ }
91
+ function isIpInBlockedCidrs(ip, cidrs) {
92
+ const normalizedIp = normalizeIp(ip);
93
+ if (!normalizedIp) return false;
94
+ for (const cidr of cidrs) {
95
+ if (cidr.includes(":")) {
96
+ if (!ip.includes(":")) continue;
97
+ if (isIpv6InCidr(ip, cidr)) return true;
98
+ } else {
99
+ if (isIpv4InCidr(normalizedIp, cidr)) return true;
100
+ }
101
+ }
102
+ return false;
103
+ }
104
+ function normalizeIp(ip) {
105
+ if (ip.startsWith("::ffff:")) {
106
+ return ip.slice(7);
107
+ }
108
+ if (/^\d+\.\d+\.\d+\.\d+$/.test(ip)) {
109
+ return ip;
110
+ }
111
+ return null;
112
+ }
113
+ function isIpv4InCidr(ip, cidr) {
114
+ const [cidrIp, prefixStr] = cidr.split("/");
115
+ if (!cidrIp || !prefixStr) return false;
116
+ const prefix = parseInt(prefixStr, 10);
117
+ if (isNaN(prefix) || prefix < 0 || prefix > 32) return false;
118
+ const ipNum = ipv4ToNum(ip);
119
+ const cidrNum = ipv4ToNum(cidrIp);
120
+ if (ipNum === null || cidrNum === null) return false;
121
+ const mask = prefix === 0 ? 0 : -1 << 32 - prefix >>> 0;
122
+ return (ipNum & mask) === (cidrNum & mask);
123
+ }
124
+ function ipv4ToNum(ip) {
125
+ const parts = ip.split(".");
126
+ if (parts.length !== 4) return null;
127
+ let num = 0;
128
+ for (const part of parts) {
129
+ const n = parseInt(part, 10);
130
+ if (isNaN(n) || n < 0 || n > 255) return null;
131
+ num = num << 8 | n;
132
+ }
133
+ return num >>> 0;
134
+ }
135
+ function isIpv6InCidr(ip, cidr) {
136
+ const [cidrIp, prefixStr] = cidr.split("/");
137
+ if (!cidrIp || !prefixStr) return false;
138
+ const prefix = parseInt(prefixStr, 10);
139
+ if (isNaN(prefix)) return false;
140
+ const ipBytes = expandIpv6(ip);
141
+ const cidrBytes = expandIpv6(cidrIp);
142
+ if (!ipBytes || !cidrBytes) return false;
143
+ const fullBytes = Math.floor(prefix / 8);
144
+ for (let i = 0; i < fullBytes && i < 16; i++) {
145
+ if (ipBytes[i] !== cidrBytes[i]) return false;
146
+ }
147
+ const remainingBits = prefix % 8;
148
+ if (remainingBits > 0 && fullBytes < 16) {
149
+ const mask = -1 << 8 - remainingBits & 255;
150
+ if ((ipBytes[fullBytes] & mask) !== (cidrBytes[fullBytes] & mask)) return false;
151
+ }
152
+ return true;
153
+ }
154
+ function expandIpv6(ip) {
155
+ const zoneIdx = ip.indexOf("%");
156
+ if (zoneIdx !== -1) ip = ip.slice(0, zoneIdx);
157
+ const parts = ip.split("::");
158
+ if (parts.length > 2) return null;
159
+ const bytes = new Array(16).fill(0);
160
+ const expandGroup = (group) => {
161
+ if (!group) return [];
162
+ return group.split(":").flatMap((hex) => {
163
+ const val = parseInt(hex || "0", 16);
164
+ return [val >> 8 & 255, val & 255];
165
+ });
166
+ };
167
+ if (parts.length === 1) {
168
+ const expanded = expandGroup(parts[0]);
169
+ if (expanded.length !== 16) return null;
170
+ return expanded;
171
+ }
172
+ const left = expandGroup(parts[0]);
173
+ const right = expandGroup(parts[1]);
174
+ if (left.length + right.length > 16) return null;
175
+ for (let i = 0; i < left.length; i++) bytes[i] = left[i];
176
+ for (let i = 0; i < right.length; i++) bytes[16 - right.length + i] = right[i];
177
+ return bytes;
178
+ }
179
+
180
+ export { isIpInBlockedCidrs, validateUrl };
4
181
  //# sourceMappingURL=security.js.map
5
182
  //# sourceMappingURL=security.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"security.js"}
1
+ {"version":3,"sources":["../src/security/ssrf.ts"],"names":[],"mappings":"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","file":"security.js","sourcesContent":["import { lookup } from \"node:dns/promises\";\nimport { createTaggedError } from \"../core/runtime/Retry.js\";\n\n/**\n * Options for validateUrl. Unified rule: allow iff host is in allowedHosts AND not in blockedHosts.\n * - \"Default allow all + blocklist\": allowedHosts: [\"*\"], blockedHosts: [\"*.internal\", ...]\n * - \"Default disallow all + allowlist\": allowedHosts: [\"api.github.com\", ...], blockedHosts: []\n */\nexport interface ValidateUrlOptions {\n /** Allow only these hosts. Use [\"*\"] for allow-all. Supports \"*.example.com\", exact host. */\n allowedHosts: string[];\n /** Block these hosts even if allowed. Supports \"*.internal\", exact host. Merged with allowlist. */\n blockedHosts: string[];\n /** CIDR ranges to block (resolved IP). */\n blockedCidrs: string[];\n}\n\n/**\n * Validate a URL: allow iff (host in allowedHosts) AND (host not in blockedHosts). Then check blockedCidrs on resolved IP.\n *\n * @throws HTTP_DISALLOWED_HOST if the URL is blocked\n */\nexport async function validateUrl(url: string, options: ValidateUrlOptions): Promise<URL> {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Invalid URL: ${url}`,\n { url },\n );\n }\n\n // Only allow http/https\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Protocol not allowed: ${parsed.protocol}. Only http: and https: are supported.`,\n { url, protocol: parsed.protocol },\n );\n }\n\n const hostname = parsed.hostname;\n\n if (!isHostAllowed(hostname, options.allowedHosts)) {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Host \"${hostname}\" is not in the allowed hosts list`,\n { url, hostname, allowedHosts: options.allowedHosts },\n );\n }\n if (isHostBlocked(hostname, options.blockedHosts)) {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Host \"${hostname}\" is in the blocked hosts list`,\n { url, hostname, blockedHosts: options.blockedHosts },\n );\n }\n\n // DNS resolve and check against blocked CIDRs\n try {\n const { address } = await lookup(hostname);\n if (isIpInBlockedCidrs(address, options.blockedCidrs)) {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Host \"${hostname}\" resolves to blocked IP: ${address}`,\n { url, hostname, resolvedIp: address },\n );\n }\n } catch (err) {\n // Re-throw our tagged errors\n if (err instanceof Error && (err as any).kind === \"HTTP_DISALLOWED_HOST\") {\n throw err;\n }\n // DNS resolution failure — block by default\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `DNS resolution failed for host \"${hostname}\": ${err instanceof Error ? err.message : String(err)}`,\n { url, hostname },\n );\n }\n\n return parsed;\n}\n\n/**\n * Check if a hostname matches any entry in the allowed hosts list.\n * Supports: exact \"*\" (allow any host), wildcard prefix (e.g. \"*.github.com\"), or exact host.\n */\nfunction isHostAllowed(hostname: string, allowedHosts: string[]): boolean {\n for (const pattern of allowedHosts) {\n if (pattern === \"*\") {\n return true;\n }\n if (pattern.startsWith(\"*.\")) {\n const suffix = pattern.slice(1); // \".github.com\"\n if (hostname.endsWith(suffix) || hostname === pattern.slice(2)) {\n return true;\n }\n } else if (hostname === pattern) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if a hostname matches any entry in the blocked hosts list (same pattern rules as allowlist).\n */\nfunction isHostBlocked(hostname: string, blockedHosts: string[]): boolean {\n for (const pattern of blockedHosts) {\n if (pattern === \"*\") {\n return true;\n }\n if (pattern.startsWith(\"*.\")) {\n const suffix = pattern.slice(1);\n if (hostname.endsWith(suffix) || hostname === pattern.slice(2)) {\n return true;\n }\n } else if (hostname === pattern) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if an IPv4 address falls within any blocked CIDR range.\n */\nexport function isIpInBlockedCidrs(ip: string, cidrs: string[]): boolean {\n // Handle IPv4-mapped IPv6\n const normalizedIp = normalizeIp(ip);\n if (!normalizedIp) return false;\n\n for (const cidr of cidrs) {\n if (cidr.includes(\":\")) {\n // IPv6 CIDR — skip for IPv4 addresses\n if (!ip.includes(\":\")) continue;\n if (isIpv6InCidr(ip, cidr)) return true;\n } else {\n if (isIpv4InCidr(normalizedIp, cidr)) return true;\n }\n }\n return false;\n}\n\nfunction normalizeIp(ip: string): string | null {\n // Handle IPv4-mapped IPv6 (e.g. \"::ffff:127.0.0.1\")\n if (ip.startsWith(\"::ffff:\")) {\n return ip.slice(7);\n }\n // Pure IPv4\n if (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(ip)) {\n return ip;\n }\n return null;\n}\n\nfunction isIpv4InCidr(ip: string, cidr: string): boolean {\n const [cidrIp, prefixStr] = cidr.split(\"/\");\n if (!cidrIp || !prefixStr) return false;\n\n const prefix = parseInt(prefixStr, 10);\n if (isNaN(prefix) || prefix < 0 || prefix > 32) return false;\n\n const ipNum = ipv4ToNum(ip);\n const cidrNum = ipv4ToNum(cidrIp);\n if (ipNum === null || cidrNum === null) return false;\n\n const mask = prefix === 0 ? 0 : (~0 << (32 - prefix)) >>> 0;\n return (ipNum & mask) === (cidrNum & mask);\n}\n\nfunction ipv4ToNum(ip: string): number | null {\n const parts = ip.split(\".\");\n if (parts.length !== 4) return null;\n let num = 0;\n for (const part of parts) {\n const n = parseInt(part, 10);\n if (isNaN(n) || n < 0 || n > 255) return null;\n num = (num << 8) | n;\n }\n return num >>> 0;\n}\n\nfunction isIpv6InCidr(ip: string, cidr: string): boolean {\n // Simplified IPv6 CIDR matching for common cases (::1, fc00::, fe80::)\n const [cidrIp, prefixStr] = cidr.split(\"/\");\n if (!cidrIp || !prefixStr) return false;\n\n const prefix = parseInt(prefixStr, 10);\n if (isNaN(prefix)) return false;\n\n const ipBytes = expandIpv6(ip);\n const cidrBytes = expandIpv6(cidrIp);\n if (!ipBytes || !cidrBytes) return false;\n\n // Compare prefix bits\n const fullBytes = Math.floor(prefix / 8);\n for (let i = 0; i < fullBytes && i < 16; i++) {\n if (ipBytes[i] !== cidrBytes[i]) return false;\n }\n\n const remainingBits = prefix % 8;\n if (remainingBits > 0 && fullBytes < 16) {\n const mask = (~0 << (8 - remainingBits)) & 0xff;\n if ((ipBytes[fullBytes]! & mask) !== (cidrBytes[fullBytes]! & mask)) return false;\n }\n\n return true;\n}\n\nfunction expandIpv6(ip: string): number[] | null {\n // Remove zone ID\n const zoneIdx = ip.indexOf(\"%\");\n if (zoneIdx !== -1) ip = ip.slice(0, zoneIdx);\n\n const parts = ip.split(\"::\");\n if (parts.length > 2) return null;\n\n const bytes: number[] = new Array(16).fill(0);\n\n const expandGroup = (group: string): number[] => {\n if (!group) return [];\n return group.split(\":\").flatMap((hex) => {\n const val = parseInt(hex || \"0\", 16);\n return [(val >> 8) & 0xff, val & 0xff];\n });\n };\n\n if (parts.length === 1) {\n const expanded = expandGroup(parts[0]!);\n if (expanded.length !== 16) return null;\n return expanded;\n }\n\n const left = expandGroup(parts[0]!);\n const right = expandGroup(parts[1]!);\n\n if (left.length + right.length > 16) return null;\n\n for (let i = 0; i < left.length; i++) bytes[i] = left[i]!;\n for (let i = 0; i < right.length; i++) bytes[16 - right.length + i] = right[i]!;\n\n return bytes;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"SkillMdParser.d.ts","sourceRoot":"","sources":["../../../src/tools/skill/SkillMdParser.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAChB,aAAa,EACd,MAAM,oBAAoB,CAAC;AAgB5B;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf;IAAE,WAAW,EAAE,gBAAgB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAsEzD;AA8CD;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAIlF;AAgDD;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAwBnF"}
1
+ {"version":3,"file":"SkillMdParser.d.ts","sourceRoot":"","sources":["../../../src/tools/skill/SkillMdParser.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,eAAe,EACf,gBAAgB,EAChB,aAAa,EACd,MAAM,oBAAoB,CAAC;AAgB5B;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf;IAAE,WAAW,EAAE,gBAAgB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CA0CzD;AA8CD;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAIlF;AAgDD;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAwBnF"}