diff --git a/library/package-lock.json b/library/package-lock.json index 593152104..4e7c1d320 100644 --- a/library/package-lock.json +++ b/library/package-lock.json @@ -9,6 +9,8 @@ "version": "0.0.0", "license": "AGPL-3.0-or-later", "devDependencies": { + "@aws-sdk/client-s3": "^3.637.0", + "@aws-sdk/credential-providers": "^3.637.0", "@clickhouse/client": "^1.7.0", "@fastify/cookie": "^10.0.0", "@google-cloud/functions-framework": "^3.3.0", @@ -130,12 +132,88 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@aws-crypto/crc32": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", + "dev": true, + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-crypto/crc32c": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", + "dev": true, + "dependencies": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "dev": true, + "dependencies": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dev": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dev": true, + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dev": true, + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@aws-crypto/sha256-browser": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", "dev": true, - "optional": true, "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@aws-crypto/supports-web-crypto": "^5.2.0", @@ -151,7 +229,6 @@ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", "dev": true, - "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -164,7 +241,6 @@ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", "dev": true, - "optional": true, "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" @@ -178,7 +254,6 @@ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", "dev": true, - "optional": true, "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" @@ -192,7 +267,6 @@ "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", "dev": true, - "optional": true, "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", @@ -207,7 +281,6 @@ "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", "dev": true, - "optional": true, "dependencies": { "tslib": "^2.6.2" } @@ -217,7 +290,6 @@ "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", @@ -229,7 +301,6 @@ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", "dev": true, - "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -242,7 +313,6 @@ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", "dev": true, - "optional": true, "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" @@ -256,7 +326,6 @@ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", "dev": true, - "optional": true, "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" @@ -270,7 +339,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.699.0.tgz", "integrity": "sha512-9tFt+we6AIvj/f1+nrLHuCWcQmyfux5gcBSOy9d9+zIG56YxGEX7S9TaZnybogpVV8A0BYWml36WvIHS9QjIpA==", "dev": true, - "optional": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", @@ -318,12 +386,580 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.715.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.715.0.tgz", + "integrity": "sha512-7Qq8nW+/Yf+1Prjbwt2I6BsxhY28V6mbi8WF0n8m4qbC+y9wvreNuGv0PgzuLpfcP1bacB1ItW/Wkwuw2mau0w==", + "dev": true, + "dependencies": { + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.714.0", + "@aws-sdk/client-sts": "3.714.0", + "@aws-sdk/core": "3.714.0", + "@aws-sdk/credential-provider-node": "3.714.0", + "@aws-sdk/middleware-bucket-endpoint": "3.714.0", + "@aws-sdk/middleware-expect-continue": "3.714.0", + "@aws-sdk/middleware-flexible-checksums": "3.715.0", + "@aws-sdk/middleware-host-header": "3.714.0", + "@aws-sdk/middleware-location-constraint": "3.714.0", + "@aws-sdk/middleware-logger": "3.714.0", + "@aws-sdk/middleware-recursion-detection": "3.714.0", + "@aws-sdk/middleware-sdk-s3": "3.714.0", + "@aws-sdk/middleware-ssec": "3.714.0", + "@aws-sdk/middleware-user-agent": "3.714.0", + "@aws-sdk/region-config-resolver": "3.714.0", + "@aws-sdk/signature-v4-multi-region": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@aws-sdk/util-endpoints": "3.714.0", + "@aws-sdk/util-user-agent-browser": "3.714.0", + "@aws-sdk/util-user-agent-node": "3.714.0", + "@aws-sdk/xml-builder": "3.709.0", + "@smithy/config-resolver": "^3.0.13", + "@smithy/core": "^2.5.5", + "@smithy/eventstream-serde-browser": "^3.0.14", + "@smithy/eventstream-serde-config-resolver": "^3.0.11", + "@smithy/eventstream-serde-node": "^3.0.13", + "@smithy/fetch-http-handler": "^4.1.2", + "@smithy/hash-blob-browser": "^3.1.10", + "@smithy/hash-node": "^3.0.11", + "@smithy/hash-stream-node": "^3.1.10", + "@smithy/invalid-dependency": "^3.0.11", + "@smithy/md5-js": "^3.0.11", + "@smithy/middleware-content-length": "^3.0.13", + "@smithy/middleware-endpoint": "^3.2.5", + "@smithy/middleware-retry": "^3.0.30", + "@smithy/middleware-serde": "^3.0.11", + "@smithy/middleware-stack": "^3.0.11", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/node-http-handler": "^3.3.2", + "@smithy/protocol-http": "^4.1.8", + "@smithy/smithy-client": "^3.5.0", + "@smithy/types": "^3.7.2", + "@smithy/url-parser": "^3.0.11", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.30", + "@smithy/util-defaults-mode-node": "^3.0.30", + "@smithy/util-endpoints": "^2.1.7", + "@smithy/util-middleware": "^3.0.11", + "@smithy/util-retry": "^3.0.11", + "@smithy/util-stream": "^3.3.2", + "@smithy/util-utf8": "^3.0.0", + "@smithy/util-waiter": "^3.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/client-sso": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.714.0.tgz", + "integrity": "sha512-pFtjY5Ga91qrryo0UfbjetdT2p9rOgtHofogAeEuGjxx7/rupBpdlW0WDOtD/7jhmbhM8WZEr6aH7GLzzkKfCA==", + "dev": true, + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.714.0", + "@aws-sdk/middleware-host-header": "3.714.0", + "@aws-sdk/middleware-logger": "3.714.0", + "@aws-sdk/middleware-recursion-detection": "3.714.0", + "@aws-sdk/middleware-user-agent": "3.714.0", + "@aws-sdk/region-config-resolver": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@aws-sdk/util-endpoints": "3.714.0", + "@aws-sdk/util-user-agent-browser": "3.714.0", + "@aws-sdk/util-user-agent-node": "3.714.0", + "@smithy/config-resolver": "^3.0.13", + "@smithy/core": "^2.5.5", + "@smithy/fetch-http-handler": "^4.1.2", + "@smithy/hash-node": "^3.0.11", + "@smithy/invalid-dependency": "^3.0.11", + "@smithy/middleware-content-length": "^3.0.13", + "@smithy/middleware-endpoint": "^3.2.5", + "@smithy/middleware-retry": "^3.0.30", + "@smithy/middleware-serde": "^3.0.11", + "@smithy/middleware-stack": "^3.0.11", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/node-http-handler": "^3.3.2", + "@smithy/protocol-http": "^4.1.8", + "@smithy/smithy-client": "^3.5.0", + "@smithy/types": "^3.7.2", + "@smithy/url-parser": "^3.0.11", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.30", + "@smithy/util-defaults-mode-node": "^3.0.30", + "@smithy/util-endpoints": "^2.1.7", + "@smithy/util-middleware": "^3.0.11", + "@smithy/util-retry": "^3.0.11", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/client-sso-oidc": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.714.0.tgz", + "integrity": "sha512-dMvpPUaL3v01psPY1ZyCzQ/w2tOgQTH1if0zBF5r2q7Vc0oOPzbBZgNAhG1bDWlRCBW0iXmoqRFoWUwQ5rtx+A==", + "dev": true, + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.714.0", + "@aws-sdk/credential-provider-node": "3.714.0", + "@aws-sdk/middleware-host-header": "3.714.0", + "@aws-sdk/middleware-logger": "3.714.0", + "@aws-sdk/middleware-recursion-detection": "3.714.0", + "@aws-sdk/middleware-user-agent": "3.714.0", + "@aws-sdk/region-config-resolver": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@aws-sdk/util-endpoints": "3.714.0", + "@aws-sdk/util-user-agent-browser": "3.714.0", + "@aws-sdk/util-user-agent-node": "3.714.0", + "@smithy/config-resolver": "^3.0.13", + "@smithy/core": "^2.5.5", + "@smithy/fetch-http-handler": "^4.1.2", + "@smithy/hash-node": "^3.0.11", + "@smithy/invalid-dependency": "^3.0.11", + "@smithy/middleware-content-length": "^3.0.13", + "@smithy/middleware-endpoint": "^3.2.5", + "@smithy/middleware-retry": "^3.0.30", + "@smithy/middleware-serde": "^3.0.11", + "@smithy/middleware-stack": "^3.0.11", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/node-http-handler": "^3.3.2", + "@smithy/protocol-http": "^4.1.8", + "@smithy/smithy-client": "^3.5.0", + "@smithy/types": "^3.7.2", + "@smithy/url-parser": "^3.0.11", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.30", + "@smithy/util-defaults-mode-node": "^3.0.30", + "@smithy/util-endpoints": "^2.1.7", + "@smithy/util-middleware": "^3.0.11", + "@smithy/util-retry": "^3.0.11", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.714.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/client-sts": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.714.0.tgz", + "integrity": "sha512-ThcXgolapPsOzeavJF4Am312umFyoFBBeiTYD8PQGIiYkbJi4hXcjoWacmtkq6moMmMZSP9iK/ellls7vwY2JQ==", + "dev": true, + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.714.0", + "@aws-sdk/core": "3.714.0", + "@aws-sdk/credential-provider-node": "3.714.0", + "@aws-sdk/middleware-host-header": "3.714.0", + "@aws-sdk/middleware-logger": "3.714.0", + "@aws-sdk/middleware-recursion-detection": "3.714.0", + "@aws-sdk/middleware-user-agent": "3.714.0", + "@aws-sdk/region-config-resolver": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@aws-sdk/util-endpoints": "3.714.0", + "@aws-sdk/util-user-agent-browser": "3.714.0", + "@aws-sdk/util-user-agent-node": "3.714.0", + "@smithy/config-resolver": "^3.0.13", + "@smithy/core": "^2.5.5", + "@smithy/fetch-http-handler": "^4.1.2", + "@smithy/hash-node": "^3.0.11", + "@smithy/invalid-dependency": "^3.0.11", + "@smithy/middleware-content-length": "^3.0.13", + "@smithy/middleware-endpoint": "^3.2.5", + "@smithy/middleware-retry": "^3.0.30", + "@smithy/middleware-serde": "^3.0.11", + "@smithy/middleware-stack": "^3.0.11", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/node-http-handler": "^3.3.2", + "@smithy/protocol-http": "^4.1.8", + "@smithy/smithy-client": "^3.5.0", + "@smithy/types": "^3.7.2", + "@smithy/url-parser": "^3.0.11", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.30", + "@smithy/util-defaults-mode-node": "^3.0.30", + "@smithy/util-endpoints": "^2.1.7", + "@smithy/util-middleware": "^3.0.11", + "@smithy/util-retry": "^3.0.11", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/core": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.714.0.tgz", + "integrity": "sha512-TlZ50d8MEPVp9O03SvisOmcmxjxhMDKHJJcrBgYjgDej6QmNfiFwtCRkReXDdkEeXP29ehMs7uPXtmVvPqziYw==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.714.0", + "@smithy/core": "^2.5.5", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/property-provider": "^3.1.11", + "@smithy/protocol-http": "^4.1.8", + "@smithy/signature-v4": "^4.2.4", + "@smithy/smithy-client": "^3.5.0", + "@smithy/types": "^3.7.2", + "@smithy/util-middleware": "^3.0.11", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.714.0.tgz", + "integrity": "sha512-0S4nKE1a+EHXAInXUeuWkyzVnXzmwIbwLStVidAIoyl6sJF8xGdw+r3AaoTr7p0YXzdoDUsn3wBTCA6ZwgXVbA==", + "dev": true, + "dependencies": { + "@aws-sdk/core": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@smithy/property-provider": "^3.1.11", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.714.0.tgz", + "integrity": "sha512-1AXEfUSQUQg+x/DpH1XJhjf2yEgTHHatM3cvYu7FZMhRXF28Q5OJDbEFPfdqrK+vmCiYRWhszDb+zuUIvz46bw==", + "dev": true, + "dependencies": { + "@aws-sdk/core": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@smithy/fetch-http-handler": "^4.1.2", + "@smithy/node-http-handler": "^3.3.2", + "@smithy/property-provider": "^3.1.11", + "@smithy/protocol-http": "^4.1.8", + "@smithy/smithy-client": "^3.5.0", + "@smithy/types": "^3.7.2", + "@smithy/util-stream": "^3.3.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.714.0.tgz", + "integrity": "sha512-w5wOcgBngfcvVev5wnYWXoc/W2ewVmGJkfRdGquhFt8pkUxktyd8eXehqkP7u31SONVlgy96EFTdSCzWpTrqOw==", + "dev": true, + "dependencies": { + "@aws-sdk/core": "3.714.0", + "@aws-sdk/credential-provider-env": "3.714.0", + "@aws-sdk/credential-provider-http": "3.714.0", + "@aws-sdk/credential-provider-process": "3.714.0", + "@aws-sdk/credential-provider-sso": "3.714.0", + "@aws-sdk/credential-provider-web-identity": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@smithy/credential-provider-imds": "^3.2.8", + "@smithy/property-provider": "^3.1.11", + "@smithy/shared-ini-file-loader": "^3.1.12", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.714.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.714.0.tgz", + "integrity": "sha512-ebho1HYNKzaw0ZfbI9kEicSW8J7tsOoV6EJajsjfFnuP+GY9J5Oi4759GEq1Qqj7GxIhrySOZFzif/hxAXPWtQ==", + "dev": true, + "dependencies": { + "@aws-sdk/credential-provider-env": "3.714.0", + "@aws-sdk/credential-provider-http": "3.714.0", + "@aws-sdk/credential-provider-ini": "3.714.0", + "@aws-sdk/credential-provider-process": "3.714.0", + "@aws-sdk/credential-provider-sso": "3.714.0", + "@aws-sdk/credential-provider-web-identity": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@smithy/credential-provider-imds": "^3.2.8", + "@smithy/property-provider": "^3.1.11", + "@smithy/shared-ini-file-loader": "^3.1.12", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.714.0.tgz", + "integrity": "sha512-mHM+zYJDUiXggBx4YvQgMOhbkV07KUib8/jWPnAZbUJcRncN/yevAp/WNocjUN4VaBWkooJUgoTET/okRK+TCQ==", + "dev": true, + "dependencies": { + "@aws-sdk/core": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@smithy/property-provider": "^3.1.11", + "@smithy/shared-ini-file-loader": "^3.1.12", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.714.0.tgz", + "integrity": "sha512-LQyHUQd+/A0PO96m6/A3KeekRplRpG9AmwLn8VPknlmACAhhbWHehzerCTd42V8dClf5pigr25/aVqh/2p/sRw==", + "dev": true, + "dependencies": { + "@aws-sdk/client-sso": "3.714.0", + "@aws-sdk/core": "3.714.0", + "@aws-sdk/token-providers": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@smithy/property-provider": "^3.1.11", + "@smithy/shared-ini-file-loader": "^3.1.12", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.714.0.tgz", + "integrity": "sha512-piKfEJvLrGZ0bH4NPO19d1dtfCZi2p6YJUK/9vRCD1rvJidOuHNeUwIcxTnkIMovQHX12rZVvU9ub0C3CwegUQ==", + "dev": true, + "dependencies": { + "@aws-sdk/core": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@smithy/property-provider": "^3.1.11", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.714.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.714.0.tgz", + "integrity": "sha512-6l68kjNrh5QC8FGX3I3geBDavWN5Tg1RLHJ2HLA8ByGBtJyCwnz3hEkKfaxn0bBx0hF9DzbfjEOUF6cDqy2Kjg==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.714.0", + "@smithy/protocol-http": "^4.1.8", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-logger": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.714.0.tgz", + "integrity": "sha512-RkqHlMvQWUaRklU1bMfUuBvdWwxgUtEqpADaHXlGVj3vtEY2UgBjy+57CveC4MByqKIunNvVHBBbjrGVtwY7Lg==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.714.0", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.714.0.tgz", + "integrity": "sha512-AVU5ixnh93nqtsfgNc284oXsXaadyHGPHpql/jwgaaqQfEXjS/1/j3j9E/vpacfTTz2Vzo7hAOjnvrOXSEVDaA==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.714.0", + "@smithy/protocol-http": "^4.1.8", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.714.0.tgz", + "integrity": "sha512-OgLjJf7WxUqA2OgiqGCfIc68gsbXlIG8LjObBiF0qlMStAd0L23AGuK5VmYinJlsle9qUpwQvWgKFKaDgdQXgA==", + "dev": true, + "dependencies": { + "@aws-sdk/core": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@aws-sdk/util-endpoints": "3.714.0", + "@smithy/core": "^2.5.5", + "@smithy/protocol-http": "^4.1.8", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.714.0.tgz", + "integrity": "sha512-HJzsQxgMOAzZrbf/YIqEx30or4tZK1oNAk6Wm6xecUQx+23JXIaePRu1YFUOLBBERQ4QBPpISFurZWBMZ5ibAw==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.714.0", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/types": "^3.7.2", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.11", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/token-providers": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.714.0.tgz", + "integrity": "sha512-vKN064aLE3kl+Zl16Ony3jltHnMddMBT7JRkP1L+lLywhA0PcAKxpdvComul/sTBWnbnwLnaS5NsDUhcWySH8A==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.714.0", + "@smithy/property-provider": "^3.1.11", + "@smithy/shared-ini-file-loader": "^3.1.12", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sso-oidc": "^3.714.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/types": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.714.0.tgz", + "integrity": "sha512-ZjpP2gYbSFlxxaUDa1Il5AVvfggvUPbjzzB/l3q0gIE5Thd6xKW+yzEpt2mLZ5s5UaYSABZbF94g8NUOF4CVGA==", + "dev": true, + "dependencies": { + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-endpoints": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.714.0.tgz", + "integrity": "sha512-Xv+Z2lhe7w7ZZRsgBwBMZgGTVmS+dkkj2S13uNHAx9lhB5ovM8PhK5G/j28xYf6vIibeuHkRAbb7/ozdZIGR+A==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.714.0", + "@smithy/types": "^3.7.2", + "@smithy/util-endpoints": "^2.1.7", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.714.0.tgz", + "integrity": "sha512-OdJJ03cP9/MgIVToPJPCPUImbpZzTcwdIgbXC0tUQPJhbD7b7cB4LdnkhNHko+MptpOrCq4CPY/33EpOjRdofw==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.714.0", + "@smithy/types": "^3.7.2", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.714.0.tgz", + "integrity": "sha512-x8JoZb7yBEbNUmHUNoRAP4L++6A5uZCVf2yFLw8CZKpH4q+Cf1a68ou48OfnND3H0rbBnLXc/3uOlseRvd57/g==", + "dev": true, + "dependencies": { + "@aws-sdk/middleware-user-agent": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/client-s3/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/@aws-sdk/client-sso": { "version": "3.696.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.696.0.tgz", "integrity": "sha512-q5TTkd08JS0DOkHfUL853tuArf7NrPeqoS5UOvqJho8ibV9Ak/a/HO4kNvy9Nj3cib/toHYHsQIEtecUPSUUrQ==", "dev": true, - "optional": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", @@ -373,7 +1009,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.699.0.tgz", "integrity": "sha512-u8a1GorY5D1l+4FQAf4XBUC1T10/t7neuwT21r0ymrtMFSK2a9QqVHKMoLkvavAwyhJnARSBM9/UQC797PFOFw==", "dev": true, - "optional": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", @@ -427,7 +1062,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.699.0.tgz", "integrity": "sha512-++lsn4x2YXsZPIzFVwv3fSUVM55ZT0WRFmPeNilYIhZClxHLmVAWKH4I55cY9ry60/aTKYjzOXkWwyBKGsGvQg==", "dev": true, - "optional": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", @@ -479,7 +1113,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.696.0.tgz", "integrity": "sha512-3c9III1k03DgvRZWg8vhVmfIXPG6hAciN9MzQTzqGngzWAELZF/WONRTRQuDFixVtarQatmLHYVw/atGeA2Byw==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/types": "3.696.0", "@smithy/core": "^2.5.3", @@ -512,7 +1145,6 @@ "url": "https://paypal.me/naturalintelligence" } ], - "optional": true, "dependencies": { "strnum": "^1.0.5" }, @@ -525,7 +1157,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.699.0.tgz", "integrity": "sha512-iuaTnudaBfEET+o444sDwf71Awe6UiZfH+ipUPmswAi2jZDwdFF1nxMKDEKL8/LV5WpXsdKSfwgS0RQeupURew==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/client-cognito-identity": "3.699.0", "@aws-sdk/types": "3.696.0", @@ -542,7 +1173,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.696.0.tgz", "integrity": "sha512-T9iMFnJL7YTlESLpVFT3fg1Lkb1lD+oiaIC8KMpepb01gDUBIpj9+Y+pA/cgRWW0yRxmkDXNazAE2qQTVFGJzA==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/core": "3.696.0", "@aws-sdk/types": "3.696.0", @@ -559,7 +1189,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.696.0.tgz", "integrity": "sha512-GV6EbvPi2eq1+WgY/o2RFA3P7HGmnkIzCNmhwtALFlqMroLYWKE7PSeHw66Uh1dFQeVESn0/+hiUNhu1mB0emA==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/core": "3.696.0", "@aws-sdk/types": "3.696.0", @@ -581,7 +1210,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.699.0.tgz", "integrity": "sha512-dXmCqjJnKmG37Q+nLjPVu22mNkrGHY8hYoOt3Jo9R2zr5MYV7s/NHsCHr+7E+BZ+tfZYLRPeB1wkpTeHiEcdRw==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/core": "3.696.0", "@aws-sdk/credential-provider-env": "3.696.0", @@ -608,7 +1236,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.699.0.tgz", "integrity": "sha512-MmEmNDo1bBtTgRmdNfdQksXu4uXe66s0p1hi1YPrn1h59Q605eq/xiWbGL6/3KdkViH6eGUuABeV2ODld86ylg==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/credential-provider-env": "3.696.0", "@aws-sdk/credential-provider-http": "3.696.0", @@ -632,7 +1259,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.696.0.tgz", "integrity": "sha512-mL1RcFDe9sfmyU5K1nuFkO8UiJXXxLX4JO1gVaDIOvPqwStpUAwi3A1BoeZhWZZNQsiKI810RnYGo0E0WB/hUA==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/core": "3.696.0", "@aws-sdk/types": "3.696.0", @@ -650,7 +1276,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.699.0.tgz", "integrity": "sha512-Ekp2cZG4pl9D8+uKWm4qO1xcm8/MeiI8f+dnlZm8aQzizeC+aXYy9GyoclSf6daK8KfRPiRfM7ZHBBL5dAfdMA==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/client-sso": "3.696.0", "@aws-sdk/core": "3.696.0", @@ -670,7 +1295,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.696.0.tgz", "integrity": "sha512-XJ/CVlWChM0VCoc259vWguFUjJDn/QwDqHwbx+K9cg3v6yrqXfK5ai+p/6lx0nQpnk4JzPVeYYxWRpaTsGC9rg==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/core": "3.696.0", "@aws-sdk/types": "3.696.0", @@ -690,7 +1314,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.699.0.tgz", "integrity": "sha512-jBjOntl9zN9Nvb0jmbMGRbiTzemDz64ij7W6BDavxBJRZpRoNeN0QCz6RolkCyXnyUJjo5mF2unY2wnv00A+LQ==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/client-cognito-identity": "3.699.0", "@aws-sdk/client-sso": "3.696.0", @@ -714,12 +1337,151 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.714.0.tgz", + "integrity": "sha512-I/xSOskiseJJ8i183Z522BgqbgYzLKP7jGcg2Qeib/IWoG2IP+9DH8pwqagKaPAycyswtnoKBJiiFXY43n0CkA==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.714.0", + "@aws-sdk/util-arn-parser": "3.693.0", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/protocol-http": "^4.1.8", + "@smithy/types": "^3.7.2", + "@smithy/util-config-provider": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/@aws-sdk/types": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.714.0.tgz", + "integrity": "sha512-ZjpP2gYbSFlxxaUDa1Il5AVvfggvUPbjzzB/l3q0gIE5Thd6xKW+yzEpt2mLZ5s5UaYSABZbF94g8NUOF4CVGA==", + "dev": true, + "dependencies": { + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.714.0.tgz", + "integrity": "sha512-rlzsXdG8Lzo4Qpl35ZnpOBAWlzvDHpP9++0AXoUwAJA0QmMm7auIRmgxJuNj91VwT9h15ZU6xjU4S7fJl4W0+w==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.714.0", + "@smithy/protocol-http": "^4.1.8", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-expect-continue/node_modules/@aws-sdk/types": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.714.0.tgz", + "integrity": "sha512-ZjpP2gYbSFlxxaUDa1Il5AVvfggvUPbjzzB/l3q0gIE5Thd6xKW+yzEpt2mLZ5s5UaYSABZbF94g8NUOF4CVGA==", + "dev": true, + "dependencies": { + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.715.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.715.0.tgz", + "integrity": "sha512-oDUxpwBZqQ0x7c9typmaX7cHxFsyxwApQPuPYV4hSTBsLtqpDc7KtyV+lgxQxkgoHya6P37+Wwllr4FjcujXwg==", + "dev": true, + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", + "@aws-sdk/core": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/protocol-http": "^4.1.8", + "@smithy/types": "^3.7.2", + "@smithy/util-middleware": "^3.0.11", + "@smithy/util-stream": "^3.3.2", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@aws-sdk/core": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.714.0.tgz", + "integrity": "sha512-TlZ50d8MEPVp9O03SvisOmcmxjxhMDKHJJcrBgYjgDej6QmNfiFwtCRkReXDdkEeXP29ehMs7uPXtmVvPqziYw==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.714.0", + "@smithy/core": "^2.5.5", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/property-provider": "^3.1.11", + "@smithy/protocol-http": "^4.1.8", + "@smithy/signature-v4": "^4.2.4", + "@smithy/smithy-client": "^3.5.0", + "@smithy/types": "^3.7.2", + "@smithy/util-middleware": "^3.0.11", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@aws-sdk/types": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.714.0.tgz", + "integrity": "sha512-ZjpP2gYbSFlxxaUDa1Il5AVvfggvUPbjzzB/l3q0gIE5Thd6xKW+yzEpt2mLZ5s5UaYSABZbF94g8NUOF4CVGA==", + "dev": true, + "dependencies": { + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, "node_modules/@aws-sdk/middleware-host-header": { "version": "3.696.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.696.0.tgz", "integrity": "sha512-zELJp9Ta2zkX7ELggMN9qMCgekqZhFC5V2rOr4hJDEb/Tte7gpfKSObAnw/3AYiVqt36sjHKfdkoTsuwGdEoDg==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/types": "3.696.0", "@smithy/protocol-http": "^4.1.7", @@ -730,31 +1492,165 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.714.0.tgz", + "integrity": "sha512-MX7M+V+FblujKck3fyuzePVIAy9530gY719IiSxV6uN1qLHl7VDJxNblpF/KpXakD6rOg8OpvtmqsXj9aBMftw==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.714.0", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-location-constraint/node_modules/@aws-sdk/types": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.714.0.tgz", + "integrity": "sha512-ZjpP2gYbSFlxxaUDa1Il5AVvfggvUPbjzzB/l3q0gIE5Thd6xKW+yzEpt2mLZ5s5UaYSABZbF94g8NUOF4CVGA==", + "dev": true, + "dependencies": { + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/middleware-logger": { "version": "3.696.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.696.0.tgz", "integrity": "sha512-KhkHt+8AjCxcR/5Zp3++YPJPpFQzxpr+jmONiT/Jw2yqnSngZ0Yspm5wGoRx2hS1HJbyZNuaOWEGuJoxLeBKfA==", "dev": true, - "optional": true, "dependencies": { - "@aws-sdk/types": "3.696.0", - "@smithy/types": "^3.7.1", + "@aws-sdk/types": "3.696.0", + "@smithy/types": "^3.7.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.696.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.696.0.tgz", + "integrity": "sha512-si/maV3Z0hH7qa99f9ru2xpS5HlfSVcasRlNUXKSDm611i7jFMWwGNLUOXFAOLhXotPX5G3Z6BLwL34oDeBMug==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.696.0", + "@smithy/protocol-http": "^4.1.7", + "@smithy/types": "^3.7.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.714.0.tgz", + "integrity": "sha512-YYhX+JefwwEsUxYs0YXn5Mfb97Lo3hwnk3qRIlUkcotCsHYwgCX4jVWjeh8HK+RFFx3Krbh/8/YmzTkI/Z4Z9Q==", + "dev": true, + "dependencies": { + "@aws-sdk/core": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@aws-sdk/util-arn-parser": "3.693.0", + "@smithy/core": "^2.5.5", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/protocol-http": "^4.1.8", + "@smithy/signature-v4": "^4.2.4", + "@smithy/smithy-client": "^3.5.0", + "@smithy/types": "^3.7.2", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.11", + "@smithy/util-stream": "^3.3.2", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@aws-sdk/core": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.714.0.tgz", + "integrity": "sha512-TlZ50d8MEPVp9O03SvisOmcmxjxhMDKHJJcrBgYjgDej6QmNfiFwtCRkReXDdkEeXP29ehMs7uPXtmVvPqziYw==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.714.0", + "@smithy/core": "^2.5.5", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/property-provider": "^3.1.11", + "@smithy/protocol-http": "^4.1.8", + "@smithy/signature-v4": "^4.2.4", + "@smithy/smithy-client": "^3.5.0", + "@smithy/types": "^3.7.2", + "@smithy/util-middleware": "^3.0.11", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@aws-sdk/types": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.714.0.tgz", + "integrity": "sha512-ZjpP2gYbSFlxxaUDa1Il5AVvfggvUPbjzzB/l3q0gIE5Thd6xKW+yzEpt2mLZ5s5UaYSABZbF94g8NUOF4CVGA==", + "dev": true, + "dependencies": { + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/@aws-sdk/middleware-ssec": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.714.0.tgz", + "integrity": "sha512-RkK8REAVwNUQmYbIDRw8eYbMJ8F1Rw4C9mlME4BBMhFlelGcD3ErU2ce24moQbDxBjNwHNESmIqgmdQk93CDCQ==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.714.0", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { "node": ">=16.0.0" } }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.696.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.696.0.tgz", - "integrity": "sha512-si/maV3Z0hH7qa99f9ru2xpS5HlfSVcasRlNUXKSDm611i7jFMWwGNLUOXFAOLhXotPX5G3Z6BLwL34oDeBMug==", + "node_modules/@aws-sdk/middleware-ssec/node_modules/@aws-sdk/types": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.714.0.tgz", + "integrity": "sha512-ZjpP2gYbSFlxxaUDa1Il5AVvfggvUPbjzzB/l3q0gIE5Thd6xKW+yzEpt2mLZ5s5UaYSABZbF94g8NUOF4CVGA==", "dev": true, - "optional": true, "dependencies": { - "@aws-sdk/types": "3.696.0", - "@smithy/protocol-http": "^4.1.7", - "@smithy/types": "^3.7.1", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { @@ -766,7 +1662,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.696.0.tgz", "integrity": "sha512-Lvyj8CTyxrHI6GHd2YVZKIRI5Fmnugt3cpJo0VrKKEgK5zMySwEZ1n4dqPK6czYRWKd5+WnYHYAuU+Wdk6Jsjw==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/core": "3.696.0", "@aws-sdk/types": "3.696.0", @@ -785,7 +1680,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.696.0.tgz", "integrity": "sha512-7EuH142lBXjI8yH6dVS/CZeiK/WZsmb/8zP6bQbVYpMrppSTgB3MzZZdxVZGzL5r8zPQOU10wLC4kIMy0qdBVQ==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/types": "3.696.0", "@smithy/node-config-provider": "^3.1.11", @@ -798,12 +1692,41 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.714.0.tgz", + "integrity": "sha512-xIQyx0ILRtJZnSUPpMsWkwASuFDYh9GPnr7p+pmfsV5KtRQluHuoH1wPkPTeNuTnAl7RDHUOmcOgTPUCDxiKxg==", + "dev": true, + "dependencies": { + "@aws-sdk/middleware-sdk-s3": "3.714.0", + "@aws-sdk/types": "3.714.0", + "@smithy/protocol-http": "^4.1.8", + "@smithy/signature-v4": "^4.2.4", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@aws-sdk/types": { + "version": "3.714.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.714.0.tgz", + "integrity": "sha512-ZjpP2gYbSFlxxaUDa1Il5AVvfggvUPbjzzB/l3q0gIE5Thd6xKW+yzEpt2mLZ5s5UaYSABZbF94g8NUOF4CVGA==", + "dev": true, + "dependencies": { + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/token-providers": { "version": "3.699.0", "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.699.0.tgz", "integrity": "sha512-kuiEW9DWs7fNos/SM+y58HCPhcIzm1nEZLhe2/7/6+TvAYLuEWURYsbK48gzsxXlaJ2k/jGY3nIsA7RptbMOwA==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/types": "3.696.0", "@smithy/property-provider": "^3.1.9", @@ -823,7 +1746,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.696.0.tgz", "integrity": "sha512-9rTvUJIAj5d3//U5FDPWGJ1nFJLuWb30vugGOrWk7aNZ6y9tuA3PI7Cc9dP8WEXKVyK1vuuk8rSFP2iqXnlgrw==", "dev": true, - "optional": true, "dependencies": { "@smithy/types": "^3.7.1", "tslib": "^2.6.2" @@ -832,12 +1754,23 @@ "node": ">=16.0.0" } }, + "node_modules/@aws-sdk/util-arn-parser": { + "version": "3.693.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.693.0.tgz", + "integrity": "sha512-WC8x6ca+NRrtpAH64rWu+ryDZI3HuLwlEr8EU6/dbC/pt+r/zC0PBoC15VEygUaBA+isppCikQpGyEDu0Yj7gQ==", + "dev": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@aws-sdk/util-endpoints": { "version": "3.696.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.696.0.tgz", "integrity": "sha512-T5s0IlBVX+gkb9g/I6CLt4yAZVzMSiGnbUqWihWsHvQR1WOoIcndQy/Oz/IJXT9T2ipoy7a80gzV6a5mglrioA==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/types": "3.696.0", "@smithy/types": "^3.7.1", @@ -853,7 +1786,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.693.0.tgz", "integrity": "sha512-ttrag6haJLWABhLqtg1Uf+4LgHWIMOVSYL+VYZmAp2v4PUGOwWmWQH0Zk8RM7YuQcLfH/EoR72/Yxz6A4FKcuw==", "dev": true, - "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -866,7 +1798,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.696.0.tgz", "integrity": "sha512-Z5rVNDdmPOe6ELoM5AhF/ja5tSjbe6ctSctDPb0JdDf4dT0v2MfwhJKzXju2RzX8Es/77Glh7MlaXLE0kCB9+Q==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/types": "3.696.0", "@smithy/types": "^3.7.1", @@ -879,7 +1810,6 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.696.0.tgz", "integrity": "sha512-KhKqcfyXIB0SCCt+qsu4eJjsfiOrNzK5dCV7RAW2YIpp+msxGUUX0NdRE9rkzjiv+3EMktgJm3eEIS+yxtlVdQ==", "dev": true, - "optional": true, "dependencies": { "@aws-sdk/middleware-user-agent": "3.696.0", "@aws-sdk/types": "3.696.0", @@ -899,6 +1829,19 @@ } } }, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.709.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.709.0.tgz", + "integrity": "sha512-2GPCwlNxeHspoK/Mc8nbk9cBOkSpp3j2SJUQmFnyQK6V/pR6II2oPRyZkMomug1Rc10hqlBHByMecq4zhV2uUw==", + "dev": true, + "dependencies": { + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.26.2", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", @@ -3381,30 +4324,47 @@ } }, "node_modules/@smithy/abort-controller": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.8.tgz", - "integrity": "sha512-+3DOBcUn5/rVjlxGvUPKc416SExarAQ+Qe0bqk30YSUjbepwpS7QN0cyKUSifvLJhdMZ0WPzPP5ymut0oonrpQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.9.tgz", + "integrity": "sha512-yiW0WI30zj8ZKoSYNx90no7ugVn3khlyH/z5W8qtKBtVE6awRALbhSG+2SAHA1r6bO/6M9utxYKVZ3PCJ1rWxw==", "dev": true, - "optional": true, "dependencies": { - "@smithy/types": "^3.7.1", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { "node": ">=16.0.0" } }, + "node_modules/@smithy/chunked-blob-reader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-4.0.0.tgz", + "integrity": "sha512-jSqRnZvkT4egkq/7b6/QRCNXmmYVcHwnJldqJ3IhVpQE2atObVJ137xmGeuGFhjFUr8gCEVAOKwSY79OvpbDaQ==", + "dev": true, + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.1.tgz", + "integrity": "sha512-VEYtPvh5rs/xlyqpm5NRnfYLZn+q0SRPELbvBV+C/G7IQ+ouTuo+NKKa3ShG5OaFR8NYVMXls9hPYLTvIKKDrQ==", + "dev": true, + "dependencies": { + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, "node_modules/@smithy/config-resolver": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.12.tgz", - "integrity": "sha512-YAJP9UJFZRZ8N+UruTeq78zkdjUHmzsY62J4qKWZ4SXB4QXJ/+680EfXXgkYA2xj77ooMqtUY9m406zGNqwivQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.13.tgz", + "integrity": "sha512-Gr/qwzyPaTL1tZcq8WQyHhTZREER5R1Wytmz4WnVGL4onA3dNk6Btll55c8Vr58pLdvWZmtG8oZxJTw3t3q7Jg==", "dev": true, - "optional": true, "dependencies": { - "@smithy/node-config-provider": "^3.1.11", - "@smithy/types": "^3.7.1", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/types": "^3.7.2", "@smithy/util-config-provider": "^3.0.0", - "@smithy/util-middleware": "^3.0.10", + "@smithy/util-middleware": "^3.0.11", "tslib": "^2.6.2" }, "engines": { @@ -3412,18 +4372,17 @@ } }, "node_modules/@smithy/core": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.5.4.tgz", - "integrity": "sha512-iFh2Ymn2sCziBRLPuOOxRPkuCx/2gBdXtBGuCUFLUe6bWYjKnhHyIPqGeNkLZ5Aco/5GjebRTBFiWID3sDbrKw==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.5.5.tgz", + "integrity": "sha512-G8G/sDDhXA7o0bOvkc7bgai6POuSld/+XhNnWAbpQTpLv2OZPvyqQ58tLPPlz0bSNsXktldDDREIv1LczFeNEw==", "dev": true, - "optional": true, "dependencies": { - "@smithy/middleware-serde": "^3.0.10", - "@smithy/protocol-http": "^4.1.7", - "@smithy/types": "^3.7.1", + "@smithy/middleware-serde": "^3.0.11", + "@smithy/protocol-http": "^4.1.8", + "@smithy/types": "^3.7.2", "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-middleware": "^3.0.10", - "@smithy/util-stream": "^3.3.1", + "@smithy/util-middleware": "^3.0.11", + "@smithy/util-stream": "^3.3.2", "@smithy/util-utf8": "^3.0.0", "tslib": "^2.6.2" }, @@ -3432,16 +4391,82 @@ } }, "node_modules/@smithy/credential-provider-imds": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.7.tgz", - "integrity": "sha512-cEfbau+rrWF8ylkmmVAObOmjbTIzKyUC5TkBL58SbLywD0RCBC4JAUKbmtSm2w5KUJNRPGgpGFMvE2FKnuNlWQ==", + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.8.tgz", + "integrity": "sha512-ZCY2yD0BY+K9iMXkkbnjo+08T2h8/34oHd0Jmh6BZUSZwaaGlGCyBT/3wnS7u7Xl33/EEfN4B6nQr3Gx5bYxgw==", "dev": true, - "optional": true, "dependencies": { - "@smithy/node-config-provider": "^3.1.11", - "@smithy/property-provider": "^3.1.10", - "@smithy/types": "^3.7.1", - "@smithy/url-parser": "^3.0.10", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/property-provider": "^3.1.11", + "@smithy/types": "^3.7.2", + "@smithy/url-parser": "^3.0.11", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.10.tgz", + "integrity": "sha512-323B8YckSbUH0nMIpXn7HZsAVKHYHFUODa8gG9cHo0ySvA1fr5iWaNT+iIL0UCqUzG6QPHA3BSsBtRQou4mMqQ==", + "dev": true, + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^3.7.2", + "@smithy/util-hex-encoding": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.14.tgz", + "integrity": "sha512-kbrt0vjOIihW3V7Cqj1SXQvAI5BR8SnyQYsandva0AOR307cXAc+IhPngxIPslxTLfxwDpNu0HzCAq6g42kCPg==", + "dev": true, + "dependencies": { + "@smithy/eventstream-serde-universal": "^3.0.13", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.11.tgz", + "integrity": "sha512-P2pnEp4n75O+QHjyO7cbw/vsw5l93K/8EWyjNCAAybYwUmj3M+hjSQZ9P5TVdUgEG08ueMAP5R4FkuSkElZ5tQ==", + "dev": true, + "dependencies": { + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.13.tgz", + "integrity": "sha512-zqy/9iwbj8Wysmvi7Lq7XFLeDgjRpTbCfwBhJa8WbrylTAHiAu6oQTwdY7iu2lxigbc9YYr9vPv5SzYny5tCXQ==", + "dev": true, + "dependencies": { + "@smithy/eventstream-serde-universal": "^3.0.13", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.13.tgz", + "integrity": "sha512-L1Ib66+gg9uTnqp/18Gz4MDpJPKRE44geOjOQ2SVc0eiaO5l255ADziATZgjQjqumC7yPtp1XnjHlF1srcwjKw==", + "dev": true, + "dependencies": { + "@smithy/eventstream-codec": "^3.1.10", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { @@ -3449,27 +4474,37 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-4.1.1.tgz", - "integrity": "sha512-bH7QW0+JdX0bPBadXt8GwMof/jz0H28I84hU1Uet9ISpzUqXqRQ3fEZJ+ANPOhzSEczYvANNl3uDQDYArSFDtA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-4.1.2.tgz", + "integrity": "sha512-R7rU7Ae3ItU4rC0c5mB2sP5mJNbCfoDc8I5XlYjIZnquyUwec7fEo78F6DA3SmgJgkU1qTMcZJuGblxZsl10ZA==", "dev": true, - "optional": true, "dependencies": { - "@smithy/protocol-http": "^4.1.7", - "@smithy/querystring-builder": "^3.0.10", - "@smithy/types": "^3.7.1", + "@smithy/protocol-http": "^4.1.8", + "@smithy/querystring-builder": "^3.0.11", + "@smithy/types": "^3.7.2", "@smithy/util-base64": "^3.0.0", "tslib": "^2.6.2" } }, + "node_modules/@smithy/hash-blob-browser": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.10.tgz", + "integrity": "sha512-elwslXOoNunmfS0fh55jHggyhccobFkexLYC1ZeZ1xP2BTSrcIBaHV2b4xUQOdctrSNOpMqOZH1r2XzWTEhyfA==", + "dev": true, + "dependencies": { + "@smithy/chunked-blob-reader": "^4.0.0", + "@smithy/chunked-blob-reader-native": "^3.0.1", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + } + }, "node_modules/@smithy/hash-node": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.10.tgz", - "integrity": "sha512-3zWGWCHI+FlJ5WJwx73Mw2llYR8aflVyZN5JhoqLxbdPZi6UyKSdCeXAWJw9ja22m6S6Tzz1KZ+kAaSwvydi0g==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.11.tgz", + "integrity": "sha512-emP23rwYyZhQBvklqTtwetkQlqbNYirDiEEwXl2v0GYWMnCzxst7ZaRAnWuy28njp5kAH54lvkdG37MblZzaHA==", "dev": true, - "optional": true, "dependencies": { - "@smithy/types": "^3.7.1", + "@smithy/types": "^3.7.2", "@smithy/util-buffer-from": "^3.0.0", "@smithy/util-utf8": "^3.0.0", "tslib": "^2.6.2" @@ -3478,14 +4513,27 @@ "node": ">=16.0.0" } }, + "node_modules/@smithy/hash-stream-node": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-3.1.10.tgz", + "integrity": "sha512-olomK/jZQ93OMayW1zfTHwcbwBdhcZOHsyWyiZ9h9IXvc1mCD/VuvzbLb3Gy/qNJwI4MANPLctTp2BucV2oU/Q==", + "dev": true, + "dependencies": { + "@smithy/types": "^3.7.2", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@smithy/invalid-dependency": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.10.tgz", - "integrity": "sha512-Lp2L65vFi+cj0vFMu2obpPW69DU+6O5g3086lmI4XcnRCG8PxvpWC7XyaVwJCxsZFzueHjXnrOH/E0pl0zikfA==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.11.tgz", + "integrity": "sha512-NuQmVPEJjUX6c+UELyVz8kUx8Q539EDeNwbRyu4IIF8MeV7hUtq1FB3SHVyki2u++5XLMFqngeMKk7ccspnNyQ==", "dev": true, - "optional": true, "dependencies": { - "@smithy/types": "^3.7.1", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" } }, @@ -3494,7 +4542,6 @@ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", "dev": true, - "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -3502,15 +4549,25 @@ "node": ">=16.0.0" } }, + "node_modules/@smithy/md5-js": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-3.0.11.tgz", + "integrity": "sha512-3NM0L3i2Zm4bbgG6Ymi9NBcxXhryi3uE8fIfHJZIOfZVxOkGdjdgjR9A06SFIZCfnEIWKXZdm6Yq5/aPXFFhsQ==", + "dev": true, + "dependencies": { + "@smithy/types": "^3.7.2", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, "node_modules/@smithy/middleware-content-length": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.12.tgz", - "integrity": "sha512-1mDEXqzM20yywaMDuf5o9ue8OkJ373lSPbaSjyEvkWdqELhFMyNNgKGWL/rCSf4KME8B+HlHKuR8u9kRj8HzEQ==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.13.tgz", + "integrity": "sha512-zfMhzojhFpIX3P5ug7jxTjfUcIPcGjcQYzB9t+rv0g1TX7B0QdwONW+ATouaLoD7h7LOw/ZlXfkq4xJ/g2TrIw==", "dev": true, - "optional": true, "dependencies": { - "@smithy/protocol-http": "^4.1.7", - "@smithy/types": "^3.7.1", + "@smithy/protocol-http": "^4.1.8", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { @@ -3518,19 +4575,18 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.4.tgz", - "integrity": "sha512-TybiW2LA3kYVd3e+lWhINVu1o26KJbBwOpADnf0L4x/35vLVica77XVR5hvV9+kWeTGeSJ3IHTcYxbRxlbwhsg==", - "dev": true, - "optional": true, - "dependencies": { - "@smithy/core": "^2.5.4", - "@smithy/middleware-serde": "^3.0.10", - "@smithy/node-config-provider": "^3.1.11", - "@smithy/shared-ini-file-loader": "^3.1.11", - "@smithy/types": "^3.7.1", - "@smithy/url-parser": "^3.0.10", - "@smithy/util-middleware": "^3.0.10", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.5.tgz", + "integrity": "sha512-VhJNs/s/lyx4weiZdXSloBgoLoS8osV0dKIain8nGmx7of3QFKu5BSdEuk1z/U8x9iwes1i+XCiNusEvuK1ijg==", + "dev": true, + "dependencies": { + "@smithy/core": "^2.5.5", + "@smithy/middleware-serde": "^3.0.11", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/shared-ini-file-loader": "^3.1.12", + "@smithy/types": "^3.7.2", + "@smithy/url-parser": "^3.0.11", + "@smithy/util-middleware": "^3.0.11", "tslib": "^2.6.2" }, "engines": { @@ -3538,19 +4594,18 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "3.0.28", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.28.tgz", - "integrity": "sha512-vK2eDfvIXG1U64FEUhYxoZ1JSj4XFbYWkK36iz02i3pFwWiDz1Q7jKhGTBCwx/7KqJNk4VS7d7cDLXFOvP7M+g==", - "dev": true, - "optional": true, - "dependencies": { - "@smithy/node-config-provider": "^3.1.11", - "@smithy/protocol-http": "^4.1.7", - "@smithy/service-error-classification": "^3.0.10", - "@smithy/smithy-client": "^3.4.5", - "@smithy/types": "^3.7.1", - "@smithy/util-middleware": "^3.0.10", - "@smithy/util-retry": "^3.0.10", + "version": "3.0.30", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.30.tgz", + "integrity": "sha512-6323RL2BvAR3VQpTjHpa52kH/iSHyxd/G9ohb2MkBk2Ucu+oMtRXT8yi7KTSIS9nb58aupG6nO0OlXnQOAcvmQ==", + "dev": true, + "dependencies": { + "@smithy/node-config-provider": "^3.1.12", + "@smithy/protocol-http": "^4.1.8", + "@smithy/service-error-classification": "^3.0.11", + "@smithy/smithy-client": "^3.5.0", + "@smithy/types": "^3.7.2", + "@smithy/util-middleware": "^3.0.11", + "@smithy/util-retry": "^3.0.11", "tslib": "^2.6.2", "uuid": "^9.0.1" }, @@ -3567,19 +4622,17 @@ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], - "optional": true, "bin": { "uuid": "dist/bin/uuid" } }, "node_modules/@smithy/middleware-serde": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.10.tgz", - "integrity": "sha512-MnAuhh+dD14F428ubSJuRnmRsfOpxSzvRhaGVTvd/lrUDE3kxzCCmH8lnVTvoNQnV2BbJ4c15QwZ3UdQBtFNZA==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.11.tgz", + "integrity": "sha512-KzPAeySp/fOoQA82TpnwItvX8BBURecpx6ZMu75EZDkAcnPtO6vf7q4aH5QHs/F1s3/snQaSFbbUMcFFZ086Mw==", "dev": true, - "optional": true, "dependencies": { - "@smithy/types": "^3.7.1", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { @@ -3587,13 +4640,12 @@ } }, "node_modules/@smithy/middleware-stack": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.10.tgz", - "integrity": "sha512-grCHyoiARDBBGPyw2BeicpjgpsDFWZZxptbVKb3CRd/ZA15F/T6rZjCCuBUjJwdck1nwUuIxYtsS4H9DDpbP5w==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.11.tgz", + "integrity": "sha512-1HGo9a6/ikgOMrTrWL/WiN9N8GSVYpuRQO5kjstAq4CvV59bjqnh7TbdXGQ4vxLD3xlSjfBjq5t1SOELePsLnA==", "dev": true, - "optional": true, "dependencies": { - "@smithy/types": "^3.7.1", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { @@ -3601,15 +4653,14 @@ } }, "node_modules/@smithy/node-config-provider": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.11.tgz", - "integrity": "sha512-URq3gT3RpDikh/8MBJUB+QGZzfS7Bm6TQTqoh4CqE8NBuyPkWa5eUXj0XFcFfeZVgg3WMh1u19iaXn8FvvXxZw==", + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.12.tgz", + "integrity": "sha512-O9LVEu5J/u/FuNlZs+L7Ikn3lz7VB9hb0GtPT9MQeiBmtK8RSY3ULmsZgXhe6VAlgTw0YO+paQx4p8xdbs43vQ==", "dev": true, - "optional": true, "dependencies": { - "@smithy/property-provider": "^3.1.10", - "@smithy/shared-ini-file-loader": "^3.1.11", - "@smithy/types": "^3.7.1", + "@smithy/property-provider": "^3.1.11", + "@smithy/shared-ini-file-loader": "^3.1.12", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { @@ -3617,16 +4668,15 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.3.1.tgz", - "integrity": "sha512-fr+UAOMGWh6bn4YSEezBCpJn9Ukp9oR4D32sCjCo7U81evE11YePOQ58ogzyfgmjIO79YeOdfXXqr0jyhPQeMg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.3.2.tgz", + "integrity": "sha512-t4ng1DAd527vlxvOfKFYEe6/QFBcsj7WpNlWTyjorwXXcKw3XlltBGbyHfSJ24QT84nF+agDha9tNYpzmSRZPA==", "dev": true, - "optional": true, "dependencies": { - "@smithy/abort-controller": "^3.1.8", - "@smithy/protocol-http": "^4.1.7", - "@smithy/querystring-builder": "^3.0.10", - "@smithy/types": "^3.7.1", + "@smithy/abort-controller": "^3.1.9", + "@smithy/protocol-http": "^4.1.8", + "@smithy/querystring-builder": "^3.0.11", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { @@ -3634,13 +4684,12 @@ } }, "node_modules/@smithy/property-provider": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.10.tgz", - "integrity": "sha512-n1MJZGTorTH2DvyTVj+3wXnd4CzjJxyXeOgnTlgNVFxaaMeT4OteEp4QrzF8p9ee2yg42nvyVK6R/awLCakjeQ==", + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz", + "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==", "dev": true, - "optional": true, "dependencies": { - "@smithy/types": "^3.7.1", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { @@ -3648,13 +4697,12 @@ } }, "node_modules/@smithy/protocol-http": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.7.tgz", - "integrity": "sha512-FP2LepWD0eJeOTm0SjssPcgqAlDFzOmRXqXmGhfIM52G7Lrox/pcpQf6RP4F21k0+O12zaqQt5fCDOeBtqY6Cg==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.8.tgz", + "integrity": "sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw==", "dev": true, - "optional": true, "dependencies": { - "@smithy/types": "^3.7.1", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { @@ -3662,13 +4710,12 @@ } }, "node_modules/@smithy/querystring-builder": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.10.tgz", - "integrity": "sha512-nT9CQF3EIJtIUepXQuBFb8dxJi3WVZS3XfuDksxSCSn+/CzZowRLdhDn+2acbBv8R6eaJqPupoI/aRFIImNVPQ==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.11.tgz", + "integrity": "sha512-u+5HV/9uJaeLj5XTb6+IEF/dokWWkEqJ0XiaRRogyREmKGUgZnNecLucADLdauWFKUNbQfulHFEZEdjwEBjXRg==", "dev": true, - "optional": true, "dependencies": { - "@smithy/types": "^3.7.1", + "@smithy/types": "^3.7.2", "@smithy/util-uri-escape": "^3.0.0", "tslib": "^2.6.2" }, @@ -3677,13 +4724,12 @@ } }, "node_modules/@smithy/querystring-parser": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.10.tgz", - "integrity": "sha512-Oa0XDcpo9SmjhiDD9ua2UyM3uU01ZTuIrNdZvzwUTykW1PM8o2yJvMh1Do1rY5sUQg4NDV70dMi0JhDx4GyxuQ==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.11.tgz", + "integrity": "sha512-Je3kFvCsFMnso1ilPwA7GtlbPaTixa3WwC+K21kmMZHsBEOZYQaqxcMqeFFoU7/slFjKDIpiiPydvdJm8Q/MCw==", "dev": true, - "optional": true, "dependencies": { - "@smithy/types": "^3.7.1", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { @@ -3691,26 +4737,24 @@ } }, "node_modules/@smithy/service-error-classification": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.10.tgz", - "integrity": "sha512-zHe642KCqDxXLuhs6xmHVgRwy078RfqxP2wRDpIyiF8EmsWXptMwnMwbVa50lw+WOGNrYm9zbaEg0oDe3PTtvQ==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.11.tgz", + "integrity": "sha512-QnYDPkyewrJzCyaeI2Rmp7pDwbUETe+hU8ADkXmgNusO1bgHBH7ovXJiYmba8t0fNfJx75fE8dlM6SEmZxheog==", "dev": true, - "optional": true, "dependencies": { - "@smithy/types": "^3.7.1" + "@smithy/types": "^3.7.2" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.11.tgz", - "integrity": "sha512-AUdrIZHFtUgmfSN4Gq9nHu3IkHMa1YDcN+s061Nfm+6pQ0mJy85YQDB0tZBCmls0Vuj22pLwDPmL92+Hvfwwlg==", + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.12.tgz", + "integrity": "sha512-1xKSGI+U9KKdbG2qDvIR9dGrw3CNx+baqJfyr0igKEpjbHL5stsqAesYBzHChYHlelWtb87VnLWlhvfCz13H8Q==", "dev": true, - "optional": true, "dependencies": { - "@smithy/types": "^3.7.1", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { @@ -3718,17 +4762,16 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.2.3.tgz", - "integrity": "sha512-pPSQQ2v2vu9vc8iew7sszLd0O09I5TRc5zhY71KA+Ao0xYazIG+uLeHbTJfIWGO3BGVLiXjUr3EEeCcEQLjpWQ==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.2.4.tgz", + "integrity": "sha512-5JWeMQYg81TgU4cG+OexAWdvDTs5JDdbEZx+Qr1iPbvo91QFGzjy0IkXAKaXUHqmKUJgSHK0ZxnCkgZpzkeNTA==", "dev": true, - "optional": true, "dependencies": { "@smithy/is-array-buffer": "^3.0.0", - "@smithy/protocol-http": "^4.1.7", - "@smithy/types": "^3.7.1", + "@smithy/protocol-http": "^4.1.8", + "@smithy/types": "^3.7.2", "@smithy/util-hex-encoding": "^3.0.0", - "@smithy/util-middleware": "^3.0.10", + "@smithy/util-middleware": "^3.0.11", "@smithy/util-uri-escape": "^3.0.0", "@smithy/util-utf8": "^3.0.0", "tslib": "^2.6.2" @@ -3738,18 +4781,17 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.4.5.tgz", - "integrity": "sha512-k0sybYT9zlP79sIKd1XGm4TmK0AS1nA2bzDHXx7m0nGi3RQ8dxxQUs4CPkSmQTKAo+KF9aINU3KzpGIpV7UoMw==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.5.0.tgz", + "integrity": "sha512-Y8FeOa7gbDfCWf7njrkoRATPa5eNLUEjlJS5z5rXatYuGkCb80LbHcu8AQR8qgAZZaNHCLyo2N+pxPsV7l+ivg==", "dev": true, - "optional": true, "dependencies": { - "@smithy/core": "^2.5.4", - "@smithy/middleware-endpoint": "^3.2.4", - "@smithy/middleware-stack": "^3.0.10", - "@smithy/protocol-http": "^4.1.7", - "@smithy/types": "^3.7.1", - "@smithy/util-stream": "^3.3.1", + "@smithy/core": "^2.5.5", + "@smithy/middleware-endpoint": "^3.2.5", + "@smithy/middleware-stack": "^3.0.11", + "@smithy/protocol-http": "^4.1.8", + "@smithy/types": "^3.7.2", + "@smithy/util-stream": "^3.3.2", "tslib": "^2.6.2" }, "engines": { @@ -3757,11 +4799,10 @@ } }, "node_modules/@smithy/types": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.7.1.tgz", - "integrity": "sha512-XKLcLXZY7sUQgvvWyeaL/qwNPp6V3dWcUjqrQKjSb+tzYiCy340R/c64LV5j+Tnb2GhmunEX0eou+L+m2hJNYA==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.7.2.tgz", + "integrity": "sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==", "dev": true, - "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -3770,14 +4811,13 @@ } }, "node_modules/@smithy/url-parser": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.10.tgz", - "integrity": "sha512-j90NUalTSBR2NaZTuruEgavSdh8MLirf58LoGSk4AtQfyIymogIhgnGUU2Mga2bkMkpSoC9gxb74xBXL5afKAQ==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.11.tgz", + "integrity": "sha512-TmlqXkSk8ZPhfc+SQutjmFr5FjC0av3GZP4B/10caK1SbRwe/v+Wzu/R6xEKxoNqL+8nY18s1byiy6HqPG37Aw==", "dev": true, - "optional": true, "dependencies": { - "@smithy/querystring-parser": "^3.0.10", - "@smithy/types": "^3.7.1", + "@smithy/querystring-parser": "^3.0.11", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" } }, @@ -3786,7 +4826,6 @@ "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", "dev": true, - "optional": true, "dependencies": { "@smithy/util-buffer-from": "^3.0.0", "@smithy/util-utf8": "^3.0.0", @@ -3801,7 +4840,6 @@ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", "dev": true, - "optional": true, "dependencies": { "tslib": "^2.6.2" } @@ -3811,7 +4849,6 @@ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", "dev": true, - "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -3824,7 +4861,6 @@ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", "dev": true, - "optional": true, "dependencies": { "@smithy/is-array-buffer": "^3.0.0", "tslib": "^2.6.2" @@ -3838,7 +4874,6 @@ "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", "dev": true, - "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -3847,15 +4882,14 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.28", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.28.tgz", - "integrity": "sha512-6bzwAbZpHRFVJsOztmov5PGDmJYsbNSoIEfHSJJyFLzfBGCCChiO3od9k7E/TLgrCsIifdAbB9nqbVbyE7wRUw==", + "version": "3.0.30", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.30.tgz", + "integrity": "sha512-nLuGmgfcr0gzm64pqF2UT4SGWVG8UGviAdayDlVzJPNa6Z4lqvpDzdRXmLxtOdEjVlTOEdpZ9dd3ZMMu488mzg==", "dev": true, - "optional": true, "dependencies": { - "@smithy/property-provider": "^3.1.10", - "@smithy/smithy-client": "^3.4.5", - "@smithy/types": "^3.7.1", + "@smithy/property-provider": "^3.1.11", + "@smithy/smithy-client": "^3.5.0", + "@smithy/types": "^3.7.2", "bowser": "^2.11.0", "tslib": "^2.6.2" }, @@ -3864,18 +4898,17 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.28", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.28.tgz", - "integrity": "sha512-78ENJDorV1CjOQselGmm3+z7Yqjj5HWCbjzh0Ixuq736dh1oEnD9sAttSBNSLlpZsX8VQnmERqA2fEFlmqWn8w==", + "version": "3.0.30", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.30.tgz", + "integrity": "sha512-OD63eWoH68vp75mYcfYyuVH+p7Li/mY4sYOROnauDrtObo1cS4uWfsy/zhOTW8F8ZPxQC1ZXZKVxoxvMGUv2Ow==", "dev": true, - "optional": true, "dependencies": { - "@smithy/config-resolver": "^3.0.12", - "@smithy/credential-provider-imds": "^3.2.7", - "@smithy/node-config-provider": "^3.1.11", - "@smithy/property-provider": "^3.1.10", - "@smithy/smithy-client": "^3.4.5", - "@smithy/types": "^3.7.1", + "@smithy/config-resolver": "^3.0.13", + "@smithy/credential-provider-imds": "^3.2.8", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/property-provider": "^3.1.11", + "@smithy/smithy-client": "^3.5.0", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { @@ -3883,14 +4916,13 @@ } }, "node_modules/@smithy/util-endpoints": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.6.tgz", - "integrity": "sha512-mFV1t3ndBh0yZOJgWxO9J/4cHZVn5UG1D8DeCc6/echfNkeEJWu9LD7mgGH5fHrEdR7LDoWw7PQO6QiGpHXhgA==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.7.tgz", + "integrity": "sha512-tSfcqKcN/Oo2STEYCABVuKgJ76nyyr6skGl9t15hs+YaiU06sgMkN7QYjo0BbVw+KT26zok3IzbdSOksQ4YzVw==", "dev": true, - "optional": true, "dependencies": { - "@smithy/node-config-provider": "^3.1.11", - "@smithy/types": "^3.7.1", + "@smithy/node-config-provider": "^3.1.12", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { @@ -3902,7 +4934,6 @@ "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", "dev": true, - "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -3911,13 +4942,12 @@ } }, "node_modules/@smithy/util-middleware": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.10.tgz", - "integrity": "sha512-eJO+/+RsrG2RpmY68jZdwQtnfsxjmPxzMlQpnHKjFPwrYqvlcT+fHdT+ZVwcjlWSrByOhGr9Ff2GG17efc192A==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.11.tgz", + "integrity": "sha512-dWpyc1e1R6VoXrwLoLDd57U1z6CwNSdkM69Ie4+6uYh2GC7Vg51Qtan7ITzczuVpqezdDTKJGJB95fFvvjU/ow==", "dev": true, - "optional": true, "dependencies": { - "@smithy/types": "^3.7.1", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { @@ -3925,14 +4955,13 @@ } }, "node_modules/@smithy/util-retry": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.10.tgz", - "integrity": "sha512-1l4qatFp4PiU6j7UsbasUHL2VU023NRB/gfaa1M0rDqVrRN4g3mCArLRyH3OuktApA4ye+yjWQHjdziunw2eWA==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.11.tgz", + "integrity": "sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==", "dev": true, - "optional": true, "dependencies": { - "@smithy/service-error-classification": "^3.0.10", - "@smithy/types": "^3.7.1", + "@smithy/service-error-classification": "^3.0.11", + "@smithy/types": "^3.7.2", "tslib": "^2.6.2" }, "engines": { @@ -3940,15 +4969,14 @@ } }, "node_modules/@smithy/util-stream": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.3.1.tgz", - "integrity": "sha512-Ff68R5lJh2zj+AUTvbAU/4yx+6QPRzg7+pI7M1FbtQHcRIp7xvguxVsQBKyB3fwiOwhAKu0lnNyYBaQfSW6TNw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.3.2.tgz", + "integrity": "sha512-sInAqdiVeisUGYAv/FrXpmJ0b4WTFmciTRqzhb7wVuem9BHvhIG7tpiYHLDWrl2stOokNZpTTGqz3mzB2qFwXg==", "dev": true, - "optional": true, "dependencies": { - "@smithy/fetch-http-handler": "^4.1.1", - "@smithy/node-http-handler": "^3.3.1", - "@smithy/types": "^3.7.1", + "@smithy/fetch-http-handler": "^4.1.2", + "@smithy/node-http-handler": "^3.3.2", + "@smithy/types": "^3.7.2", "@smithy/util-base64": "^3.0.0", "@smithy/util-buffer-from": "^3.0.0", "@smithy/util-hex-encoding": "^3.0.0", @@ -3964,7 +4992,6 @@ "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", "dev": true, - "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -3977,7 +5004,6 @@ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", "dev": true, - "optional": true, "dependencies": { "@smithy/util-buffer-from": "^3.0.0", "tslib": "^2.6.2" @@ -3986,6 +5012,20 @@ "node": ">=16.0.0" } }, + "node_modules/@smithy/util-waiter": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-3.2.0.tgz", + "integrity": "sha512-PpjSboaDUE6yl+1qlg3Si57++e84oXdWGbuFUSAciXsVfEZJJJupR2Nb0QuXHiunt2vGR+1PTizOMvnUPaG2Qg==", + "dev": true, + "dependencies": { + "@smithy/abort-controller": "^3.1.9", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@tapjs/after": { "version": "1.1.22", "resolved": "https://registry.npmjs.org/@tapjs/after/-/after-1.1.22.tgz", @@ -6231,8 +7271,7 @@ "version": "2.11.0", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", - "dev": true, - "optional": true + "dev": true }, "node_modules/brace-expansion": { "version": "2.0.1", diff --git a/library/package.json b/library/package.json index 810670a38..3779e5115 100644 --- a/library/package.json +++ b/library/package.json @@ -44,6 +44,8 @@ "devDependencies": { "@clickhouse/client": "^1.7.0", "@fastify/cookie": "^10.0.0", + "@aws-sdk/client-s3": "^3.637.0", + "@aws-sdk/credential-providers": "^3.637.0", "@google-cloud/functions-framework": "^3.3.0", "@google-cloud/pubsub": "^4.3.3", "@graphql-tools/executor": "^1.3.2", diff --git a/library/sinks/AwsSDKVersion3.test.ts b/library/sinks/AwsSDKVersion3.test.ts new file mode 100644 index 000000000..b1eb5631a --- /dev/null +++ b/library/sinks/AwsSDKVersion3.test.ts @@ -0,0 +1,40 @@ +import { CreateBucketCommand, ListBucketsCommand } from "@aws-sdk/client-s3"; +import { fromEnv } from "@aws-sdk/credential-providers"; +import * as t from "tap"; +import { createTestAgent } from "../helpers/createTestAgent"; +import { HTTPRequest } from "./HTTPRequest"; + +t.test("it works", async (t) => { + const agent = createTestAgent(); + + agent.start([new HTTPRequest()]); + + const { S3Client } = + require("@aws-sdk/client-s3") as typeof import("@aws-sdk/client-s3"); + + process.env.AWS_ACCESS_KEY_ID = "test"; + process.env.AWS_SECRET_ACCESS_KEY = "test"; + + const s3 = new S3Client({ + region: "us-east-1", + endpoint: "http://localhost:9090", + credentials: fromEnv(), + forcePathStyle: true, + }); + + const name = "bucket"; + + try { + await s3.send(new CreateBucketCommand({ Bucket: name })); + } catch (err: any) { + if (err.Code !== "BucketAlreadyOwnedByYou") { + throw err; + } + } + + const buckets = await s3.send(new ListBucketsCommand({})); + t.same( + buckets.Buckets?.map((bucket) => bucket.Name), + [name] + ); +}); diff --git a/library/sinks/HTTPRequest.axios.test.ts b/library/sinks/HTTPRequest.axios.test.ts index 036ab8678..0cd6ffbba 100644 --- a/library/sinks/HTTPRequest.axios.test.ts +++ b/library/sinks/HTTPRequest.axios.test.ts @@ -21,11 +21,8 @@ const context: Context = { const redirectTestUrl = "http://ssrf-redirects.testssandbox.com"; -t.test("it works", { skip: "SSRF redirect check disabled atm" }, async (t) => { - const agent = createTestAgent({ - token: new Token("123"), - }); - +t.test("it works", async (t) => { + const agent = createTestAgent(); agent.start([new HTTPRequest()]); t.same(agent.getHostnames().asArray(), []); @@ -33,11 +30,11 @@ t.test("it works", { skip: "SSRF redirect check disabled atm" }, async (t) => { const axios = require("axios"); await runWithContext(context, async () => { - await axios.request("https://www.aikido.dev"); + await axios.request("https://app.aikido.dev"); }); t.same(agent.getHostnames().asArray(), [ - { hostname: "www.aikido.dev", port: 443, hits: 1 }, + { hostname: "app.aikido.dev", port: 443, hits: 1 }, ]); agent.getHostnames().clear(); diff --git a/library/sinks/HTTPRequest.context.test.ts b/library/sinks/HTTPRequest.context.test.ts new file mode 100644 index 000000000..7f7ad3fe0 --- /dev/null +++ b/library/sinks/HTTPRequest.context.test.ts @@ -0,0 +1,66 @@ +/* eslint-disable prefer-rest-params */ +import * as t from "tap"; +import { Agent } from "../agent/Agent"; +import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; +import { Token } from "../agent/api/Token"; +import { Context, getContext, runWithContext } from "../agent/Context"; +import { LoggerNoop } from "../agent/logger/LoggerNoop"; +import { createTestAgent } from "../helpers/createTestAgent"; +import { HTTPRequest } from "./HTTPRequest"; + +const source = + "http://firewallssrfredirects-env-2.eba-7ifve22q.eu-north-1.elasticbeanstalk.com/ssrf-test"; +const destination = "http://127.0.0.1/test"; + +const context: Context = { + remoteAddress: "::1", + method: "POST", + url: "http://localhost:4000", + query: {}, + headers: {}, + body: { + image: source, + }, + cookies: {}, + routeParams: {}, + source: "express", + route: "/posts/:id", +}; + +t.test("it wraps ", (t) => { + const agent = createTestAgent({ + token: new Token("123"), + }); + agent.start([new HTTPRequest()]); + + const http = require("http") as typeof import("http"); + + runWithContext(context, () => { + const request = http.request(source, (res) => { + res.on("data", () => {}); + }); + + request.on("response", (res) => { + t.same( + getContext()!.outgoingRequestRedirects!.map((r) => ({ + source: r.source.toString(), + destination: r.destination.toString(), + })), + [ + { + source: source, + destination: destination, + }, + ] + ); + t.end(); + }); + + request.on("error", (e) => { + t.fail(e); + t.end(); + }); + + request.end(); + }); +}); diff --git a/library/sinks/HTTPRequest.followRedirects.test.ts b/library/sinks/HTTPRequest.followRedirects.test.ts index da84d8e96..2e613ed7e 100644 --- a/library/sinks/HTTPRequest.followRedirects.test.ts +++ b/library/sinks/HTTPRequest.followRedirects.test.ts @@ -1,3 +1,4 @@ +import type { IncomingMessage } from "http"; import * as t from "tap"; import { Token } from "../agent/api/Token"; import { Context, runWithContext } from "../agent/Context"; @@ -22,6 +23,14 @@ const context: Context = { let server: import("http").Server; const port = 3000; +function consumeBody(res: IncomingMessage) { + // We need to consume the body + // From Node.19+ this would otherwise hang the test + res.on("readable", () => { + while (res.read() !== null) {} + }); +} + t.before(async () => { const { createServer } = require("http") as typeof import("http"); @@ -39,7 +48,7 @@ t.before(async () => { const redirectTestUrl = "http://ssrf-redirects.testssandbox.com"; -t.test("it works", { skip: "SSRF redirect check disabled atm" }, (t) => { +t.test("it works", (t) => { const agent = createTestAgent({ token: new Token("123"), }); @@ -120,8 +129,7 @@ t.test("it works", { skip: "SSRF redirect check disabled atm" }, (t) => { }, () => { const response = http.request(`http://[::]:${port}`, (res) => { - // consume body - while (res.read()) {} + consumeBody(res); t.same(res.statusCode, 200); }); diff --git a/library/sinks/HTTPRequest.localhost.test.ts b/library/sinks/HTTPRequest.localhost.test.ts index 127429055..baf5b14e7 100644 --- a/library/sinks/HTTPRequest.localhost.test.ts +++ b/library/sinks/HTTPRequest.localhost.test.ts @@ -1,11 +1,8 @@ /* eslint-disable prefer-rest-params */ import * as t from "tap"; -import { Agent } from "../agent/Agent"; import { createServer, IncomingMessage, Server } from "http"; -import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Token } from "../agent/api/Token"; import { Context, runWithContext } from "../agent/Context"; -import { LoggerNoop } from "../agent/logger/LoggerNoop"; import { createTestAgent } from "../helpers/createTestAgent"; import { HTTPRequest } from "./HTTPRequest"; @@ -52,6 +49,14 @@ function createContext({ }; } +function consumeBody(res: IncomingMessage) { + // We need to consume the body + // From Node.19+ this would otherwise hang the test + res.on("readable", () => { + while (res.read() !== null) {} + }); +} + const agent = createTestAgent({ token: new Token("123"), }); @@ -92,8 +97,8 @@ t.test("it does not block request to localhost with same port", (t) => { // The server should respond with a 200 // Because we'll allow requests to localhost if it's the same port t.same(response.statusCode, 200); - response.on("data", () => {}); - response.on("end", () => {}); + + consumeBody(response); }); request.end(); } @@ -129,8 +134,8 @@ t.test("it blocks requests to other ports", (t) => { request.on("response", (response: IncomingMessage) => { // This should not be called t.fail(); - response.on("data", () => {}); - response.on("end", () => {}); + + consumeBody(response); }); request.end(); } catch (error) { diff --git a/library/sinks/HTTPRequest.needle.test.ts b/library/sinks/HTTPRequest.needle.test.ts index 6407d2638..21af43c48 100644 --- a/library/sinks/HTTPRequest.needle.test.ts +++ b/library/sinks/HTTPRequest.needle.test.ts @@ -1,83 +1,106 @@ import * as t from "tap"; import { Token } from "../agent/api/Token"; import { Context, runWithContext } from "../agent/Context"; +import { getMajorNodeVersion } from "../helpers/getNodeVersion"; import { HTTPRequest } from "./HTTPRequest"; import { createTestAgent } from "../helpers/createTestAgent"; -const context: Context = { - remoteAddress: "::1", - method: "POST", - url: "http://localhost:4000", - query: {}, - headers: {}, - body: { - image: "http://localhost:5000/api/internal", - }, - cookies: {}, - routeParams: {}, - source: "express", - route: "/posts/:id", -}; - -const redirectTestUrl = "http://ssrf-redirects.testssandbox.com"; +function createContext(obj = {}): Context { + return { + ...{ + remoteAddress: "::1", + method: "POST", + url: "http://localhost:4000", + query: {}, + headers: {}, + body: { + image: "http://localhost:5000/api/internal", + }, + cookies: {}, + routeParams: {}, + source: "express", + route: "/posts/:id", + }, + ...obj, + }; +} -t.test("it works", { skip: "SSRF redirect check disabled atm" }, async (t) => { - const agent = createTestAgent({ - token: new Token("123"), - }); +t.test("it works", async (t) => { + const agent = createTestAgent(); agent.start([new HTTPRequest()]); t.same(agent.getHostnames().asArray(), []); const needle = require("needle") as typeof import("needle"); - await runWithContext(context, async () => { - await needle("get", "https://www.aikido.dev"); + await runWithContext(createContext(), async () => { + await needle("get", "https://app.aikido.dev"); }); t.same(agent.getHostnames().asArray(), [ - { hostname: "www.aikido.dev", port: 443, hits: 1 }, + { hostname: "app.aikido.dev", port: 443, hits: 1 }, ]); agent.getHostnames().clear(); const error = await t.rejects( async () => - await runWithContext(context, async () => { + await runWithContext(createContext(), async () => { await needle("get", "http://localhost:5000/api/internal"); }) ); + + t.ok(error instanceof Error); if (error instanceof Error) { t.same( error.message, "Zen has blocked a server-side request forgery: http.request(...) originating from body.image" ); } - - await runWithContext( - { - ...context, - ...{ body: { image: `${redirectTestUrl}/ssrf-test-domain` } }, - }, - async () => { - await new Promise((resolve) => { - needle.request( - "get", - `${redirectTestUrl}/ssrf-test-domain`, - {}, - { - // eslint-disable-next-line camelcase - follow_max: 1, - }, - (error, response) => { - t.ok(error instanceof Error); - t.match( - error?.message, - /Zen has blocked a server-side request forgery/ - ); - resolve(); - } - ); - }); - } - ); }); + +const redirectTestUrl = "http://ssrf-redirects.testssandbox.com"; + +t.test( + "it detects SSRF attacks with redirects", + { + skip: + getMajorNodeVersion() >= 19 ? "This request hangs on Node.js 19+" : false, + }, + async (t) => { + const agent = createTestAgent({ + token: new Token("123"), + }); + agent.start([new HTTPRequest()]); + + const needle = require("needle") as typeof import("needle"); + + await runWithContext( + createContext({ body: { image: `${redirectTestUrl}/ssrf-test-domain` } }), + async () => { + await new Promise((resolve) => { + needle.request( + "get", + `${redirectTestUrl}/ssrf-test-domain`, + {}, + { + /* eslint-disable camelcase */ + follow_max: 1, + open_timeout: 5000, + response_timeout: 5000, + read_timeout: 5000, + /* eslint-enable camelcase */ + }, + (error, response) => { + t.ok(error instanceof Error); + t.match( + error?.message, + /Zen has blocked a server-side request forgery/ + ); + resolve(); + } + ); + }); + } + ); + } +); diff --git a/library/sinks/HTTPRequest.nodeFetch.test.ts b/library/sinks/HTTPRequest.nodeFetch.test.ts index ee95a6c3c..df9735b86 100644 --- a/library/sinks/HTTPRequest.nodeFetch.test.ts +++ b/library/sinks/HTTPRequest.nodeFetch.test.ts @@ -21,10 +21,8 @@ const context: Context = { const redirectTestUrl = "http://ssrf-redirects.testssandbox.com"; -t.test("it works", { skip: "SSRF redirect check disabled atm" }, async (t) => { - const agent = createTestAgent({ - token: new Token("123"), - }); +t.test("it works", async (t) => { + const agent = createTestAgent(); agent.start([new HTTPRequest()]); t.same(agent.getHostnames().asArray(), []); @@ -32,11 +30,11 @@ t.test("it works", { skip: "SSRF redirect check disabled atm" }, async (t) => { const fetch = require("node-fetch"); await runWithContext(context, async () => { - await fetch("https://www.aikido.dev"); + await fetch("https://app.aikido.dev"); }); t.same(agent.getHostnames().asArray(), [ - { hostname: "www.aikido.dev", port: 443, hits: 1 }, + { hostname: "app.aikido.dev", port: 443, hits: 1 }, ]); agent.getHostnames().clear(); diff --git a/library/sinks/HTTPRequest.redirect.test.ts b/library/sinks/HTTPRequest.redirect.test.ts index 5b0097d66..2e917ed25 100644 --- a/library/sinks/HTTPRequest.redirect.test.ts +++ b/library/sinks/HTTPRequest.redirect.test.ts @@ -1,27 +1,33 @@ /* eslint-disable prefer-rest-params */ +import { type IncomingMessage } from "http"; import * as t from "tap"; import { Token } from "../agent/api/Token"; import { Context, runWithContext } from "../agent/Context"; import { HTTPRequest } from "./HTTPRequest"; import { createTestAgent } from "../helpers/createTestAgent"; -const context: Context = { - remoteAddress: "::1", - method: "POST", - url: "http://localhost:4000", - query: {}, - headers: {}, - body: { - image: "http://localhost:4000/api/internal", - }, - cookies: {}, - routeParams: {}, - source: "express", - route: "/posts/:id", -}; +function createContext(obj: Partial = {}): Context { + return { + ...{ + remoteAddress: "::1", + method: "POST", + url: "http://localhost:4000", + query: {}, + headers: {}, + body: { + image: "http://localhost:5000/api/internal", + }, + cookies: {}, + routeParams: {}, + source: "express", + route: "/posts/:id", + }, + ...obj, + }; +} const redirectTestUrl = "http://ssrf-redirects.testssandbox.com"; -const redirecTestUrl2 = +const redirectTestUrl2 = "http://firewallssrfredirects-env-2.eba-7ifve22q.eu-north-1.elasticbeanstalk.com"; const redirectUrl = { @@ -31,7 +37,15 @@ const redirectUrl = { domainTwice: `${redirectTestUrl}/ssrf-test-domain-twice`, // Redirects to /ssrf-test-domain }; -t.test("it works", { skip: "SSRF redirect check disabled atm" }, (t) => { +function consumeBody(res: IncomingMessage) { + // We need to consume the body + // From Node.19+ this would otherwise hang the test + res.on("readable", () => { + while (res.read() !== null) {} + }); +} + +t.test("it works", (t) => { const agent = createTestAgent({ token: new Token("123"), }); @@ -40,14 +54,16 @@ t.test("it works", { skip: "SSRF redirect check disabled atm" }, (t) => { const http = require("http") as typeof import("http"); runWithContext( - { - ...context, - ...{ body: { image: redirectUrl.ip } }, - }, + createContext({ + body: { image: redirectUrl.ip }, + }), () => { const response1 = http.request(redirectUrl.ip, (res) => { t.same(res.statusCode, 302); t.same(res.headers.location, "http://127.0.0.1/test"); + + consumeBody(res); + const error = t.throws(() => http.request("http://127.0.0.1/test")); t.ok(error instanceof Error); if (error instanceof Error) { @@ -62,16 +78,16 @@ t.test("it works", { skip: "SSRF redirect check disabled atm" }, (t) => { ); runWithContext( - { - ...context, - ...{ body: { test: redirectUrl.domain } }, - }, + createContext({ + body: { test: redirectUrl.domain }, + }), () => { const response1 = http.request(redirectUrl.domain, (res) => { t.same(res.statusCode, 302); t.same(res.headers.location, "http://local.aikido.io/test"); + consumeBody(res); + http.request("http://local.aikido.io/test").on("error", (e) => { - t.ok(e instanceof Error); t.same( e.message, "Zen has blocked a server-side request forgery: http.request(...) originating from body.test" @@ -83,15 +99,19 @@ t.test("it works", { skip: "SSRF redirect check disabled atm" }, (t) => { ); runWithContext( - { - ...context, - ...{ body: { image: redirectUrl.ipTwice } }, - }, + createContext({ + body: { image: redirectUrl.ipTwice }, + }), () => { const response1 = http.request(redirectUrl.ipTwice, (res) => { t.same(res.statusCode, 302); t.same(res.headers.location, "/ssrf-test"); + + consumeBody(res); + const response2 = http.request(redirectUrl.ip, (res) => { + consumeBody(res); + const error = t.throws(() => http.request("http://127.0.0.1/test")); t.ok(error instanceof Error); if (error instanceof Error) { @@ -108,17 +128,20 @@ t.test("it works", { skip: "SSRF redirect check disabled atm" }, (t) => { ); runWithContext( - { - ...context, - ...{ body: { image: redirectUrl.domainTwice } }, - }, + createContext({ + body: { image: redirectUrl.domainTwice }, + }), () => { const response1 = http.request(redirectUrl.domainTwice, (res) => { t.same(res.statusCode, 302); t.same(res.headers.location, "/ssrf-test-domain"); + + consumeBody(res); + const response2 = http.request(redirectUrl.domain, (res) => { + consumeBody(res); + http.request("http://local.aikido.io/test").on("error", (e) => { - t.ok(e instanceof Error); t.same( e.message, "Zen has blocked a server-side request forgery: http.request(...) originating from body.image" @@ -132,33 +155,38 @@ t.test("it works", { skip: "SSRF redirect check disabled atm" }, (t) => { ); runWithContext( - { - ...context, - ...{ - body: { - image: `${redirecTestUrl2}/ssrf-test-absolute-domain`, - }, + createContext({ + body: { + image: `${redirectTestUrl2}/ssrf-test-absolute-domain`, }, - }, + }), () => { - const response1 = http.request( - `${redirecTestUrl2}/ssrf-test-absolute-domain`, - (res) => { - t.same(res.statusCode, 302); - t.same(res.headers.location, redirectUrl.domain); - const response2 = http.request(redirectUrl.domain, (res) => { - http.request("http://local.aikido.io/test").on("error", (e) => { - t.ok(e instanceof Error); + const req1 = http.request( + `${redirectTestUrl2}/ssrf-test-absolute-domain` + ); + req1.on("response", (res) => { + t.same(res.statusCode, 302); + t.same(res.headers.location, `${redirectTestUrl2}/ssrf-test-domain`); + + consumeBody(res); + + const req2 = http.request(`${redirectTestUrl2}/ssrf-test-domain`); + req2.prependOnceListener("response", (res) => { + consumeBody(res); + + http + .request("http://local.aikido.io/test") + .on("error", (e) => { t.same( e.message, "Zen has blocked a server-side request forgery: http.request(...) originating from body.image" ); - }); - }); - response2.end(); - } - ); - response1.end(); + }) + .end(); + }); + req2.end(); + }); + req1.end(); } ); diff --git a/library/sinks/HTTPRequest.ts b/library/sinks/HTTPRequest.ts index e6b4e58ba..5b2313a0d 100644 --- a/library/sinks/HTTPRequest.ts +++ b/library/sinks/HTTPRequest.ts @@ -1,18 +1,21 @@ +import { subscribe } from "diagnostics_channel"; import { lookup } from "dns"; -import { type RequestOptions } from "http"; +import { type RequestOptions, ClientRequest, IncomingMessage } from "http"; import { Agent } from "../agent/Agent"; import { getContext } from "../agent/Context"; import { Hooks } from "../agent/hooks/Hooks"; import { InterceptorResult } from "../agent/hooks/InterceptorResult"; import { Wrapper } from "../agent/Wrapper"; +import { getSemverNodeVersion } from "../helpers/getNodeVersion"; import { getPortFromURL } from "../helpers/getPortFromURL"; +import { isVersionGreaterOrEqual } from "../helpers/isVersionGreaterOrEqual"; import { checkContextForSSRF } from "../vulnerabilities/ssrf/checkContextForSSRF"; import { inspectDNSLookupCalls } from "../vulnerabilities/ssrf/inspectDNSLookupCalls"; import { isRedirectToPrivateIP } from "../vulnerabilities/ssrf/isRedirectToPrivateIP"; import { getUrlFromHTTPRequestArgs } from "./http-request/getUrlFromHTTPRequestArgs"; -import { wrapResponseHandler } from "./http-request/wrapResponseHandler"; import { wrapExport } from "../agent/hooks/wrapExport"; import { isOptionsObject } from "./http-request/isOptionsObject"; +import { onHTTPResponse } from "./http-request/onHTTPResponse"; export class HTTPRequest implements Wrapper { private inspectHostname( @@ -144,18 +147,26 @@ export class HTTPRequest implements Wrapper { return args; } - wrapResponseHandler(args: unknown[], module: "http" | "https") { - if (args.find((arg) => typeof arg === "function")) { - return args.map((arg) => { - if (typeof arg === "function") { - return wrapResponseHandler(args, module, arg); - } + handleResponseFinish({ + request, + response, + }: { + request: ClientRequest; + response: IncomingMessage; + }) { + const context = getContext(); - return arg; - }); + if (!context) { + return; } - return args.concat([wrapResponseHandler(args, module, () => {})]); + try { + const source = + request.protocol + request.getHeader("host") + request.path; + onHTTPResponse(new URL(source), response, context); + } catch { + // Ignore errors + } } wrap(hooks: Hooks) { @@ -164,6 +175,14 @@ export class HTTPRequest implements Wrapper { for (const module of modules) { hooks.addBuiltinModule(module).onRequire((exports, pkgInfo) => { + if (isVersionGreaterOrEqual("16.17.0", getSemverNodeVersion())) { + subscribe("http.client.response.finish", (message) => + this.handleResponseFinish( + message as { request: ClientRequest; response: IncomingMessage } + ) + ); + } + for (const method of methods) { wrapExport(exports, method, pkgInfo, { // Whenever a request is made, we'll check the hostname whether it's a private IP diff --git a/library/sinks/http-request/wrapResponseHandler.ts b/library/sinks/http-request/onHTTPResponse.ts similarity index 50% rename from library/sinks/http-request/wrapResponseHandler.ts rename to library/sinks/http-request/onHTTPResponse.ts index da29aade0..b661fffa5 100644 --- a/library/sinks/http-request/wrapResponseHandler.ts +++ b/library/sinks/http-request/onHTTPResponse.ts @@ -1,50 +1,13 @@ import { IncomingMessage } from "http"; import { Context, getContext, updateContext } from "../../agent/Context"; -import { getMajorNodeVersion } from "../../helpers/getNodeVersion"; import { getPortFromURL } from "../../helpers/getPortFromURL"; import { isRedirectStatusCode } from "../../helpers/isRedirectStatusCode"; import { tryParseURL } from "../../helpers/tryParseURL"; import { findHostnameInContext } from "../../vulnerabilities/ssrf/findHostnameInContext"; import { getRedirectOrigin } from "../../vulnerabilities/ssrf/getRedirectOrigin"; -import { getUrlFromHTTPRequestArgs } from "./getUrlFromHTTPRequestArgs"; -/** - * We are wrapping the response handler for outgoing HTTP requests to detect redirects. - * If the response is a redirect, we will add the redirect to the context to be able to detect SSRF attacks with redirects. - */ -export function wrapResponseHandler( - args: unknown[], - module: "http" | "https", - fn: Function -) { - return function responseHandler(res: IncomingMessage) { - // If you don't have a response handler, pre node 19, the process will exit - // From node 19 onwards, the process will not exit if there is no response handler - if (getMajorNodeVersion() >= 19) { - // Need to attach data & end event handler otherwise the process will not exit - // As safety we'll attach the handlers only if there are no listeners - if (res.rawListeners("data").length === 0) { - res.on("data", () => {}); - } - - if (res.rawListeners("end").length === 0) { - res.on("end", () => {}); - } - } - - const context = getContext(); - if (context) { - onHTTPResponse(args, module, res, context); - } - - // eslint-disable-next-line prefer-rest-params - fn(...arguments); - }; -} - -function onHTTPResponse( - args: unknown[], - module: "http" | "https", +export function onHTTPResponse( + source: URL, res: IncomingMessage, context: Context ) { @@ -61,11 +24,6 @@ function onHTTPResponse( return; } - const source = getUrlFromHTTPRequestArgs(args, module); - if (!source) { - return; - } - addRedirectToContext(source, destination, context); } @@ -80,7 +38,7 @@ function addRedirectToContext(source: URL, destination: URL, context: Context) { // Check if the source hostname is in the context - is true if it's the first redirect in the chain and the user input is the source const found = findHostnameInContext(source.hostname, context, sourcePort); - // If the source hostname is not in the context, check if it's a redirect in a already existing chain + // If the source hostname is not in the context, check if it's a redirect in an already existing chain if (!found && context.outgoingRequestRedirects) { // Get initial source of the redirect chain (first redirect), if url is part of a redirect chain redirectOrigin = getRedirectOrigin( @@ -89,16 +47,28 @@ function addRedirectToContext(source: URL, destination: URL, context: Context) { ); } - // Get existing redirects or create a new array - const outgoingRedirects = context.outgoingRequestRedirects || []; - - // If it's 1. a initial redirect with user provided url or 2. a redirect in an existing chain, add it to the context + // If it's 1. an initial redirect with user provided url or 2. a redirect in an existing chain, add it to the context if (found || redirectOrigin) { - outgoingRedirects.push({ - source, - destination, - }); + addRedirectToChain(source, destination, context); + } +} - updateContext(context, "outgoingRequestRedirects", outgoingRedirects); +function addRedirectToChain(source: URL, destination: URL, context: Context) { + const outgoingRedirects = context.outgoingRequestRedirects || []; + const alreadyAdded = outgoingRedirects.find( + (r) => + r.source.toString() === source.toString() && + r.destination.toString() === destination.toString() + ); + + if (alreadyAdded) { + return; } + + outgoingRedirects.push({ + source, + destination, + }); + + updateContext(context, "outgoingRequestRedirects", outgoingRedirects); } diff --git a/library/vulnerabilities/ssrf/getRedirectOrigin.test.ts b/library/vulnerabilities/ssrf/getRedirectOrigin.test.ts index e5e47b682..e8ed4afb8 100644 --- a/library/vulnerabilities/ssrf/getRedirectOrigin.test.ts +++ b/library/vulnerabilities/ssrf/getRedirectOrigin.test.ts @@ -98,3 +98,324 @@ t.test( ); } ); + +t.test("it does not result in an infinite loop", async (t) => { + t.equal( + getRedirectOrigin( + [ + { + source: new URL("https://example.com"), + destination: new URL("https://example.com/2"), + }, + { + source: new URL("https://example.com/2"), + destination: new URL("https://example.com"), + }, + ], + new URL("https://example.com") + ), + undefined + ); +}); + +t.test( + "it avoids infinite loops with unrelated cyclic redirects", + async (t) => { + t.equal( + getRedirectOrigin( + [ + // Unrelated cyclic redirects + { + source: new URL("https://cycle.com/a"), + destination: new URL("https://cycle.com/b"), + }, + { + source: new URL("https://cycle.com/b"), + destination: new URL("https://cycle.com/c"), + }, + { + source: new URL("https://cycle.com/c"), + destination: new URL("https://cycle.com/a"), + }, + // Relevant redirects + { + source: new URL("https://start.com"), + destination: new URL("https://middle.com"), + }, + { + source: new URL("https://middle.com"), + destination: new URL("https://end.com"), + }, + ], + new URL("https://end.com") + )?.href, + new URL("https://start.com").href + ); + } +); + +t.test("it handles multiple requests with overlapping redirects", async (t) => { + t.equal( + getRedirectOrigin( + [ + // Overlapping redirects + { + source: new URL("https://site1.com"), + destination: new URL("https://site2.com"), + }, + { + source: new URL("https://site2.com"), + destination: new URL("https://site3.com"), + }, + { + source: new URL("https://site3.com"), + destination: new URL("https://site1.com"), // Cycle + }, + // Relevant redirects + { + source: new URL("https://origin.com"), + destination: new URL("https://destination.com"), + }, + ], + new URL("https://destination.com") + )?.href, + new URL("https://origin.com").href + ); +}); + +t.test( + "it avoids infinite loops when cycles are part of the redirect chain", + async (t) => { + t.equal( + getRedirectOrigin( + [ + { + source: new URL("https://start.com"), + destination: new URL("https://loop.com/a"), + }, + { + source: new URL("https://loop.com/a"), + destination: new URL("https://loop.com/b"), + }, + { + source: new URL("https://loop.com/b"), + destination: new URL("https://loop.com/c"), + }, + { + source: new URL("https://loop.com/c"), + destination: new URL("https://loop.com/a"), // Cycle here + }, + ], + new URL("https://loop.com/b") + )?.href, + new URL("https://start.com").href + ); + } +); + +t.test("it handles redirects with query parameters", async (t) => { + t.equal( + getRedirectOrigin( + [ + { + source: new URL("https://example.com"), + destination: new URL("https://example.com?param=value"), + }, + ], + new URL("https://example.com?param=value") + )?.href, + new URL("https://example.com").href + ); +}); + +t.test("it handles redirects with fragment identifiers", async (t) => { + t.equal( + getRedirectOrigin( + [ + { + source: new URL("https://example.com"), + destination: new URL("https://example.com#section"), + }, + ], + new URL("https://example.com#section") + )?.href, + new URL("https://example.com").href + ); +}); + +t.test("it handles redirects with different protocols", async (t) => { + t.equal( + getRedirectOrigin( + [ + { + source: new URL("http://example.com"), + destination: new URL("https://example.com"), + }, + ], + new URL("https://example.com") + )?.href, + new URL("http://example.com").href + ); +}); + +t.test("it handles redirects with different ports", async (t) => { + t.equal( + getRedirectOrigin( + [ + { + source: new URL("https://example.com"), + destination: new URL("https://example.com:8080"), + }, + ], + new URL("https://example.com:8080") + )?.href, + new URL("https://example.com").href + ); +}); + +t.test("it handles redirects with paths", async (t) => { + t.equal( + getRedirectOrigin( + [ + { + source: new URL("https://example.com"), + destination: new URL("https://example.com/home"), + }, + { + source: new URL("https://example.com/home"), + destination: new URL("https://example.com/home/welcome"), + }, + ], + new URL("https://example.com/home/welcome") + )?.href, + new URL("https://example.com").href + ); +}); + +t.test("it handles multiple redirects to the same destination", async (t) => { + t.equal( + getRedirectOrigin( + [ + { + source: new URL("https://a.com"), + destination: new URL("https://d.com"), + }, + { + source: new URL("https://b.com"), + destination: new URL("https://d.com"), + }, + { + source: new URL("https://c.com"), + destination: new URL("https://d.com"), + }, + ], + new URL("https://d.com") + )?.href, + new URL("https://a.com").href // It will return the first matching source + ); +}); + +t.test("it handles multiple redirect paths to the same URL", async (t) => { + t.equal( + getRedirectOrigin( + [ + { + source: new URL("https://x.com"), + destination: new URL("https://y.com"), + }, + { + source: new URL("https://y.com"), + destination: new URL("https://z.com"), + }, + { + source: new URL("https://a.com"), + destination: new URL("https://b.com"), + }, + { + source: new URL("https://b.com"), + destination: new URL("https://z.com"), + }, + ], + new URL("https://z.com") + )?.href, + new URL("https://x.com").href // It follows the first matching path + ); +}); + +t.test( + "it returns undefined when source and destination are the same URL", + async (t) => { + t.equal( + getRedirectOrigin( + [ + { + source: new URL("https://example.com"), + destination: new URL("https://example.com"), + }, + ], + new URL("https://example.com") + ), + undefined + ); + } +); + +t.test("it handles very long redirect chains", async (t) => { + const redirects = []; + for (let i = 0; i < 100; i++) { + redirects.push({ + source: new URL(`https://example.com/${i}`), + destination: new URL(`https://example.com/${i + 1}`), + }); + } + + t.equal( + getRedirectOrigin(redirects, new URL("https://example.com/100"))?.href, + new URL("https://example.com/0").href + ); +}); + +t.test( + "it handles redirects with cycles longer than one redirect", + async (t) => { + t.equal( + getRedirectOrigin( + [ + { + source: new URL("https://a.com"), + destination: new URL("https://b.com"), + }, + { + source: new URL("https://b.com"), + destination: new URL("https://c.com"), + }, + { + source: new URL("https://c.com"), + destination: new URL("https://a.com"), + }, + ], + new URL("https://a.com") + ), + undefined + ); + } +); + +t.test("it handles redirects with different query parameters", async (t) => { + t.equal( + getRedirectOrigin( + [ + { + source: new URL("https://example.com"), + destination: new URL("https://example.com?param=1"), + }, + { + source: new URL("https://example.com?param=1"), + destination: new URL("https://example.com?param=2"), + }, + ], + new URL("https://example.com?param=2") + )?.href, + new URL("https://example.com").href + ); +}); diff --git a/library/vulnerabilities/ssrf/getRedirectOrigin.ts b/library/vulnerabilities/ssrf/getRedirectOrigin.ts index ecd9219b5..32cd18555 100644 --- a/library/vulnerabilities/ssrf/getRedirectOrigin.ts +++ b/library/vulnerabilities/ssrf/getRedirectOrigin.ts @@ -1,6 +1,7 @@ import { Context } from "../../agent/Context"; + /** - * This function checks if the given URL is part of a redirect chain that is passed in the redirects parameter. + * This function checks if the given URL is part of a redirect chain that is passed in the `redirects` parameter. * It returns the origin of a redirect chain if the URL is the result of a redirect. * The origin is the first URL in the chain, so the initial URL that was requested and redirected to the given URL * or in case of multiple redirects the URL that was redirected to the given URL. @@ -13,24 +14,37 @@ import { Context } from "../../agent/Context"; export function getRedirectOrigin( redirects: Context["outgoingRequestRedirects"], url: URL -) { +): URL | undefined { if (!Array.isArray(redirects)) { return undefined; } - let currentUrl = url; - - // Follow the redirect chain until we reach the origin or don't find a redirect - while (true) { - const redirect = redirects.find( - // url.href contains the full URL so we can use it for comparison - (r) => r.destination.href === currentUrl.href - ); - if (!redirect) { - break; - } - currentUrl = redirect.source; + const origin = findOrigin(redirects, url); + + // If the origin is the same as the input URL, there's no redirect origin + return origin.href === url.href ? undefined : origin; +} + +function findOrigin( + redirects: NonNullable, + url: URL, + visited: Set = new Set() +): URL { + if (visited.has(url.href)) { + // To avoid infinite loops in case of cyclic redirects + return url; + } + + visited.add(url.href); + + // Find a redirect where the current URL is the destination + const redirect = redirects.find((r) => r.destination.href === url.href); + + if (redirect) { + // Recursively find the origin starting from the source URL + return findOrigin(redirects, redirect.source, visited); } - return currentUrl.href === url.href ? undefined : currentUrl; + // If no redirect leads to this URL, return the URL itself + return url; }