diff --git a/.github/workflows/unit-test-esm.yml b/.github/workflows/unit-test-esm.yml new file mode 100644 index 000000000..d7bd68eaf --- /dev/null +++ b/.github/workflows/unit-test-esm.yml @@ -0,0 +1,29 @@ +name: Unit tests (ESM) +on: + push: {} + workflow_call: {} +jobs: + build: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + node-version: [22.x] + steps: + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + - name: Add local.aikido.io to /etc/hosts + run: | + sudo echo "127.0.0.1 local.aikido.io" | sudo tee -a /etc/hosts + - run: make install + - run: cd library && npm run test:esm + - name: "Upload coverage" + uses: codecov/codecov-action@v4.0.1 + with: + file: ./library/.tap/report/lcov.info + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + slug: AikidoSec/firewall-node diff --git a/Makefile b/Makefile index 57d501d5a..836647f41 100644 --- a/Makefile +++ b/Makefile @@ -81,6 +81,7 @@ build: cp README.md build/README.md cp LICENSE build/LICENSE cp library/package.json build/package.json + cd build && ln -s ../library/node_modules node_modules .PHONY: watch watch: build diff --git a/benchmarks/api-discovery/package-lock.json b/benchmarks/api-discovery/package-lock.json index 4c0aab161..941f8c4f6 100644 --- a/benchmarks/api-discovery/package-lock.json +++ b/benchmarks/api-discovery/package-lock.json @@ -15,6 +15,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/benchmarks/hono-pg/package-lock.json b/benchmarks/hono-pg/package-lock.json index 170a5c629..aafc1e583 100644 --- a/benchmarks/hono-pg/package-lock.json +++ b/benchmarks/hono-pg/package-lock.json @@ -18,6 +18,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/benchmarks/nosql-injection/package-lock.json b/benchmarks/nosql-injection/package-lock.json index b95c75fc4..76efb7621 100644 --- a/benchmarks/nosql-injection/package-lock.json +++ b/benchmarks/nosql-injection/package-lock.json @@ -17,6 +17,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/benchmarks/shell-injection/package-lock.json b/benchmarks/shell-injection/package-lock.json index 27d738a34..befa1fc23 100644 --- a/benchmarks/shell-injection/package-lock.json +++ b/benchmarks/shell-injection/package-lock.json @@ -15,6 +15,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/benchmarks/sql-injection/package-lock.json b/benchmarks/sql-injection/package-lock.json index 21aa8971e..94f46c418 100644 --- a/benchmarks/sql-injection/package-lock.json +++ b/benchmarks/sql-injection/package-lock.json @@ -15,6 +15,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/end2end/tests/hono-sqlite3-esm.test.js b/end2end/tests/hono-sqlite3-esm.test.js new file mode 100644 index 000000000..8428d1b20 --- /dev/null +++ b/end2end/tests/hono-sqlite3-esm.test.js @@ -0,0 +1,146 @@ +const t = require("tap"); +const { spawn } = require("child_process"); +const { resolve } = require("path"); +const timeout = require("../timeout"); + +const appDir = resolve(__dirname, "../../sample-apps/hono-sqlite3-esm"); + +const pathToApp = resolve(appDir, "app.js"); + +t.test("it blocks in blocking mode", (t) => { + const server = spawn( + `node`, + [ + "--preserve-symlinks", + "--import", + "@aikidosec/firewall/esm", + pathToApp, + "4002", + ], + { + cwd: appDir, + env: { ...process.env, AIKIDO_DEBUG: "true", AIKIDO_BLOCKING: "true" }, + } + ); + + server.on("close", () => { + t.end(); + }); + + server.on("error", (err) => { + t.fail(err.message); + }); + + let stdout = ""; + server.stdout.on("data", (data) => { + console.log(data.toString()); + stdout += data.toString(); + }); + + let stderr = ""; + server.stderr.on("data", (data) => { + console.log(data.toString()); + stderr += data.toString(); + }); + + // Wait for the server to start + timeout(2000) + .then(() => { + return Promise.all([ + fetch("http://127.0.0.1:4002/add", { + method: "POST", + body: JSON.stringify({ name: "Test'), ('Test2');--" }), + headers: { + "Content-Type": "application/json", + }, + signal: AbortSignal.timeout(5000), + }), + fetch("http://127.0.0.1:4002/add", { + method: "POST", + body: JSON.stringify({ name: "Miau" }), + headers: { + "Content-Type": "application/json", + }, + signal: AbortSignal.timeout(5000), + }), + ]); + }) + .then(([sqlInjection, normalAdd]) => { + t.equal(sqlInjection.status, 500); + t.equal(normalAdd.status, 200); + t.match(stdout, /Starting agent/); + t.match(stderr, /Zen has blocked an SQL injection/); + }) + .catch((error) => { + t.fail(error.message); + }) + .finally(() => { + server.kill(); + }); +}); + +t.test("it does not block in dry mode", (t) => { + const server = spawn( + `node`, + [ + "--preserve-symlinks", + "--import", + "@aikidosec/firewall/esm", + pathToApp, + "4003", + ], + { + cwd: appDir, + env: { ...process.env, AIKIDO_DEBUG: "true" }, + } + ); + + server.on("close", () => { + t.end(); + }); + + let stdout = ""; + server.stdout.on("data", (data) => { + stdout += data.toString(); + }); + + let stderr = ""; + server.stderr.on("data", (data) => { + stderr += data.toString(); + }); + + // Wait for the server to start + timeout(2000) + .then(() => + Promise.all([ + fetch("http://127.0.0.1:4003/add", { + method: "POST", + body: JSON.stringify({ name: "Test'), ('Test2');--" }), + headers: { + "Content-Type": "application/json", + }, + signal: AbortSignal.timeout(5000), + }), + fetch("http://127.0.0.1:4003/add", { + method: "POST", + body: JSON.stringify({ name: "Miau" }), + headers: { + "Content-Type": "application/json", + }, + signal: AbortSignal.timeout(5000), + }), + ]) + ) + .then(([sqlInjection, normalAdd]) => { + t.equal(sqlInjection.status, 200); + t.equal(normalAdd.status, 200); + t.match(stdout, /Starting agent/); + t.notMatch(stderr, /Zen has blocked an SQL injection/); + }) + .catch((error) => { + t.fail(error.message); + }) + .finally(() => { + server.kill(); + }); +}); diff --git a/library/agent/Agent.test.ts b/library/agent/Agent.test.ts index 8a3557c31..04f719f1f 100644 --- a/library/agent/Agent.test.ts +++ b/library/agent/Agent.test.ts @@ -1,6 +1,6 @@ import * as FakeTimers from "@sinonjs/fake-timers"; import { hostname, platform, release } from "os"; -import * as t from "tap"; +import t from "tap"; import { getSemverNodeVersion } from "../helpers/getNodeVersion"; import { ip } from "../helpers/ipAddress"; import { MongoDB } from "../sinks/MongoDB"; diff --git a/library/agent/Agent.ts b/library/agent/Agent.ts index d7e88b8fa..3f0c7f137 100644 --- a/library/agent/Agent.ts +++ b/library/agent/Agent.ts @@ -53,7 +53,8 @@ export class Agent { private readonly logger: Logger, private readonly api: ReportingAPI, private readonly token: Token | undefined, - private readonly serverless: string | undefined + private readonly serverless: string | undefined, + private readonly isESM: boolean | undefined = false ) { if (typeof this.serverless === "string" && this.serverless.length === 0) { throw new Error("Serverless cannot be an empty string"); @@ -415,7 +416,7 @@ export class Agent { setInstance(this); } - wrapInstalledPackages(wrappers); + wrapInstalledPackages(wrappers, this.isESM || false); // Send startup event and wait for config // Then start heartbeats and polling for config changes diff --git a/library/agent/Context.test.ts b/library/agent/Context.test.ts index 546bec68b..6e2535be6 100644 --- a/library/agent/Context.test.ts +++ b/library/agent/Context.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { extractStringsFromUserInputCached } from "../helpers/extractStringsFromUserInputCached"; import { type Context, diff --git a/library/agent/Hostnames.test.ts b/library/agent/Hostnames.test.ts index 462e72322..26bcc5787 100644 --- a/library/agent/Hostnames.test.ts +++ b/library/agent/Hostnames.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Hostnames } from "./Hostnames"; t.test("it works", async () => { diff --git a/library/agent/InspectionStatistics.test.ts b/library/agent/InspectionStatistics.test.ts index fc218b3a0..1c9ef964c 100644 --- a/library/agent/InspectionStatistics.test.ts +++ b/library/agent/InspectionStatistics.test.ts @@ -1,5 +1,5 @@ import * as FakeTimers from "@sinonjs/fake-timers"; -import * as t from "tap"; +import t from "tap"; import { InspectionStatistics } from "./InspectionStatistics"; t.test("it resets stats", async () => { diff --git a/library/agent/Routes.test.ts b/library/agent/Routes.test.ts index 19816cb35..6e41ca7fb 100644 --- a/library/agent/Routes.test.ts +++ b/library/agent/Routes.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Routes } from "./Routes"; import { Context } from "./Context"; diff --git a/library/agent/ServiceConfig.test.ts b/library/agent/ServiceConfig.test.ts index 908b74a2d..5c38d9063 100644 --- a/library/agent/ServiceConfig.test.ts +++ b/library/agent/ServiceConfig.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { ServiceConfig } from "./ServiceConfig"; t.test("it returns false if empty rules", async () => { diff --git a/library/agent/Users.test.ts b/library/agent/Users.test.ts index 2778a498b..4cd416e4f 100644 --- a/library/agent/Users.test.ts +++ b/library/agent/Users.test.ts @@ -1,5 +1,5 @@ import * as FakeTimers from "@sinonjs/fake-timers"; -import * as t from "tap"; +import t from "tap"; import { Users } from "./Users"; t.test("it works", async () => { diff --git a/library/agent/api-discovery/getApiAuthType.test.ts b/library/agent/api-discovery/getApiAuthType.test.ts index 06a9d1bde..af0165251 100644 --- a/library/agent/api-discovery/getApiAuthType.test.ts +++ b/library/agent/api-discovery/getApiAuthType.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { getApiAuthType as get } from "./getApiAuthType"; import type { Context } from "../Context"; diff --git a/library/agent/api-discovery/getBodyDataType.test.ts b/library/agent/api-discovery/getBodyDataType.test.ts index c83b89a09..d421f39ee 100644 --- a/library/agent/api-discovery/getBodyDataType.test.ts +++ b/library/agent/api-discovery/getBodyDataType.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { getBodyDataType } from "./getBodyDataType"; t.test("it works", async (t) => { diff --git a/library/agent/api-discovery/getDataSchema.test.ts b/library/agent/api-discovery/getDataSchema.test.ts index 9cecf86d3..4c6c7826a 100644 --- a/library/agent/api-discovery/getDataSchema.test.ts +++ b/library/agent/api-discovery/getDataSchema.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { getDataSchema } from "./getDataSchema"; t.test("it works", async (t) => { diff --git a/library/agent/api-discovery/mergeApiAuthTypes.test.ts b/library/agent/api-discovery/mergeApiAuthTypes.test.ts index bb61c60d5..f731c1927 100644 --- a/library/agent/api-discovery/mergeApiAuthTypes.test.ts +++ b/library/agent/api-discovery/mergeApiAuthTypes.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { mergeApiAuthTypes as merge } from "./mergeApiAuthTypes"; t.test("it works", async (t) => { diff --git a/library/agent/api-discovery/mergeDataSchemas.test.ts b/library/agent/api-discovery/mergeDataSchemas.test.ts index acae3da21..663a74450 100644 --- a/library/agent/api-discovery/mergeDataSchemas.test.ts +++ b/library/agent/api-discovery/mergeDataSchemas.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { mergeDataSchemas } from "./mergeDataSchemas"; import { getDataSchema } from "./getDataSchema"; diff --git a/library/agent/api/ReportingAPINodeHTTP.test.ts b/library/agent/api/ReportingAPINodeHTTP.test.ts index ec6d05018..da9bef33b 100644 --- a/library/agent/api/ReportingAPINodeHTTP.test.ts +++ b/library/agent/api/ReportingAPINodeHTTP.test.ts @@ -1,6 +1,6 @@ import * as express from "express"; import * as asyncHandler from "express-async-handler"; -import * as t from "tap"; +import t from "tap"; import { ReportingAPINodeHTTP } from "./ReportingAPINodeHTTP"; import { Event } from "./Event"; import { Token } from "./Token"; diff --git a/library/agent/api/ReportingAPIRateLimitedClientSide.test.ts b/library/agent/api/ReportingAPIRateLimitedClientSide.test.ts index fa82d82cd..4ca131826 100644 --- a/library/agent/api/ReportingAPIRateLimitedClientSide.test.ts +++ b/library/agent/api/ReportingAPIRateLimitedClientSide.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { ReportingAPIForTesting } from "./ReportingAPIForTesting"; import { ReportingAPIRateLimitedClientSide } from "./ReportingAPIRateLimitedClientSide"; import { Token } from "./Token"; diff --git a/library/agent/api/ReportingAPIRateLimitedServerSide.test.ts b/library/agent/api/ReportingAPIRateLimitedServerSide.test.ts index 5ce783551..5b46822c6 100644 --- a/library/agent/api/ReportingAPIRateLimitedServerSide.test.ts +++ b/library/agent/api/ReportingAPIRateLimitedServerSide.test.ts @@ -1,5 +1,5 @@ import * as FakeTimers from "@sinonjs/fake-timers"; -import * as t from "tap"; +import t from "tap"; import { ReportingAPIForTesting } from "./ReportingAPIForTesting"; import { ReportingAPIRateLimitedServerSide } from "./ReportingAPIRateLimitedServerSide"; import { Event } from "./Event"; diff --git a/library/agent/api/ReportingAPIThatValidatesToken.test.ts b/library/agent/api/ReportingAPIThatValidatesToken.test.ts index a8f399ac2..0cf601d73 100644 --- a/library/agent/api/ReportingAPIThatValidatesToken.test.ts +++ b/library/agent/api/ReportingAPIThatValidatesToken.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { ReportingAPIForTesting } from "./ReportingAPIForTesting"; import { ReportingAPIThatValidatesToken } from "./ReportingAPIThatValidatesToken"; import { Event } from "./Event"; diff --git a/library/agent/api/Token.test.ts b/library/agent/api/Token.test.ts index 052f360b9..86f3988a8 100644 --- a/library/agent/api/Token.test.ts +++ b/library/agent/api/Token.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Token } from "./Token"; t.test("it throws error if token is empty", async (t) => { diff --git a/library/agent/applyHooks.test.ts b/library/agent/applyHooks.test.ts index 61538d1aa..3183830f7 100644 --- a/library/agent/applyHooks.test.ts +++ b/library/agent/applyHooks.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "./Agent"; import { ReportingAPIForTesting } from "./api/ReportingAPIForTesting"; import { Token } from "./api/Token"; diff --git a/library/agent/applyHooks.ts b/library/agent/applyHooks.ts index 754a0e9ed..7a8787d5d 100644 --- a/library/agent/applyHooks.ts +++ b/library/agent/applyHooks.ts @@ -5,6 +5,7 @@ import { wrapRequire, } from "./hooks/wrapRequire"; import { wrapExport } from "./hooks/wrapExport"; +import { wrapImport } from "./hooks/wrapImport"; /** * Hooks allows you to register packages and then wrap specific methods on @@ -13,10 +14,16 @@ import { wrapExport } from "./hooks/wrapExport"; * This method wraps the require function and sets up the hooks. * Globals are wrapped directly. */ -export function applyHooks(hooks: Hooks) { - setPackagesToPatch(hooks.getPackages()); - setBuiltinModulesToPatch(hooks.getBuiltInModules()); - wrapRequire(); +export function applyHooks(hooks: Hooks, isESM: boolean) { + // If not esm, wrap require + if (!isESM) { + // Todo check if we need to wrap require too in ESM mode under certain conditions + setPackagesToPatch(hooks.getPackages()); + setBuiltinModulesToPatch(hooks.getBuiltInModules()); + wrapRequire(); + } else { + wrapImport(hooks.getPackages(), hooks.getBuiltInModules()); + } hooks.getGlobals().forEach((g) => { const name = g.getName(); diff --git a/library/agent/context/user.test.ts b/library/agent/context/user.test.ts index af0d49bc8..eb7fc0c83 100644 --- a/library/agent/context/user.test.ts +++ b/library/agent/context/user.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../Agent"; import { setInstance } from "../AgentSingleton"; import { ReportingAPIForTesting } from "../api/ReportingAPIForTesting"; diff --git a/library/agent/hooks/Hooks.test.ts b/library/agent/hooks/Hooks.test.ts index 3980ea26c..465094b6c 100644 --- a/library/agent/hooks/Hooks.test.ts +++ b/library/agent/hooks/Hooks.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Hooks } from "./Hooks"; t.test("package throws error if name is empty", async (t) => { diff --git a/library/agent/hooks/WrapPackageInfo.ts b/library/agent/hooks/WrapPackageInfo.ts index 55c77079b..cb744b20b 100644 --- a/library/agent/hooks/WrapPackageInfo.ts +++ b/library/agent/hooks/WrapPackageInfo.ts @@ -14,6 +14,10 @@ export type WrapPackageInfo = { /** * Only set if the module is not a builtin module. */ + /** + * True if the module is imported via import statement or dynamic import from a esm file. + */ + isESMImport?: boolean; path?: { base: string; /** diff --git a/library/agent/hooks/executeInterceptors.ts b/library/agent/hooks/executeInterceptors.ts new file mode 100644 index 000000000..b32d9ad6a --- /dev/null +++ b/library/agent/hooks/executeInterceptors.ts @@ -0,0 +1,47 @@ +import { getInstance } from "../AgentSingleton"; +import type { RequireInterceptor } from "./RequireInterceptor"; +import type { WrapPackageInfo } from "./WrapPackageInfo"; + +/** + * Executes the provided require interceptor functions and sets the cache. + */ +export function executeInterceptors( + interceptors: RequireInterceptor[], + exports: unknown, + cache: Map | undefined, + cacheKey: string | undefined, + wrapPackageInfo: WrapPackageInfo +) { + // Cache because we need to prevent this called again if module is imported inside interceptors + if (cache && cacheKey) { + cache.set(cacheKey, exports); + } + + // Return early if no interceptors + if (!interceptors.length) { + return exports; + } + + // Foreach interceptor function + for (const interceptor of interceptors) { + // If one interceptor fails, we don't want to stop the other interceptors + try { + const returnVal = interceptor(exports, wrapPackageInfo); + // If the interceptor returns a value, we want to use this value as the new exports + if (typeof returnVal !== "undefined") { + exports = returnVal; + } + } catch (error) { + if (error instanceof Error) { + getInstance()?.onFailedToWrapModule(wrapPackageInfo.name, error); + } + } + } + + // Finally cache the result + if (cache && cacheKey) { + cache.set(cacheKey, exports); + } + + return exports; +} diff --git a/library/agent/hooks/getModuleInfoFromPath.test.ts b/library/agent/hooks/getModuleInfoFromPath.test.ts index 28d31cc5f..41b39f1c3 100644 --- a/library/agent/hooks/getModuleInfoFromPath.test.ts +++ b/library/agent/hooks/getModuleInfoFromPath.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { getModuleInfoFromPath } from "./getModuleInfoFromPath"; t.test("it works", async (t) => { diff --git a/library/agent/hooks/isBuiltinModule.test.ts b/library/agent/hooks/isBuiltinModule.test.ts index def4d28a5..a220ac8db 100644 --- a/library/agent/hooks/isBuiltinModule.test.ts +++ b/library/agent/hooks/isBuiltinModule.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { isBuiltinModule } from "./isBuiltinModule"; t.test("it works", async (t) => { diff --git a/library/agent/hooks/isBuiltinModule.ts b/library/agent/hooks/isBuiltinModule.ts index 0d60ab655..7a17da4d0 100644 --- a/library/agent/hooks/isBuiltinModule.ts +++ b/library/agent/hooks/isBuiltinModule.ts @@ -6,7 +6,7 @@ const moduleList = mod.builtinModules; /** * Returns true if the module is a builtin module, otherwise false. */ -export function isBuiltinModule(moduleName: string) { +export function isBuiltinModule(moduleName: string): boolean { // Added in Node.js v18.6.0, v16.17.0 if (typeof mod.isBuiltin === "function") { return mod.isBuiltin(moduleName); diff --git a/library/agent/hooks/isMainJsFile.test.ts b/library/agent/hooks/isMainJsFile.test.ts index 6b7535df1..e587cefb5 100644 --- a/library/agent/hooks/isMainJsFile.test.ts +++ b/library/agent/hooks/isMainJsFile.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { isMainJsFile } from "./isMainJsFile"; import type { PackageJson } from "type-fest"; @@ -133,6 +133,22 @@ t.test("package.json exports: is main file", async (t) => { } ) ); + t.ok( + isMainJsFile( + { + name: "aikido-module", + base: "/home/user/proj/node_modules/aikido-module", + path: "index.js", + }, + "abc", + "/home/user/proj/node_modules/aikido-module/index.js", + // @ts-expect-error Merge + { + ...basePackageJson, + ...{ main: "./index" }, + } + ) + ); t.ok( isMainJsFile( { @@ -352,3 +368,176 @@ t.test("package.json exports: is not main file", async (t) => { ) ); }); + +t.test("Works with esm import", async (t) => { + t.ok( + isMainJsFile( + { + name: "aikido-module", + base: "/home/user/proj/node_modules/aikido-module", + path: "index.mjs", + }, + undefined, + "/home/user/proj/node_modules/aikido-module/index.mjs", + // @ts-expect-error Merge + { + ...basePackageJson, + ...{ + main: "index.mjs", + exports: { + ".": { + browser: "./index.cjs", + }, + "./test": "./test/abc.cjs", + }, + }, + }, + true + ) + ); + t.ok( + isMainJsFile( + { + name: "aikido-module", + base: "/home/user/proj/node_modules/aikido-module", + path: "index.mjs", + }, + undefined, + "/home/user/proj/node_modules/aikido-module/index.mjs", + // @ts-expect-error Merge + { + ...basePackageJson, + ...{ + main: "index.js", + exports: { + "./": { + browser: "./index.cjs", + import: "./index.mjs", + }, + "./test": "./test/abc.cjs", + }, + }, + }, + true + ) + ); + t.ok( + isMainJsFile( + { + name: "aikido-module", + base: "/home/user/proj/node_modules/aikido-module", + path: "index.mjs", + }, + undefined, + "/home/user/proj/node_modules/aikido-module/index.mjs", + // @ts-expect-error Merge + { + ...basePackageJson, + ...{ + main: "index.js", + exports: { + "./index.mjs": { + import: "./index.mjs", + }, + "./test": "./test/abc.cjs", + }, + }, + }, + true + ) + ); + t.ok( + isMainJsFile( + { + name: "aikido-module", + base: "/home/user/proj/node_modules/aikido-module", + path: "index.mjs", + }, + undefined, + "/home/user/proj/node_modules/aikido-module/index.mjs", + // @ts-expect-error Merge + { + ...basePackageJson, + main: undefined, + }, + true + ) + ); + t.notOk( + isMainJsFile( + { + name: "aikido-module", + base: "/home/user/proj/node_modules/aikido-module", + path: "index.mjs", + }, + undefined, + "/home/user/proj/node_modules/aikido-module/index.mjs", + // @ts-expect-error Merge + { + ...basePackageJson, + ...{ + main: "index.js", + exports: { + ".": { + browser: "./index.cjs", + import: "./index.mjs", + }, + "./test": "./test/abc.cjs", + }, + }, + }, + false + ) + ); + t.notOk( + isMainJsFile( + { + name: "aikido-module", + base: "/home/user/proj/node_modules/aikido-module", + path: "index.mjs", + }, + undefined, + "/home/user/proj/node_modules/aikido-module/index.mjs", + // @ts-expect-error Merge + { + ...basePackageJson, + ...{ + main: "index.js", + exports: { + ".": { + browser: "./index.cjs", + import: "./index.mjs", + }, + "./test": "./test/abc.cjs", + }, + }, + } + ) + ); + t.notOk( + isMainJsFile( + { + name: "aikido-module", + base: "/home/user/proj/node_modules/aikido-module", + path: "index.mjs", + }, + undefined, + "/home/user/proj/node_modules/aikido-module/index.mjs", + // @ts-expect-error Merge + { + ...basePackageJson, + ...{ + main: "index.js", + exports: { + "./tester": { + browser: "./index.cjs", + import: "./index.mjs", + }, + "./test": "./test/abc.cjs", + }, + }, + }, + true + ) + ); +}); diff --git a/library/agent/hooks/isMainJsFile.ts b/library/agent/hooks/isMainJsFile.ts index 5ef885b14..b436c25f8 100644 --- a/library/agent/hooks/isMainJsFile.ts +++ b/library/agent/hooks/isMainJsFile.ts @@ -9,9 +9,10 @@ import { isPlainObject } from "../../helpers/isPlainObject"; */ export function isMainJsFile( pathInfo: ModulePathInfo, - requireId: string, + requireId: string | undefined, filename: string, - packageJson: PackageJson + packageJson: PackageJson, + esmImport = false ) { // If the name of the package is the same as the requireId (the argument passed to require), then it is the main file if (pathInfo.name === requireId) { @@ -19,16 +20,23 @@ export function isMainJsFile( } // Check package.json main field - if ( - typeof packageJson.main === "string" && - resolve(pathInfo.base, packageJson.main) === filename - ) { - return true; + if (typeof packageJson.main === "string") { + if (resolve(pathInfo.base, packageJson.main) === filename) { + return true; + } + + if (!packageJson.main.endsWith(".js")) { + if (resolve(pathInfo.base, `${packageJson.main}.js`) === filename) { + return true; + } + } } - // Defaults to index.js if main field is not set + // Defaults to index if main field is not set if (packageJson.main === undefined) { - if (resolve(pathInfo.base, "index.js") === filename) { + if ( + resolve(pathInfo.base, `index.${esmImport ? "mjs" : "js"}`) === filename + ) { return true; } } @@ -37,29 +45,31 @@ export function isMainJsFile( return doesMainExportMatchFilename( packageJson.exports, pathInfo.base, - filename + filename, + esmImport ); } -const allowedExportConditions = [ - "default", - "node", - "node-addons", - "require", -] as const; - /** * This function checks if the main package exported js file is the same as the passed file. */ function doesMainExportMatchFilename( exportsField: PackageJson["exports"], base: string, - filename: string + filename: string, + esmImport: boolean ) { if (!exportsField) { return false; } + const allowedExportConditions = ["default", "node", "node-addons"]; + if (!esmImport) { + allowedExportConditions.push("require"); + } else { + allowedExportConditions.push("import"); + } + if (typeof exportsField === "string") { if (resolve(base, exportsField) === filename) { return true; @@ -74,7 +84,7 @@ function doesMainExportMatchFilename( } } else if (isPlainObject(exportsField)) { for (const [key, value] of Object.entries(exportsField)) { - if ([".", "./", "./index.js"].includes(key)) { + if ([".", "./", "./index.js", "./index.mjs"].includes(key)) { if (typeof value === "string" && resolve(base, value) === filename) { return true; } diff --git a/library/agent/hooks/wrapDefaultOrNamed.ts b/library/agent/hooks/wrapDefaultOrNamed.ts index 3c6c932b4..dd52030d5 100644 --- a/library/agent/hooks/wrapDefaultOrNamed.ts +++ b/library/agent/hooks/wrapDefaultOrNamed.ts @@ -7,10 +7,11 @@ import { createWrappedFunction, wrap } from "../../helpers/wrap"; export function wrapDefaultOrNamed( module: any, name: string | undefined, - wrapper: (original: Function) => Function + wrapper: (original: Function) => Function, + isESMImport = false ) { if (typeof name === "undefined") { return createWrappedFunction(module, wrapper); } - return wrap(module, name, wrapper); + return wrap(module, name, wrapper, isESMImport); } diff --git a/library/agent/hooks/wrapExport.test.ts b/library/agent/hooks/wrapExport.test.ts index dba2896ab..6a9559642 100644 --- a/library/agent/hooks/wrapExport.test.ts +++ b/library/agent/hooks/wrapExport.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { wrapExport } from "./wrapExport"; import { Agent } from "../Agent"; import { LoggerForTesting } from "../logger/LoggerForTesting"; diff --git a/library/agent/hooks/wrapExport.ts b/library/agent/hooks/wrapExport.ts index f39824363..6489ba23e 100644 --- a/library/agent/hooks/wrapExport.ts +++ b/library/agent/hooks/wrapExport.ts @@ -113,7 +113,8 @@ export function wrapExport( return returnVal; }; - } + }, + pkgInfo.isESMImport ); } catch (error) { agent.onFailedToWrapMethod(pkgInfo.name, methodName); diff --git a/library/agent/hooks/wrapImport.test.mjs b/library/agent/hooks/wrapImport.test.mjs new file mode 100644 index 000000000..ec1d053dd --- /dev/null +++ b/library/agent/hooks/wrapImport.test.mjs @@ -0,0 +1,40 @@ +import t from "tap"; + +import wrapImport from "./wrapImport.js"; +import Package from "./Package.js"; +import BuiltinModule from "./BuiltinModule.js"; + +t.test("it works", async (t) => { + const initialSqlite3 = await import("sqlite3"); + t.same(typeof initialSqlite3.default, "object"); + + const sqlite3Pkg = new Package.Package("sqlite3"); + sqlite3Pkg.withVersion("^5.0.0").onRequire((exports, pkgInfo) => { + t.same(pkgInfo.name, "sqlite3"); + t.same(pkgInfo.type, "external"); + t.ok(pkgInfo.path?.base.endsWith("node_modules/sqlite3")); + t.same(pkgInfo.path?.relative, "lib/sqlite3.js"); + + exports.default = 42; + }); + + const internalFs = new BuiltinModule.BuiltinModule("fs"); + internalFs.onRequire((exports, pkgInfo) => { + t.same(pkgInfo.name, "fs"); + t.same(pkgInfo.type, "builtin"); + t.same(pkgInfo.path, undefined); + + exports.readFile = () => "hello from aikido"; + }); + + wrapImport.wrapImport([sqlite3Pkg], [internalFs]); + + // Should not change anything + wrapImport.wrapImport(); + + const sqlite3 = await import("sqlite3"); + t.same(sqlite3.default, 42); + + const fs = await import("fs"); + t.same(fs.readFile(), "hello from aikido"); +}); diff --git a/library/agent/hooks/wrapImport.ts b/library/agent/hooks/wrapImport.ts new file mode 100644 index 000000000..e86c661e8 --- /dev/null +++ b/library/agent/hooks/wrapImport.ts @@ -0,0 +1,214 @@ +/* eslint-disable max-lines-per-function */ +import { register } from "module"; +import { pathToFileURL } from "url"; +import { Hook } from "import-in-the-middle"; +import { BuiltinModule } from "./BuiltinModule"; +import { Package } from "./Package"; +import { isBuiltinModule } from "./isBuiltinModule"; +import { getInstance } from "../AgentSingleton"; +import { removeNodePrefix } from "../../helpers/removeNodePrefix"; +import { executeInterceptors } from "./executeInterceptors"; +import { getModuleInfoFromPath, ModulePathInfo } from "./getModuleInfoFromPath"; +import { getOrignalRequire } from "./wrapRequire"; +import type { PackageJson } from "type-fest"; +import { satisfiesVersion } from "../../helpers/satisfiesVersion"; +import { RequireInterceptor } from "./RequireInterceptor"; +import { isMainJsFile } from "./isMainJsFile"; +import { join } from "path"; + +let isImportHookRegistered = false; + +let packages: Package[] = []; +let builtinModules: BuiltinModule[] = []; + +/** + * Intercept esm package imports. + * This function makes sure that the import function is only wrapped once. + */ +export function wrapImport( + packagesToPatch: Package[], + builtinModulesToPatch: BuiltinModule[] +) { + if (isImportHookRegistered) { + return; + } + packages = packagesToPatch; + builtinModules = builtinModulesToPatch; + + // Prevent registering the import hook multiple times + isImportHookRegistered = true; + + // Register import-in-the-middle hook + register("import-in-the-middle/hook.mjs", pathToFileURL(__filename)); + + const allPackageNames = [packages, builtinModules] + .flat() + .map((p) => p.getName()); + + new Hook( + allPackageNames, + { + internals: true, + }, + onImport + ); +} + +/** + * This function is called when a package / file of a package is imported for the first time. + */ +function onImport(exports: any, name: string, baseDir: string | void) { + try { + // Check if its a builtin module + // They are easier to patch (no file patching) + if (isBuiltinModule(name)) { + patchBuiltinModule(exports, name); + return; + } + + patchPackage(exports, name, baseDir); + } catch (error) { + if (error instanceof Error) { + getInstance()?.onFailedToWrapModule(name, error); + } + } +} + +function patchBuiltinModule(exports: any, name: string) { + const moduleName = removeNodePrefix(name); + + // Check if we want to patch this builtin module + const matchingBuiltins = builtinModules.filter( + (m) => m.getName() === moduleName + ); + + // Get interceptors from all matching builtin modules + const interceptors = matchingBuiltins + .map((m) => m.getRequireInterceptors()) + .flat(); + + executeInterceptors(interceptors, exports, undefined, undefined, { + name: moduleName, + type: "builtin", + isESMImport: true, + }); +} + +function getRelativeImportedFilePath(packageName: string, importName: string) { + if (!importName.startsWith(packageName)) { + return importName; + } + return importName.substring(packageName.length + 1); +} + +function patchPackage( + exports: any, + importName: string, + baseDir: string | void +) { + // Ignore .json files + if (importName.endsWith(".json")) { + return; + } + + // Required for getting package version + if (!baseDir) { + throw new Error("Can not patch package without baseDir"); + } + + // Base dir and importName include the package name + // The importName also includes the path to the file inside the imported package + // We call getModuleInfoFromPath with the importName to get the package name because packages can have a scope + // Do not use pathInfo.base because its wrong, use baseDir instead! + const pathInfoForName = getModuleInfoFromPath(`node_modules/${importName}`); + if (!pathInfoForName) { + // Can happen if the package is not inside a node_modules folder, like the dev build of our library itself + return; + } + const packageName = pathInfoForName.name; + + const pathInfo: ModulePathInfo = { + name: packageName, + base: baseDir, + path: getRelativeImportedFilePath(packageName, importName), + }; + + // Get all versioned packages for the module name + const versionedPackages = packages + .filter((pkg) => pkg.getName() === packageName) + .map((pkg) => pkg.getVersions()) + .flat(); + + // We don't want to patch this package because we do not have any hooks for it + if (!versionedPackages.length) { + return; + } + + // Get the original require function (if it was wrapped) + const requireFunc = getOrignalRequire() || require; + + // Read the package.json of the required package + const packageJson = requireFunc(`${baseDir}/package.json`) as PackageJson; + + // Get the version of the installed package + const installedPkgVersion = packageJson.version; + if (!installedPkgVersion) { + throw new Error( + `Could not get installed package version for ${packageName} on import` + ); + } + + // Check if the installed package version is supported (get all matching versioned packages) + const matchingVersionedPackages = versionedPackages.filter((pkg) => + satisfiesVersion(pkg.getRange(), installedPkgVersion) + ); + + const agent = getInstance(); + if (agent) { + // Report to the agent that the package was wrapped or not if it's version is not supported + agent.onPackageWrapped(packageName, { + version: installedPkgVersion, + supported: !!matchingVersionedPackages.length, + }); + } + + if (!matchingVersionedPackages.length) { + // We don't want to patch this package version + return; + } + + const fullFilePath = join(pathInfo.base, pathInfo.path); + + // Check if the imported file is the main file of the package or another js file inside the package + const isMainFile = isMainJsFile( + pathInfo, + undefined, + fullFilePath, + packageJson, + true + ); + + let interceptors: RequireInterceptor[] = []; + + if (isMainFile) { + interceptors = matchingVersionedPackages + .map((pkg) => pkg.getRequireInterceptors()) + .flat(); + } else { + // If its not the main file, we check if we want to patch the required file + interceptors = matchingVersionedPackages + .map((pkg) => pkg.getRequireFileInterceptor(pathInfo.path) || []) + .flat(); + } + + executeInterceptors(interceptors, exports, undefined, undefined, { + name: pathInfo.name, + version: installedPkgVersion, + type: "external", + isESMImport: true, + path: { + base: pathInfo.base, + relative: pathInfo.path, + }, + }); +} diff --git a/library/agent/hooks/wrapNewInstance.test.ts b/library/agent/hooks/wrapNewInstance.test.ts index 3d02518d9..c9e41c151 100644 --- a/library/agent/hooks/wrapNewInstance.test.ts +++ b/library/agent/hooks/wrapNewInstance.test.ts @@ -1,5 +1,5 @@ /* eslint-disable max-classes-per-file */ -import * as t from "tap"; +import t from "tap"; import { wrapNewInstance } from "./wrapNewInstance"; import { Agent } from "../Agent"; import { LoggerForTesting } from "../logger/LoggerForTesting"; diff --git a/library/agent/hooks/wrapRequire.test.ts b/library/agent/hooks/wrapRequire.test.ts index 3a38d2fe7..5149a2182 100644 --- a/library/agent/hooks/wrapRequire.test.ts +++ b/library/agent/hooks/wrapRequire.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { wrapRequire, setPackagesToPatch, diff --git a/library/agent/hooks/wrapRequire.ts b/library/agent/hooks/wrapRequire.ts index 56e48b01c..37127fb87 100644 --- a/library/agent/hooks/wrapRequire.ts +++ b/library/agent/hooks/wrapRequire.ts @@ -9,10 +9,10 @@ import { removeNodePrefix } from "../../helpers/removeNodePrefix"; import { RequireInterceptor } from "./RequireInterceptor"; import type { PackageJson } from "type-fest"; import { isMainJsFile } from "./isMainJsFile"; -import { WrapPackageInfo } from "./WrapPackageInfo"; import { getInstance } from "../AgentSingleton"; +import { executeInterceptors } from "./executeInterceptors"; -const originalRequire = mod.prototype.require; +let originalRequire: typeof mod.prototype.require; let isRequireWrapped = false; let packages: Package[] = []; @@ -34,8 +34,11 @@ export function wrapRequire() { `Could not find the _resolveFilename function in node:module using Node.js version ${process.version}` ); } + // Prevent wrapping the require function multiple times isRequireWrapped = true; + // Save the original require function + originalRequire = mod.prototype.require; // @ts-expect-error TS doesn't know that we are not overwriting the subproperties mod.prototype.require = function wrapped() { @@ -232,7 +235,7 @@ function patchPackage(this: mod, id: string, originalExports: unknown) { .map((pkg) => pkg.getRequireInterceptors()) .flat(); } else { - // If its not the main file, we want to check if the want to patch the required file + // If its not the main file, we check if we want to patch the required file interceptors = matchingVersionedPackages .map((pkg) => pkg.getRequireFileInterceptor(pathInfo.path) || []) .flat(); @@ -255,49 +258,9 @@ function patchPackage(this: mod, id: string, originalExports: unknown) { ); } -/** - * Executes the provided require interceptor functions and sets the cache. - */ -function executeInterceptors( - interceptors: RequireInterceptor[], - exports: unknown, - cache: Map, - cacheKey: string, - wrapPackageInfo: WrapPackageInfo -) { - // Cache because we need to prevent this called again if module is imported inside interceptors - cache.set(cacheKey, exports); - - // Return early if no interceptors - if (!interceptors.length) { - return exports; - } - - // Foreach interceptor function - for (const interceptor of interceptors) { - // If one interceptor fails, we don't want to stop the other interceptors - try { - const returnVal = interceptor(exports, wrapPackageInfo); - // If the interceptor returns a value, we want to use this value as the new exports - if (typeof returnVal !== "undefined") { - exports = returnVal; - } - } catch (error) { - if (error instanceof Error) { - getInstance()?.onFailedToWrapModule(wrapPackageInfo.name, error); - } - } - } - - // Finally cache the result - cache.set(cacheKey, exports); - - return exports; -} - /** * Returns the unwrapped require function. */ export function getOrignalRequire() { - return originalRequire; + return originalRequire || mod.prototype?.require; } diff --git a/library/agent/protect.ts b/library/agent/protect.ts index 2b930e99a..efcf4cee2 100644 --- a/library/agent/protect.ts +++ b/library/agent/protect.ts @@ -93,7 +93,13 @@ function getTokenFromEnv(): Token | undefined { : undefined; } -function getAgent({ serverless }: { serverless: string | undefined }) { +function getAgent({ + serverless, + isESM, +}: { + serverless: string | undefined; + isESM?: boolean; +}) { const current = getInstance(); if (current) { @@ -105,7 +111,8 @@ function getAgent({ serverless }: { serverless: string | undefined }) { getLogger(), getAPI(), getTokenFromEnv(), - serverless + serverless, + isESM ); setInstance(agent); @@ -142,9 +149,10 @@ function getWrappers() { ]; } -export function protect() { +export function protect(isESM = false) { const agent = getAgent({ serverless: undefined, + isESM, }); agent.start(getWrappers()); diff --git a/library/agent/realtime/pollForChanges.test.ts b/library/agent/realtime/pollForChanges.test.ts index 54cfe65d8..c63a7b4bd 100644 --- a/library/agent/realtime/pollForChanges.test.ts +++ b/library/agent/realtime/pollForChanges.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import * as fetch from "../../helpers/fetch"; import { wrap } from "../../helpers/wrap"; import { Token } from "../api/Token"; diff --git a/library/agent/wrapInstalledPackages.ts b/library/agent/wrapInstalledPackages.ts index 6b7b364a8..2fdaf8832 100644 --- a/library/agent/wrapInstalledPackages.ts +++ b/library/agent/wrapInstalledPackages.ts @@ -2,11 +2,11 @@ import { applyHooks } from "./applyHooks"; import { Hooks } from "./hooks/Hooks"; import { Wrapper } from "./Wrapper"; -export function wrapInstalledPackages(wrappers: Wrapper[]) { +export function wrapInstalledPackages(wrappers: Wrapper[], isESM: boolean) { const hooks = new Hooks(); wrappers.forEach((wrapper) => { wrapper.wrap(hooks); }); - return applyHooks(hooks); + return applyHooks(hooks, isESM); } diff --git a/library/esm/index.ts b/library/esm/index.ts new file mode 100644 index 000000000..aff69db5e --- /dev/null +++ b/library/esm/index.ts @@ -0,0 +1,27 @@ +import isFirewallSupported from "../helpers/isFirewallSupported"; +import { + getMajorNodeVersion, + getMinorNodeVersion, +} from "../helpers/getNodeVersion"; + +// Was added in v20.6.0 and v18.19.0 +function isESMSupported() { + const nodeMajor = getMajorNodeVersion(); + const nodeMinor = getMinorNodeVersion(); + return ( + nodeMajor >= 22 || + (nodeMajor === 20 && nodeMinor >= 6) || + (nodeMajor === 18 && nodeMinor >= 19) + ); +} + +if (isFirewallSupported()) { + if (isESMSupported()) { + require("../agent/protect").protect(true); + } else { + // eslint-disable-next-line no-console + console.error( + "Error: Aikido Firewall requires Node.js v20.6.0 / v18.19.0 or higher to support ESM." + ); + } +} diff --git a/library/helpers/buildRouteFromURL.test.ts b/library/helpers/buildRouteFromURL.test.ts index d01ebe7b3..fa6f53d8c 100644 --- a/library/helpers/buildRouteFromURL.test.ts +++ b/library/helpers/buildRouteFromURL.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { buildRouteFromURL } from "./buildRouteFromURL"; import * as ObjectID from "bson-objectid"; diff --git a/library/helpers/cleanupStackTrace.test.ts b/library/helpers/cleanupStackTrace.test.ts index 9e68fa365..143547939 100644 --- a/library/helpers/cleanupStackTrace.test.ts +++ b/library/helpers/cleanupStackTrace.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { cleanupStackTrace } from "./cleanupStackTrace"; t.test("it works", async () => { diff --git a/library/helpers/convertRequestBodyToString.test.ts b/library/helpers/convertRequestBodyToString.test.ts index 1bffa307e..feae1b52e 100644 --- a/library/helpers/convertRequestBodyToString.test.ts +++ b/library/helpers/convertRequestBodyToString.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { convertRequestBodyToString } from "./convertRequestBodyToString"; t.test("it converts object body to JSON string", async (t) => { diff --git a/library/helpers/escapeHTML.test.ts b/library/helpers/escapeHTML.test.ts index 3b05974db..829445d88 100644 --- a/library/helpers/escapeHTML.test.ts +++ b/library/helpers/escapeHTML.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { escapeHTML } from "./escapeHTML"; t.test('should escape "&" character', async (t) => { diff --git a/library/helpers/escapeStringRegexp.test.ts b/library/helpers/escapeStringRegexp.test.ts index 7151baec8..c43014460 100644 --- a/library/helpers/escapeStringRegexp.test.ts +++ b/library/helpers/escapeStringRegexp.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { escapeStringRegexp } from "./escapeStringRegexp"; t.test("main", async (t) => { diff --git a/library/helpers/extractStringsFromUserInput.test.ts b/library/helpers/extractStringsFromUserInput.test.ts index baa1df19a..823730341 100644 --- a/library/helpers/extractStringsFromUserInput.test.ts +++ b/library/helpers/extractStringsFromUserInput.test.ts @@ -1,5 +1,5 @@ /* eslint-disable camelcase */ -import * as t from "tap"; +import t from "tap"; import { extractStringsFromUserInput } from "./extractStringsFromUserInput"; t.test("empty object returns empty array", async () => { diff --git a/library/helpers/featureFlags.test.ts b/library/helpers/featureFlags.test.ts index f1ba3fc81..b938a9759 100644 --- a/library/helpers/featureFlags.test.ts +++ b/library/helpers/featureFlags.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { isFeatureEnabled } from "./featureFlags"; t.test("isFeatureEnabled", async (t) => { diff --git a/library/helpers/filterEmptyRequestHeaders.test.ts b/library/helpers/filterEmptyRequestHeaders.test.ts index f42eaff11..9fe864fbc 100644 --- a/library/helpers/filterEmptyRequestHeaders.test.ts +++ b/library/helpers/filterEmptyRequestHeaders.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { filterEmptyRequestHeaders } from "./filterEmptyRequestHeaders"; t.test("it filters empty headers", async (t) => { diff --git a/library/helpers/getAgentVersion.test.ts b/library/helpers/getAgentVersion.test.ts index 25272be6e..9ab6850d0 100644 --- a/library/helpers/getAgentVersion.test.ts +++ b/library/helpers/getAgentVersion.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { getAgentVersion } from "./getAgentVersion"; t.test("it returns the current library version", async () => { diff --git a/library/helpers/getCurrentAndNextSegments.test.ts b/library/helpers/getCurrentAndNextSegments.test.ts index db009181c..5cad4f610 100644 --- a/library/helpers/getCurrentAndNextSegments.test.ts +++ b/library/helpers/getCurrentAndNextSegments.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { getCurrentAndNextSegments } from "./getCurrentAndNextSegments"; t.test( diff --git a/library/helpers/getMaxBodySize.test.ts b/library/helpers/getMaxBodySize.test.ts index f22c60d93..443a326ba 100644 --- a/library/helpers/getMaxBodySize.test.ts +++ b/library/helpers/getMaxBodySize.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { getMaxBodySize } from "./getMaxBodySize"; t.test( diff --git a/library/helpers/getNodeVersion.test.ts b/library/helpers/getNodeVersion.test.ts index c64d6410d..fed327839 100644 --- a/library/helpers/getNodeVersion.test.ts +++ b/library/helpers/getNodeVersion.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { getMajorNodeVersion, getMinorNodeVersion, diff --git a/library/helpers/getPackageVersion.test.ts b/library/helpers/getPackageVersion.test.ts index 51699abdf..0998c7626 100644 --- a/library/helpers/getPackageVersion.test.ts +++ b/library/helpers/getPackageVersion.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { getPackageVersion } from "./getPackageVersion"; t.test("it resolves the version of a package", async (t) => { diff --git a/library/helpers/getPortFromURL.test.ts b/library/helpers/getPortFromURL.test.ts index 5b0f32cda..71b1a7cb6 100644 --- a/library/helpers/getPortFromURL.test.ts +++ b/library/helpers/getPortFromURL.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { getPortFromURL } from "./getPortFromURL"; t.test("it works", async (t) => { diff --git a/library/helpers/ipAddress.test.ts b/library/helpers/ipAddress.test.ts index 234e1e1bb..38c63e5a2 100644 --- a/library/helpers/ipAddress.test.ts +++ b/library/helpers/ipAddress.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { wrap } from "./wrap"; import { ip } from "./ipAddress"; diff --git a/library/helpers/isAikidoCI.test.ts b/library/helpers/isAikidoCI.test.ts index dcab9800e..9ae460aaa 100644 --- a/library/helpers/isAikidoCI.test.ts +++ b/library/helpers/isAikidoCI.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { isAikidoCI } from "./isAikidoCI"; t.test("get aikido ci env", async (t) => { diff --git a/library/helpers/isCJS.ts b/library/helpers/isCJS.ts new file mode 100644 index 000000000..c71ba20f0 --- /dev/null +++ b/library/helpers/isCJS.ts @@ -0,0 +1,9 @@ +import * as mod from "module"; + +/** + * Check if executed in CommonJS environment. + * This will always be true if the library is normally used because it is a CommonJS library. + */ +export function isCJS(): boolean { + return mod.prototype !== undefined && mod.prototype.require !== undefined; +} diff --git a/library/helpers/isPackageInstalled.test.ts b/library/helpers/isPackageInstalled.test.ts index 34584d8a7..c24bcfbec 100644 --- a/library/helpers/isPackageInstalled.test.ts +++ b/library/helpers/isPackageInstalled.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { isPackageInstalled } from "./isPackageInstalled"; t.test("it returns true if the package is installed", async (t) => { diff --git a/library/helpers/isPlainObject.test.ts b/library/helpers/isPlainObject.test.ts index 4382d1cee..078a9ce33 100644 --- a/library/helpers/isPlainObject.test.ts +++ b/library/helpers/isPlainObject.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { isPlainObject } from "./isPlainObject"; t.test( diff --git a/library/helpers/limitLengthMetadata.test.ts b/library/helpers/limitLengthMetadata.test.ts index 04d4138c6..96dbb199b 100644 --- a/library/helpers/limitLengthMetadata.test.ts +++ b/library/helpers/limitLengthMetadata.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { limitLengthMetadata } from "./limitLengthMetadata"; t.test("it limits metadata length", async () => { diff --git a/library/helpers/looksLikeASecret.test.ts b/library/helpers/looksLikeASecret.test.ts index 0c6d55607..2695cee77 100644 --- a/library/helpers/looksLikeASecret.test.ts +++ b/library/helpers/looksLikeASecret.test.ts @@ -1,5 +1,5 @@ import { randomInt } from "crypto"; -import * as t from "tap"; +import t from "tap"; import { looksLikeASecret } from "./looksLikeASecret"; const lower = "abcdefghijklmnopqrstuvwxyz"; diff --git a/library/helpers/matchEndpoints.test.ts b/library/helpers/matchEndpoints.test.ts index 8fd45c39b..daa14706f 100644 --- a/library/helpers/matchEndpoints.test.ts +++ b/library/helpers/matchEndpoints.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Context } from "../agent/Context"; import { buildRouteFromURL } from "./buildRouteFromURL"; import { matchEndpoints } from "./matchEndpoints"; diff --git a/library/helpers/package-json.test.ts b/library/helpers/package-json.test.ts index 2bd3057fc..46ad464db 100644 --- a/library/helpers/package-json.test.ts +++ b/library/helpers/package-json.test.ts @@ -1,7 +1,9 @@ -import * as t from "tap"; +import t from "tap"; const PackageJson = require("../package.json"); -t.test("Check that no dependencies are present", async (t) => { - t.equal(PackageJson.dependencies, undefined); +t.test("Check that only correct dependencies are used", async (t) => { + t.same(PackageJson.dependencies, { + "import-in-the-middle": "^1.11.1", + }); }); diff --git a/library/helpers/parseCookies.test.ts b/library/helpers/parseCookies.test.ts index 636a7ec21..d67fd5078 100644 --- a/library/helpers/parseCookies.test.ts +++ b/library/helpers/parseCookies.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { parse } from "./parseCookies"; t.test("should parse cookie string to object", async () => { diff --git a/library/helpers/percentiles.test.ts b/library/helpers/percentiles.test.ts index c2599f5d5..aafcb7d63 100644 --- a/library/helpers/percentiles.test.ts +++ b/library/helpers/percentiles.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { percentiles } from "./percentiles"; function generateArray( diff --git a/library/helpers/satisfiesVersion.test.ts b/library/helpers/satisfiesVersion.test.ts index 76da7cc7e..935a59668 100644 --- a/library/helpers/satisfiesVersion.test.ts +++ b/library/helpers/satisfiesVersion.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { satisfiesVersion } from "./satisfiesVersion"; t.test("it returns false if empty strings", async () => { diff --git a/library/helpers/tryDecodeAsJWT.test.ts b/library/helpers/tryDecodeAsJWT.test.ts index d32e8d188..f517f2457 100644 --- a/library/helpers/tryDecodeAsJWT.test.ts +++ b/library/helpers/tryDecodeAsJWT.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { tryDecodeAsJWT } from "./tryDecodeAsJWT"; t.test("it returns undefined for empty string", async () => { diff --git a/library/helpers/tryParseURL.test.ts b/library/helpers/tryParseURL.test.ts index b2860043a..986e935e8 100644 --- a/library/helpers/tryParseURL.test.ts +++ b/library/helpers/tryParseURL.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { tryParseURL } from "./tryParseURL"; t.test("it returns undefined if invalid URL", async () => { diff --git a/library/helpers/tryParseURLParams.test.ts b/library/helpers/tryParseURLParams.test.ts index 68fd9bc7b..254a3e0cf 100644 --- a/library/helpers/tryParseURLParams.test.ts +++ b/library/helpers/tryParseURLParams.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { tryParseURLParams } from "./tryParseURLParams"; t.test("it returns undefined if invalid URL", async () => { diff --git a/library/helpers/tryParseURLPath.test.ts b/library/helpers/tryParseURLPath.test.ts index 599715887..ffc52d7f2 100644 --- a/library/helpers/tryParseURLPath.test.ts +++ b/library/helpers/tryParseURLPath.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { tryParseURLPath } from "./tryParseURLPath"; t.test("it returns undefined if nothing found", async () => { diff --git a/library/helpers/wrap.test.ts b/library/helpers/wrap.test.ts index abe18c6fb..fb3df8102 100644 --- a/library/helpers/wrap.test.ts +++ b/library/helpers/wrap.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { isWrapped, wrap } from "./wrap"; class MyClass { diff --git a/library/helpers/wrap.ts b/library/helpers/wrap.ts index 3c7f3b52e..b5b015968 100644 --- a/library/helpers/wrap.ts +++ b/library/helpers/wrap.ts @@ -5,7 +5,8 @@ type WrappedFunction = T & { export function wrap( module: any, name: string, - wrapper: (original: Function) => Function + wrapper: (original: Function) => Function, + isESMImport = false ) { if (!module[name]) { throw new Error(`no original function ${name} to wrap`); @@ -20,7 +21,11 @@ export function wrap( const original = module[name]; const wrapped = createWrappedFunction(original, wrapper); - defineProperty(module, name, wrapped); + if (!isESMImport) { + defineProperty(module, name, wrapped); + } else { + module[name] = wrapped; + } return wrapped; } @@ -51,8 +56,13 @@ export function createWrappedFunction( // Sets a property on an object, preserving its enumerability. // This function assumes that the property is already writable. function defineProperty(obj: unknown, name: string, value: unknown) { - // @ts-expect-error We don't know the type of obj - const enumerable = !!obj[name] && obj.propertyIsEnumerable(name); + const enumerable = + // @ts-expect-error We don't know the type of obj + !!obj[name] && + // @ts-expect-error We don't know the type of obj + typeof obj.propertyIsEnumerable === "function" && + // @ts-expect-error We don't know the type of obj + obj.propertyIsEnumerable(name); Object.defineProperty(obj, name, { configurable: true, enumerable: enumerable, diff --git a/library/package-lock.json b/library/package-lock.json index 4dcca9374..f28d2eb8a 100644 --- a/library/package-lock.json +++ b/library/package-lock.json @@ -8,6 +8,9 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, "devDependencies": { "@google-cloud/functions-framework": "^3.3.0", "@google-cloud/pubsub": "^4.3.3", @@ -3933,7 +3936,6 @@ "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -3942,6 +3944,15 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", @@ -4800,6 +4811,12 @@ "node": ">=8" } }, + "node_modules/cjs-module-lexer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", + "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", + "license": "MIT" + }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -7537,6 +7554,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-in-the-middle": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.11.2.tgz", + "integrity": "sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA==", + "dependencies": { + "acorn": "^8.8.2", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -8893,6 +8921,12 @@ "dev": true, "license": "MIT" }, + "node_modules/module-details-from-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.3.tgz", + "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==", + "license": "MIT" + }, "node_modules/mongodb": { "version": "6.8.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.8.0.tgz", diff --git a/library/package.json b/library/package.json index 5fcf09fb5..15e3cc4cf 100644 --- a/library/package.json +++ b/library/package.json @@ -31,6 +31,14 @@ "engines": { "node": ">=16" }, + "exports": { + ".": "./index.js", + "./esm": "./esm/index.js", + "./context": "./context/index.js", + "./lambda": "./lambda/index.js", + "./nopp": "./nopp/index.js", + "./cloud-function": "./cloud-function/index.js" + }, "devDependencies": { "@google-cloud/functions-framework": "^3.3.0", "@google-cloud/pubsub": "^4.3.3", @@ -91,6 +99,10 @@ "build:watch": "tsc --watch", "lint": "npm run lint-eslint && npm run lint-tsc", "lint-eslint": "eslint '**/*.ts'", - "lint-tsc": "tsc --noEmit" + "lint-tsc": "tsc --noEmit", + "test:esm": "npx tap --tsconfig ./tsconfig.esm-test.json --allow-incomplete-coverage --coverage-report=lcov '!(*node_modules)/**/*.test.mjs'" + }, + "dependencies": { + "import-in-the-middle": "^1.11.1" } } diff --git a/library/ratelimiting/LRUMap.test.ts b/library/ratelimiting/LRUMap.test.ts index 09cd1d242..e31628c11 100644 --- a/library/ratelimiting/LRUMap.test.ts +++ b/library/ratelimiting/LRUMap.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { LRUMap } from "./LRUMap"; t.test("it creates LRUMap", async (t) => { diff --git a/library/ratelimiting/RateLimiter.test.ts b/library/ratelimiting/RateLimiter.test.ts index c4cb08ad3..200990442 100644 --- a/library/ratelimiting/RateLimiter.test.ts +++ b/library/ratelimiting/RateLimiter.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import * as FakeTimers from "@sinonjs/fake-timers"; import { RateLimiter } from "./RateLimiter"; diff --git a/library/ratelimiting/getRateLimitedEndpoint.test.ts b/library/ratelimiting/getRateLimitedEndpoint.test.ts index c3233353a..1faa9c300 100644 --- a/library/ratelimiting/getRateLimitedEndpoint.test.ts +++ b/library/ratelimiting/getRateLimitedEndpoint.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import type { Context } from "../agent/Context"; import { ServiceConfig } from "../agent/ServiceConfig"; import { getRateLimitedEndpoint } from "./getRateLimitedEndpoint"; diff --git a/library/ratelimiting/shouldRateLimitRequest.test.ts b/library/ratelimiting/shouldRateLimitRequest.test.ts index 01c3e9a05..aede58d6a 100644 --- a/library/ratelimiting/shouldRateLimitRequest.test.ts +++ b/library/ratelimiting/shouldRateLimitRequest.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Token } from "../agent/api/Token"; diff --git a/library/sinks/AwsSDKVersion2.test.ts b/library/sinks/AwsSDKVersion2.test.ts index 2a9f97cff..be207c5b1 100644 --- a/library/sinks/AwsSDKVersion2.test.ts +++ b/library/sinks/AwsSDKVersion2.test.ts @@ -1,9 +1,10 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Context, runWithContext } from "../agent/Context"; import { LoggerForTesting } from "../agent/logger/LoggerForTesting"; import { AwsSDKVersion2 } from "./AwsSDKVersion2"; +import { isCJS } from "../helpers/isCJS"; // Suppress upgrade to SDK v3 notice require("aws-sdk/lib/maintenance_mode_message").suppress = true; @@ -32,12 +33,13 @@ t.test("it works", async (t) => { logger, new ReportingAPIForTesting(), undefined, - undefined + undefined, + !isCJS() ); agent.start([new AwsSDKVersion2()]); - const AWS = require("aws-sdk"); + const AWS = isCJS() ? require("aws-sdk") : (await import("aws-sdk")).default; const s3 = new AWS.S3({ region: "us-east-1", diff --git a/library/sinks/AwsSDKVersion2.ts b/library/sinks/AwsSDKVersion2.ts index c8233d2ef..cb5ff926d 100644 --- a/library/sinks/AwsSDKVersion2.ts +++ b/library/sinks/AwsSDKVersion2.ts @@ -73,7 +73,9 @@ export class AwsSDKVersion2 implements Wrapper { .addPackage("aws-sdk") .withVersion("^2.0.0") .onRequire((exports, pkgInfo) => { - wrapNewInstance(exports, "S3", pkgInfo, (instance) => { + const base = pkgInfo.isESMImport ? exports.default : exports; + + wrapNewInstance(base, "S3", pkgInfo, (instance) => { for (const operation of operationsWithKey) { wrapExport(instance, operation, pkgInfo, { inspectArgs: (args) => this.inspectS3Operation(args, operation), diff --git a/library/sinks/BetterSQLite3.test.ts b/library/sinks/BetterSQLite3.test.ts index 3770a7be9..efd37aeb1 100644 --- a/library/sinks/BetterSQLite3.test.ts +++ b/library/sinks/BetterSQLite3.test.ts @@ -1,9 +1,10 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { runWithContext, type Context } from "../agent/Context"; import { LoggerNoop } from "../agent/logger/LoggerNoop"; import { BetterSQLite3 } from "./BetterSQLite3"; +import { isCJS } from "../helpers/isCJS"; const dangerousContext: Context = { remoteAddress: "::1", @@ -54,11 +55,14 @@ t.test("it detects SQL injections", async (t) => { new LoggerNoop(), new ReportingAPIForTesting(), undefined, - "lambda" + "lambda", + !isCJS() ); agent.start([new BetterSQLite3()]); - const betterSqlite3 = require("better-sqlite3"); + const betterSqlite3 = isCJS() + ? require("better-sqlite3") + : (await import("better-sqlite3")).default; const db = new betterSqlite3(":memory:"); try { diff --git a/library/sinks/BetterSQLite3.ts b/library/sinks/BetterSQLite3.ts index f29f170b0..bc7070c95 100644 --- a/library/sinks/BetterSQLite3.ts +++ b/library/sinks/BetterSQLite3.ts @@ -69,15 +69,17 @@ export class BetterSQLite3 implements Wrapper { .addPackage("better-sqlite3") .withVersion("^11.0.0 || ^10.0.0 || ^9.0.0 || ^8.0.0") .onRequire((exports, pkgInfo) => { + const base = pkgInfo.isESMImport ? exports.default : exports; + for (const func of sqlFunctions) { - wrapExport(exports.prototype, func, pkgInfo, { + wrapExport(base.prototype, func, pkgInfo, { inspectArgs: (args) => { return this.inspectQuery(`better-sqlite3.${func}`, args); }, }); } for (const func of fsPathFunctions) { - wrapExport(exports.prototype, func, pkgInfo, { + wrapExport(base.prototype, func, pkgInfo, { inspectArgs: (args) => { return this.inspectPath(`better-sqlite3.${func}`, args); }, diff --git a/library/sinks/ChildProcess.test.ts b/library/sinks/ChildProcess.test.ts index b57e72b1a..b3db4b6fa 100644 --- a/library/sinks/ChildProcess.test.ts +++ b/library/sinks/ChildProcess.test.ts @@ -1,10 +1,11 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Context, runWithContext } from "../agent/Context"; import { LoggerNoop } from "../agent/logger/LoggerNoop"; import { ChildProcess } from "./ChildProcess"; -import { execFile, execFileSync, fork } from "child_process"; +import { execFile, execFileSync } from "child_process"; +import { isCJS } from "../helpers/isCJS"; const unsafeContext: Context = { remoteAddress: "::1", @@ -36,12 +37,15 @@ t.test("it works", async (t) => { new LoggerNoop(), new ReportingAPIForTesting(), undefined, - "lambda" + "lambda", + !isCJS() ); agent.start([new ChildProcess()]); - const { exec, execSync, spawn, spawnSync, fork } = require("child_process"); + const { exec, execSync, spawn, spawnSync, fork } = isCJS() + ? require("child_process") + : await import("child_process"); const runCommandsWithInvalidArgs = () => { throws( diff --git a/library/sinks/ChildProcess.ts b/library/sinks/ChildProcess.ts index 3a2fa7849..8b1bcd064 100644 --- a/library/sinks/ChildProcess.ts +++ b/library/sinks/ChildProcess.ts @@ -19,41 +19,47 @@ const PATH_PREFIXES = [ export class ChildProcess implements Wrapper { wrap(hooks: Hooks) { hooks.addBuiltinModule("child_process").onRequire((exports, pkgInfo) => { - wrapExport(exports, "exec", pkgInfo, { - inspectArgs: (args) => { - return this.inspectExec(args, "exec"); - }, - }); - wrapExport(exports, "execSync", pkgInfo, { - inspectArgs: (args) => { - return this.inspectExec(args, "execSync"); - }, - }); - wrapExport(exports, "spawn", pkgInfo, { - inspectArgs: (args) => { - return this.inspectSpawn(args, "spawn"); - }, - }); - wrapExport(exports, "spawnSync", pkgInfo, { - inspectArgs: (args) => { - return this.inspectSpawn(args, "spawnSync"); - }, - }); - wrapExport(exports, "execFile", pkgInfo, { - inspectArgs: (args) => { - return this.inspectExecFile(args, "execFile"); - }, - }); - wrapExport(exports, "execFileSync", pkgInfo, { - inspectArgs: (args) => { - return this.inspectExecFile(args, "execFileSync"); - }, - }); - wrapExport(exports, "fork", pkgInfo, { - inspectArgs: (args) => { - return this.inspectFork(args, "fork"); - }, - }); + const toWrap = pkgInfo.isESMImport + ? [exports, exports.default] + : [exports]; + + for (const exportObj of toWrap) { + wrapExport(exportObj, "exec", pkgInfo, { + inspectArgs: (args) => { + return this.inspectExec(args, "exec"); + }, + }); + wrapExport(exportObj, "execSync", pkgInfo, { + inspectArgs: (args) => { + return this.inspectExec(args, "execSync"); + }, + }); + wrapExport(exportObj, "spawn", pkgInfo, { + inspectArgs: (args) => { + return this.inspectSpawn(args, "spawn"); + }, + }); + wrapExport(exportObj, "spawnSync", pkgInfo, { + inspectArgs: (args) => { + return this.inspectSpawn(args, "spawnSync"); + }, + }); + wrapExport(exportObj, "execFile", pkgInfo, { + inspectArgs: (args) => { + return this.inspectExecFile(args, "execFile"); + }, + }); + wrapExport(exportObj, "execFileSync", pkgInfo, { + inspectArgs: (args) => { + return this.inspectExecFile(args, "execFileSync"); + }, + }); + wrapExport(exportObj, "fork", pkgInfo, { + inspectArgs: (args) => { + return this.inspectFork(args, "fork"); + }, + }); + } }); } diff --git a/library/sinks/Fetch.test.ts b/library/sinks/Fetch.test.ts index b2ed54089..eeb4892b6 100644 --- a/library/sinks/Fetch.test.ts +++ b/library/sinks/Fetch.test.ts @@ -1,5 +1,5 @@ /* eslint-disable prefer-rest-params */ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Token } from "../agent/api/Token"; @@ -8,35 +8,39 @@ import { LoggerNoop } from "../agent/logger/LoggerNoop"; import { wrap } from "../helpers/wrap"; import { Fetch } from "./Fetch"; import * as dns from "dns"; +import { isCJS } from "../helpers/isCJS"; const calls: Record = {}; -wrap(dns, "lookup", function lookup(original) { - return function lookup() { - const hostname = arguments[0]; - if (!calls[hostname]) { - calls[hostname] = 0; - } +if (isCJS()) { + wrap(dns, "lookup", function lookup(original) { + return function lookup() { + const hostname = arguments[0]; - calls[hostname]++; + if (!calls[hostname]) { + calls[hostname] = 0; + } - if (hostname === "thisdomainpointstointernalip.com") { - return original.apply(this, [ - "localhost", - ...Array.from(arguments).slice(1), - ]); - } + calls[hostname]++; - if (hostname === "example,prefix.thisdomainpointstointernalip.com") { - return original.apply(this, [ - "localhost", - ...Array.from(arguments).slice(1), - ]); - } + if (hostname === "thisdomainpointstointernalip.com") { + return original.apply(this, [ + "localhost", + ...Array.from(arguments).slice(1), + ]); + } - original.apply(this, arguments); - }; -}); + if (hostname === "example,prefix.thisdomainpointstointernalip.com") { + return original.apply(this, [ + "localhost", + ...Array.from(arguments).slice(1), + ]); + } + + original.apply(this, arguments); + }; + }); +} const context: Context = { remoteAddress: "::1", @@ -76,7 +80,8 @@ t.test( new LoggerNoop(), api, new Token("123"), - undefined + undefined, + !isCJS() ); agent.start([new Fetch()]); @@ -154,47 +159,50 @@ t.test( } }); - await runWithContext( - { - ...context, - ...{ - body: { - image2: [ - "http://example", - "prefix.thisdomainpointstointernalip.com", - ], - image: "http://thisdomainpointstointernalip.com/path", + // Because we need to wrap dns here in the test + if (isCJS()) { + await runWithContext( + { + ...context, + ...{ + body: { + image2: [ + "http://example", + "prefix.thisdomainpointstointernalip.com", + ], + image: "http://thisdomainpointstointernalip.com/path", + }, }, }, - }, - async () => { - const error = await t.rejects(() => - fetch("http://thisdomainpointstointernalip.com") - ); - if (error instanceof Error) { - t.same( - // @ts-expect-error Type is not defined - error.cause.message, - "Zen has blocked a server-side request forgery: fetch(...) originating from body.image" + async () => { + const error = await t.rejects(() => + fetch("http://thisdomainpointstointernalip.com") ); - } + if (error instanceof Error) { + t.same( + // @ts-expect-error Type is not defined + error.cause.message, + "Zen has blocked a server-side request forgery: fetch(...) originating from body.image" + ); + } - const error2 = await t.rejects(() => - fetch(["http://example", "prefix.thisdomainpointstointernalip.com"]) - ); - if (error2 instanceof Error) { - t.same( - // @ts-expect-error Type is not defined - error2.cause.message, - "Zen has blocked a server-side request forgery: fetch(...) originating from body.image2" + const error2 = await t.rejects(() => + fetch(["http://example", "prefix.thisdomainpointstointernalip.com"]) ); - } + if (error2 instanceof Error) { + t.same( + // @ts-expect-error Type is not defined + error2.cause.message, + "Zen has blocked a server-side request forgery: fetch(...) originating from body.image2" + ); + } - // Ensure the lookup is only called once per hostname - // Otherwise, it could be vulnerable to TOCTOU - t.same(calls["thisdomainpointstointernalip.com"], 1); - } - ); + // Ensure the lookup is only called once per hostname + // Otherwise, it could be vulnerable to TOCTOU + t.same(calls["thisdomainpointstointernalip.com"], 1); + } + ); + } await runWithContext( { diff --git a/library/sinks/FileSystem.test.ts b/library/sinks/FileSystem.test.ts index a13132e70..8e7da45ea 100644 --- a/library/sinks/FileSystem.test.ts +++ b/library/sinks/FileSystem.test.ts @@ -1,9 +1,10 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Context, runWithContext } from "../agent/Context"; import { LoggerNoop } from "../agent/logger/LoggerNoop"; import { FileSystem } from "./FileSystem"; +import { isCJS } from "../helpers/isCJS"; const unsafeContext: Context = { remoteAddress: "::1", @@ -52,7 +53,8 @@ t.test("it works", async (t) => { new LoggerNoop(), new ReportingAPIForTesting(), undefined, - "lambda" + "lambda", + !isCJS() ); agent.start([new FileSystem()]); @@ -64,8 +66,10 @@ t.test("it works", async (t) => { realpath, promises: fsDotPromise, realpathSync, - } = require("fs"); - const { writeFile: writeFilePromise } = require("fs/promises"); + } = isCJS() ? require("fs") : await import("fs"); + const { writeFile: writeFilePromise } = isCJS() + ? require("fs/promises") + : await import("fs/promises"); t.ok(typeof realpath.native === "function"); t.ok(typeof realpathSync.native === "function"); diff --git a/library/sinks/FileSystem.ts b/library/sinks/FileSystem.ts index 956dcf2d8..b9e205e49 100644 --- a/library/sinks/FileSystem.ts +++ b/library/sinks/FileSystem.ts @@ -85,48 +85,60 @@ export class FileSystem implements Wrapper { wrap(hooks: Hooks) { // Wrap fs hooks.addBuiltinModule("fs").onRequire((exports, pkgInfo) => { - Object.keys(functions).forEach((name) => { - const { pathsArgs, sync, promise } = functions[name]; + const toWrap = pkgInfo.isESMImport + ? [exports, exports.default] + : [exports]; - wrapExport(exports, name, pkgInfo, { - inspectArgs: (args) => { - return this.inspectPath(args, name, pathsArgs); - }, - }); + for (const exportObj of toWrap) { + Object.keys(functions).forEach((name) => { + const { pathsArgs, sync, promise } = functions[name]; - if (sync) { - wrapExport(exports, `${name}Sync`, pkgInfo, { + wrapExport(exportObj, name, pkgInfo, { inspectArgs: (args) => { - return this.inspectPath(args, `${name}Sync`, pathsArgs); + return this.inspectPath(args, name, pathsArgs); }, }); - } - }); - // Wrap realpath.native - wrapExport(exports.realpath, "native", pkgInfo, { - inspectArgs: (args) => { - return this.inspectPath(args, "realpath.native", 1); - }, - }); - wrapExport(exports.realpathSync, "native", pkgInfo, { - inspectArgs: (args) => { - return this.inspectPath(args, "realpathSync.native", 1); - }, - }); + if (sync) { + wrapExport(exportObj, `${name}Sync`, pkgInfo, { + inspectArgs: (args) => { + return this.inspectPath(args, `${name}Sync`, pathsArgs); + }, + }); + } + }); + + // Wrap realpath.native + wrapExport(exportObj.realpath, "native", pkgInfo, { + inspectArgs: (args) => { + return this.inspectPath(args, "realpath.native", 1); + }, + }); + wrapExport(exportObj.realpathSync, "native", pkgInfo, { + inspectArgs: (args) => { + return this.inspectPath(args, "realpathSync.native", 1); + }, + }); + } }); // Wrap fs/promises hooks.addBuiltinModule("fs/promises").onRequire((exports, pkgInfo) => { - Object.keys(functions).forEach((name) => { - const { pathsArgs, sync, promise } = functions[name]; + const toWrap = pkgInfo.isESMImport + ? [exports, exports.default] + : [exports]; - if (promise) { - wrapExport(exports, name, pkgInfo, { - inspectArgs: (args) => this.inspectPath(args, name, pathsArgs), - }); - } - }); + for (const exportObj of toWrap) { + Object.keys(functions).forEach((name) => { + const { pathsArgs, promise } = functions[name]; + + if (promise) { + wrapExport(exportObj, name, pkgInfo, { + inspectArgs: (args) => this.inspectPath(args, name, pathsArgs), + }); + } + }); + } }); } } diff --git a/library/sinks/HTTPRequest.axios.test.ts b/library/sinks/HTTPRequest.axios.test.ts index e0d12083b..2d0d29361 100644 --- a/library/sinks/HTTPRequest.axios.test.ts +++ b/library/sinks/HTTPRequest.axios.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Token } from "../agent/api/Token"; diff --git a/library/sinks/HTTPRequest.followRedirects.test.ts b/library/sinks/HTTPRequest.followRedirects.test.ts index e5baeeb11..1b761fcf1 100644 --- a/library/sinks/HTTPRequest.followRedirects.test.ts +++ b/library/sinks/HTTPRequest.followRedirects.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Token } from "../agent/api/Token"; diff --git a/library/sinks/HTTPRequest.needle.test.ts b/library/sinks/HTTPRequest.needle.test.ts index cc1bd643d..1b597cbe4 100644 --- a/library/sinks/HTTPRequest.needle.test.ts +++ b/library/sinks/HTTPRequest.needle.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Token } from "../agent/api/Token"; diff --git a/library/sinks/HTTPRequest.nodeFetch.test.ts b/library/sinks/HTTPRequest.nodeFetch.test.ts index 7ad3951d8..39b4d9fae 100644 --- a/library/sinks/HTTPRequest.nodeFetch.test.ts +++ b/library/sinks/HTTPRequest.nodeFetch.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Token } from "../agent/api/Token"; diff --git a/library/sinks/HTTPRequest.redirect.test.ts b/library/sinks/HTTPRequest.redirect.test.ts index 66374adf7..189dfdfe2 100644 --- a/library/sinks/HTTPRequest.redirect.test.ts +++ b/library/sinks/HTTPRequest.redirect.test.ts @@ -1,5 +1,5 @@ /* eslint-disable prefer-rest-params */ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Token } from "../agent/api/Token"; diff --git a/library/sinks/HTTPRequest.test.ts b/library/sinks/HTTPRequest.test.ts index 85bb98934..3b7ace013 100644 --- a/library/sinks/HTTPRequest.test.ts +++ b/library/sinks/HTTPRequest.test.ts @@ -1,6 +1,6 @@ /* eslint-disable prefer-rest-params */ import * as dns from "dns"; -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Token } from "../agent/api/Token"; @@ -8,31 +8,35 @@ import { Context, runWithContext } from "../agent/Context"; import { LoggerNoop } from "../agent/logger/LoggerNoop"; import { wrap } from "../helpers/wrap"; import { HTTPRequest } from "./HTTPRequest"; +import { isCJS } from "../helpers/isCJS"; const calls: Record = {}; -wrap(dns, "lookup", function lookup(original) { - return function lookup() { - const hostname = arguments[0]; - if (!calls[hostname]) { - calls[hostname] = 0; - } - - calls[hostname]++; - - if ( - hostname === "thisdomainpointstointernalip.com" || - hostname === "thisdomainpointstointernalip2.com" - ) { - return original.apply(this, [ - "localhost", - ...Array.from(arguments).slice(1), - ]); - } - - original.apply(this, arguments); - }; -}); +if (isCJS()) { + wrap(dns, "lookup", function lookup(original) { + return function lookup() { + const hostname = arguments[0]; + + if (!calls[hostname]) { + calls[hostname] = 0; + } + + calls[hostname]++; + + if ( + hostname === "thisdomainpointstointernalip.com" || + hostname === "thisdomainpointstointernalip2.com" + ) { + return original.apply(this, [ + "localhost", + ...Array.from(arguments).slice(1), + ]); + } + + original.apply(this, arguments); + }; + }); +} const context: Context = { remoteAddress: "::1", @@ -49,21 +53,30 @@ const context: Context = { route: "/posts/:id", }; -t.test("it works", (t) => { - const agent = new Agent( +let http: typeof import("http"); +let https: typeof import("https"); +let agent: Agent; + +// Separate test for the setup is required because the setup is async +// The second test can not be async because we can not defer the t.end() call in the end +t.test("setup", async (t) => { + agent = new Agent( true, new LoggerNoop(), new ReportingAPIForTesting(), new Token("123"), - undefined + undefined, + !isCJS() ); agent.start([new HTTPRequest()]); t.same(agent.getHostnames().asArray(), []); - const http = require("http"); - const https = require("https"); + http = isCJS() ? require("http") : (await import("http")).default; + https = isCJS() ? require("https") : (await import("https")).default; +}); +t.test("it works", (t) => { runWithContext(context, () => { const aikido = http.request("http://aikido.dev"); aikido.end(); @@ -133,47 +146,55 @@ t.test("it works", (t) => { t.same(agent.getHostnames().asArray(), []); agent.getHostnames().clear(); - runWithContext( - { ...context, ...{ body: { image: "thisdomainpointstointernalip.com" } } }, - () => { - https - .request("https://thisdomainpointstointernalip.com") - .on("error", (error) => { - t.match( - error.message, - "Zen has blocked a server-side request forgery: https.request(...) originating from body.image" - ); - - // Ensure the lookup is only called once per hostname - // Otherwise, it could be vulnerable to TOCTOU - t.same(calls["thisdomainpointstointernalip.com"], 1); - }) - .on("finish", () => { - t.fail("should not finish"); - }) - .end(); - } - ); + if (isCJS()) { + runWithContext( + { + ...context, + ...{ body: { image: "thisdomainpointstointernalip.com" } }, + }, + () => { + https + .request("https://thisdomainpointstointernalip.com") + .on("error", (error) => { + t.match( + error.message, + "Zen has blocked a server-side request forgery: https.request(...) originating from body.image" + ); + + // Ensure the lookup is only called once per hostname + // Otherwise, it could be vulnerable to TOCTOU + t.same(calls["thisdomainpointstointernalip.com"], 1); + }) + .on("finish", () => { + t.fail("should not finish"); + }) + .end(); + } + ); - runWithContext( - { ...context, ...{ body: { image: "thisdomainpointstointernalip2.com" } } }, - () => { - https - .request("https://thisdomainpointstointernalip2.com", (res) => { - t.fail("should not respond"); - }) - .on("error", (error) => { - t.match( - error.message, - "Zen has blocked a server-side request forgery: https.request(...) originating from body.image" - ); - }) - .on("finish", () => { - t.fail("should not finish"); - }) - .end(); - } - ); + runWithContext( + { + ...context, + ...{ body: { image: "thisdomainpointstointernalip2.com" } }, + }, + () => { + https + .request("https://thisdomainpointstointernalip2.com", (res) => { + t.fail("should not respond"); + }) + .on("error", (error) => { + t.match( + error.message, + "Zen has blocked a server-side request forgery: https.request(...) originating from body.image" + ); + }) + .on("finish", () => { + t.fail("should not finish"); + }) + .end(); + } + ); + } runWithContext(context, () => { // With lookup function specified diff --git a/library/sinks/HTTPRequest.ts b/library/sinks/HTTPRequest.ts index 660aca7c1..1a90fe8ac 100644 --- a/library/sinks/HTTPRequest.ts +++ b/library/sinks/HTTPRequest.ts @@ -164,16 +164,22 @@ export class HTTPRequest implements Wrapper { for (const module of modules) { hooks.addBuiltinModule(module).onRequire((exports, pkgInfo) => { - 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 - inspectArgs: (args, agent) => - this.inspectHttpRequest(args, agent, module), - // Whenever a request is made, we'll modify the options to pass a custom lookup function - // that will inspect resolved IP address (and thus preventing TOCTOU attacks) - modifyArgs: (args, agent) => - this.monitorDNSLookups(args, agent, module), - }); + const toWrap = pkgInfo.isESMImport + ? [exports, exports.default] + : [exports]; + + for (const exportObj of toWrap) { + for (const method of methods) { + wrapExport(exportObj, method, pkgInfo, { + // Whenever a request is made, we'll check the hostname whether it's a private IP + inspectArgs: (args, agent) => + this.inspectHttpRequest(args, agent, module), + // Whenever a request is made, we'll modify the options to pass a custom lookup function + // that will inspect resolved IP address (and thus preventing TOCTOU attacks) + modifyArgs: (args, agent) => + this.monitorDNSLookups(args, agent, module), + }); + } } }); } diff --git a/library/sinks/MongoDB.test.ts b/library/sinks/MongoDB.test.ts index b8feba3b6..d4ecc5459 100644 --- a/library/sinks/MongoDB.test.ts +++ b/library/sinks/MongoDB.test.ts @@ -1,9 +1,10 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Context, runWithContext } from "../agent/Context"; import { LoggerNoop } from "../agent/logger/LoggerNoop"; import { MongoDB } from "./MongoDB"; +import { isCJS } from "../helpers/isCJS"; const unsafeContext: Context = { remoteAddress: "::1", @@ -41,11 +42,14 @@ t.test("it inspects method calls and blocks if needed", async (t) => { new LoggerNoop(), new ReportingAPIForTesting(), undefined, - "lambda" + "lambda", + !isCJS() ); agent.start([new MongoDB()]); - const { MongoClient } = require("mongodb"); + const { MongoClient } = isCJS() + ? require("mongodb") + : await import("mongodb"); const client = new MongoClient("mongodb://root:password@127.0.0.1:27017"); await client.connect(); diff --git a/library/sinks/MongoDB.ts b/library/sinks/MongoDB.ts index 05fd28ef2..14828555d 100644 --- a/library/sinks/MongoDB.ts +++ b/library/sinks/MongoDB.ts @@ -191,29 +191,39 @@ export class MongoDB implements Wrapper { .addPackage("mongodb") .withVersion("^4.0.0 || ^5.0.0 || ^6.0.0") .onRequire((exports, pkgInfo) => { - const collectionProto = exports.Collection.prototype; + const toWrap = pkgInfo.isESMImport + ? [exports, exports.default] + : [exports]; + + for (const exportObj of toWrap) { + const collectionProto = exportObj.Collection.prototype; + + OPERATIONS_WITH_FILTER.forEach((operation) => { + wrapExport(collectionProto, operation, pkgInfo, { + inspectArgs: (args, agent, collection) => + this.inspectOperation( + operation, + args, + collection as Collection + ), + }); + }); + + wrapExport(collectionProto, "bulkWrite", pkgInfo, { + inspectArgs: (args, agent, collection) => + this.inspectBulkWrite(args, collection as Collection), + }); - OPERATIONS_WITH_FILTER.forEach((operation) => { - wrapExport(collectionProto, operation, pkgInfo, { + wrapExport(collectionProto, "aggregate", pkgInfo, { inspectArgs: (args, agent, collection) => - this.inspectOperation(operation, args, collection as Collection), + this.inspectAggregate(args, collection as Collection), }); - }); - - wrapExport(collectionProto, "bulkWrite", pkgInfo, { - inspectArgs: (args, agent, collection) => - this.inspectBulkWrite(args, collection as Collection), - }); - - wrapExport(collectionProto, "aggregate", pkgInfo, { - inspectArgs: (args, agent, collection) => - this.inspectAggregate(args, collection as Collection), - }); - - wrapExport(collectionProto, "distinct", pkgInfo, { - inspectArgs: (args, agent, collection) => - this.inspectDistinct(args, collection as Collection), - }); + + wrapExport(collectionProto, "distinct", pkgInfo, { + inspectArgs: (args, agent, collection) => + this.inspectDistinct(args, collection as Collection), + }); + } }); } } diff --git a/library/sinks/MySQL.test.ts b/library/sinks/MySQL.test.ts index 654a4d4ef..3de54b00a 100644 --- a/library/sinks/MySQL.test.ts +++ b/library/sinks/MySQL.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { getContext, runWithContext, type Context } from "../agent/Context"; diff --git a/library/sinks/MySQL2.test.ts b/library/sinks/MySQL2.test.ts index a2604aa8a..c1425bd88 100644 --- a/library/sinks/MySQL2.test.ts +++ b/library/sinks/MySQL2.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { runWithContext, type Context } from "../agent/Context"; diff --git a/library/sinks/NodeSQLite.test.ts b/library/sinks/NodeSQLite.test.ts index c1450318f..15e1ba5b2 100644 --- a/library/sinks/NodeSQLite.test.ts +++ b/library/sinks/NodeSQLite.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { runWithContext, type Context } from "../agent/Context"; diff --git a/library/sinks/Path.test.ts b/library/sinks/Path.test.ts index a104df230..44fd6c355 100644 --- a/library/sinks/Path.test.ts +++ b/library/sinks/Path.test.ts @@ -1,9 +1,10 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Context, runWithContext } from "../agent/Context"; import { LoggerNoop } from "../agent/logger/LoggerNoop"; import { Path } from "./Path"; +import { isCJS } from "../helpers/isCJS"; const unsafeContext: Context = { remoteAddress: "::1", @@ -33,12 +34,13 @@ t.test("it works", async (t) => { new LoggerNoop(), new ReportingAPIForTesting(), undefined, - undefined + undefined, + !isCJS() ); agent.start([new Path()]); - const { join, resolve } = require("path"); + const { join, resolve } = isCJS() ? require("path") : await import("path"); function safeCalls() { t.same(join("test.txt"), "test.txt"); diff --git a/library/sinks/Path.ts b/library/sinks/Path.ts index c5a4b5148..1846bd17c 100644 --- a/library/sinks/Path.ts +++ b/library/sinks/Path.ts @@ -36,11 +36,18 @@ export class Path implements Wrapper { wrap(hooks: Hooks): void { const functions = ["join", "resolve", "normalize"]; + // Todo after merging main: check path/posix and path/win32 hooks.addBuiltinModule("path").onRequire((exports, pkgInfo) => { - for (const func of functions) { - wrapExport(exports, func, pkgInfo, { - inspectArgs: (args) => this.inspectPath(args, func), - }); + const wrapParts = pkgInfo.isESMImport + ? [exports, exports.default] + : [exports.posix, exports.win32]; + + for (const toWrap of wrapParts) { + for (const func of functions) { + wrapExport(toWrap, func, pkgInfo, { + inspectArgs: (args) => this.inspectPath(args, func), + }); + } } }); } diff --git a/library/sinks/Postgres.pool.test.ts b/library/sinks/Postgres.pool.test.ts index f5e9310f7..8bb384557 100644 --- a/library/sinks/Postgres.pool.test.ts +++ b/library/sinks/Postgres.pool.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { runWithContext, type Context } from "../agent/Context"; diff --git a/library/sinks/Postgres.test.ts b/library/sinks/Postgres.test.ts index cf269d66f..bc3f507a1 100644 --- a/library/sinks/Postgres.test.ts +++ b/library/sinks/Postgres.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { getContext, runWithContext, type Context } from "../agent/Context"; diff --git a/library/sinks/SQLite3.test.ts b/library/sinks/SQLite3.test.ts index 79b53685e..3a2bc22c8 100644 --- a/library/sinks/SQLite3.test.ts +++ b/library/sinks/SQLite3.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { runWithContext, type Context } from "../agent/Context"; diff --git a/library/sinks/SQLite3.ts b/library/sinks/SQLite3.ts index 7aebce1ee..7914cf734 100644 --- a/library/sinks/SQLite3.ts +++ b/library/sinks/SQLite3.ts @@ -76,7 +76,12 @@ export class SQLite3 implements Wrapper { .addPackage("sqlite3") .withVersion("^5.0.0") .onRequire((exports, pkgInfo) => { - const db = exports.Database.prototype; + let db: any; + if (pkgInfo.isESMImport) { + db = exports.default.Database.prototype; + } else { + db = exports.Database.prototype; + } for (const func of sqlFunctions) { wrapExport(db, func, pkgInfo, { diff --git a/library/sinks/Shelljs.test.ts b/library/sinks/Shelljs.test.ts index 2c1cfe9b5..e04e0ccc2 100644 --- a/library/sinks/Shelljs.test.ts +++ b/library/sinks/Shelljs.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { getContext, runWithContext, type Context } from "../agent/Context"; diff --git a/library/sinks/Undici.test.ts b/library/sinks/Undici.test.ts index 2e0155c93..802b2f25a 100644 --- a/library/sinks/Undici.test.ts +++ b/library/sinks/Undici.test.ts @@ -1,6 +1,6 @@ /* eslint-disable prefer-rest-params */ import * as dns from "dns"; -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Token } from "../agent/api/Token"; diff --git a/library/sinks/http-request/getUrlFromHTTPRequestArgs.test.ts b/library/sinks/http-request/getUrlFromHTTPRequestArgs.test.ts index b8179f133..0d41d24d0 100644 --- a/library/sinks/http-request/getUrlFromHTTPRequestArgs.test.ts +++ b/library/sinks/http-request/getUrlFromHTTPRequestArgs.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { getUrlFromHTTPRequestArgs as getURL } from "./getUrlFromHTTPRequestArgs"; t.test("it works with strings", async (t) => { diff --git a/library/sinks/http-request/isOptionsObject.test.ts b/library/sinks/http-request/isOptionsObject.test.ts index d91a490c3..9a4c3e7b6 100644 --- a/library/sinks/http-request/isOptionsObject.test.ts +++ b/library/sinks/http-request/isOptionsObject.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { isOptionsObject } from "./isOptionsObject"; t.test("it works with objects", async (t) => { diff --git a/library/sinks/undici/parseHeaders.test.ts b/library/sinks/undici/parseHeaders.test.ts index f0f0c395a..a17fca085 100644 --- a/library/sinks/undici/parseHeaders.test.ts +++ b/library/sinks/undici/parseHeaders.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { parseHeaders } from "./parseHeaders"; t.test("it works", async (t) => { diff --git a/library/sources/Express.test.ts b/library/sources/Express.test.ts index 62b64a21b..3c7304de9 100644 --- a/library/sources/Express.test.ts +++ b/library/sources/Express.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { setInstance } from "../agent/AgentSingleton"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; diff --git a/library/sources/FastXmlParser.test.ts b/library/sources/FastXmlParser.test.ts index e79cfbeaf..80d145807 100644 --- a/library/sources/FastXmlParser.test.ts +++ b/library/sources/FastXmlParser.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { getContext, runWithContext } from "../agent/Context"; diff --git a/library/sources/FunctionsFramework.test.ts b/library/sources/FunctionsFramework.test.ts index 4b901d439..add3c268e 100644 --- a/library/sources/FunctionsFramework.test.ts +++ b/library/sources/FunctionsFramework.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import * as express from "express"; import * as request from "supertest"; import { Agent } from "../agent/Agent"; diff --git a/library/sources/GraphQL.test.ts b/library/sources/GraphQL.test.ts index 321f402b6..2f97eb125 100644 --- a/library/sources/GraphQL.test.ts +++ b/library/sources/GraphQL.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { getContext, runWithContext } from "../agent/Context"; diff --git a/library/sources/HTTP2Server.test.ts b/library/sources/HTTP2Server.test.ts index 8d9a461cf..60e7db6ee 100644 --- a/library/sources/HTTP2Server.test.ts +++ b/library/sources/HTTP2Server.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Token } from "../agent/api/Token"; import { connect, IncomingHttpHeaders } from "http2"; import { Agent } from "../agent/Agent"; diff --git a/library/sources/HTTPServer.test.ts b/library/sources/HTTPServer.test.ts index f0f5f4b31..16ab66919 100644 --- a/library/sources/HTTPServer.test.ts +++ b/library/sources/HTTPServer.test.ts @@ -14,7 +14,7 @@ wrap(pkg, "isPackageInstalled", function wrap() { }; }); -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { getContext } from "../agent/Context"; diff --git a/library/sources/Hapi.test.ts b/library/sources/Hapi.test.ts index 5f86e2836..c91adc1bd 100644 --- a/library/sources/Hapi.test.ts +++ b/library/sources/Hapi.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { setInstance } from "../agent/AgentSingleton"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; diff --git a/library/sources/Hono.test.ts b/library/sources/Hono.test.ts index 2ed0c5b2c..6c1aa74ba 100644 --- a/library/sources/Hono.test.ts +++ b/library/sources/Hono.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { setInstance } from "../agent/AgentSingleton"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; diff --git a/library/sources/Lambda.test.ts b/library/sources/Lambda.test.ts index bc0d2173f..b901b0df0 100644 --- a/library/sources/Lambda.test.ts +++ b/library/sources/Lambda.test.ts @@ -1,6 +1,6 @@ import * as FakeTimers from "@sinonjs/fake-timers"; import type { Context } from "aws-lambda"; -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { setInstance } from "../agent/AgentSingleton"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; diff --git a/library/sources/Xml2js.test.ts b/library/sources/Xml2js.test.ts index 3d0568361..9ca52e1aa 100644 --- a/library/sources/Xml2js.test.ts +++ b/library/sources/Xml2js.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { Context, getContext, runWithContext } from "../agent/Context"; diff --git a/library/sources/XmlMinusJs.test.ts b/library/sources/XmlMinusJs.test.ts index 4d4311f42..a8da70d47 100644 --- a/library/sources/XmlMinusJs.test.ts +++ b/library/sources/XmlMinusJs.test.ts @@ -1,5 +1,5 @@ import { join } from "path"; -import * as t from "tap"; +import t from "tap"; import { Agent } from "../agent/Agent"; import { ReportingAPIForTesting } from "../agent/api/ReportingAPIForTesting"; import { getContext, runWithContext } from "../agent/Context"; diff --git a/library/sources/graphql/extractInputsFromDocument.test.ts b/library/sources/graphql/extractInputsFromDocument.test.ts index 0c68cfc6e..e7529ffb7 100644 --- a/library/sources/graphql/extractInputsFromDocument.test.ts +++ b/library/sources/graphql/extractInputsFromDocument.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { GraphQLSchema, GraphQLObjectType, diff --git a/library/sources/graphql/extractTopLevelFieldsFromDocument.test.ts b/library/sources/graphql/extractTopLevelFieldsFromDocument.test.ts index 89f119536..c763ae467 100644 --- a/library/sources/graphql/extractTopLevelFieldsFromDocument.test.ts +++ b/library/sources/graphql/extractTopLevelFieldsFromDocument.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { parse, FieldNode } from "graphql"; import { extractTopLevelFieldsFromDocument, diff --git a/library/sources/graphql/shouldRateLimitOperation.test.ts b/library/sources/graphql/shouldRateLimitOperation.test.ts index 0b0363c79..19b40c9d2 100644 --- a/library/sources/graphql/shouldRateLimitOperation.test.ts +++ b/library/sources/graphql/shouldRateLimitOperation.test.ts @@ -1,5 +1,5 @@ import { parse, ExecutionArgs } from "graphql"; -import * as t from "tap"; +import t from "tap"; import { Agent } from "../../agent/Agent"; import { ReportingAPIForTesting } from "../../agent/api/ReportingAPIForTesting"; import { Token } from "../../agent/api/Token"; diff --git a/library/sources/http-server/ipAllowedToAccessRoute.test.ts b/library/sources/http-server/ipAllowedToAccessRoute.test.ts index 1e08630dd..1431ac807 100644 --- a/library/sources/http-server/ipAllowedToAccessRoute.test.ts +++ b/library/sources/http-server/ipAllowedToAccessRoute.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../../agent/Agent"; import { ReportingAPIForTesting } from "../../agent/api/ReportingAPIForTesting"; import { Token } from "../../agent/api/Token"; diff --git a/library/sources/http-server/shouldDiscoverRoute.test.ts b/library/sources/http-server/shouldDiscoverRoute.test.ts index ac10649fc..22a048b71 100644 --- a/library/sources/http-server/shouldDiscoverRoute.test.ts +++ b/library/sources/http-server/shouldDiscoverRoute.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { shouldDiscoverRoute } from "./shouldDiscoverRoute"; t.test("it rejects invalid status codes", async () => { diff --git a/library/tsconfig.esm-test.json b/library/tsconfig.esm-test.json new file mode 100644 index 000000000..6c26cc300 --- /dev/null +++ b/library/tsconfig.esm-test.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ESNext", + "lib": ["ESNext", "DOM"], + "module": "NodeNext", + "moduleResolution": "NodeNext", + "declaration": true, + "strict": true, + "allowJs": false, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true + }, + "include": ["**/*.test.mjs"] +} diff --git a/library/tsconfig.json b/library/tsconfig.json index e9cda6dfe..cdc68ee69 100644 --- a/library/tsconfig.json +++ b/library/tsconfig.json @@ -11,5 +11,5 @@ "skipLibCheck": true }, "include": ["**/*.ts"], - "exclude": ["**/*.test.ts"] + "exclude": ["**/*.test.ts", "**/*.test.mjs"] } diff --git a/library/vulnerabilities/nosql-injection/detectNoSQLInjection.test.ts b/library/vulnerabilities/nosql-injection/detectNoSQLInjection.test.ts index 377b8b32f..3ec6ea878 100644 --- a/library/vulnerabilities/nosql-injection/detectNoSQLInjection.test.ts +++ b/library/vulnerabilities/nosql-injection/detectNoSQLInjection.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { detectNoSQLInjection } from "./detectNoSQLInjection"; import { Context } from "../../agent/Context"; diff --git a/library/vulnerabilities/path-traversal/checkContextForPathTraversal.test.ts b/library/vulnerabilities/path-traversal/checkContextForPathTraversal.test.ts index 7788bc7db..9aecaa355 100644 --- a/library/vulnerabilities/path-traversal/checkContextForPathTraversal.test.ts +++ b/library/vulnerabilities/path-traversal/checkContextForPathTraversal.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { checkContextForPathTraversal } from "./checkContextForPathTraversal"; const unsafeContext = { diff --git a/library/vulnerabilities/path-traversal/detectPathTraversal.test.ts b/library/vulnerabilities/path-traversal/detectPathTraversal.test.ts index 1fe0acfff..0d9568587 100644 --- a/library/vulnerabilities/path-traversal/detectPathTraversal.test.ts +++ b/library/vulnerabilities/path-traversal/detectPathTraversal.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { detectPathTraversal } from "./detectPathTraversal"; import { join, resolve } from "path"; diff --git a/library/vulnerabilities/prototype-pollution/preventPrototypePollution.test.ts b/library/vulnerabilities/prototype-pollution/preventPrototypePollution.test.ts index 691ef466e..18a48fba6 100644 --- a/library/vulnerabilities/prototype-pollution/preventPrototypePollution.test.ts +++ b/library/vulnerabilities/prototype-pollution/preventPrototypePollution.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { Agent } from "../../agent/Agent"; import { setInstance } from "../../agent/AgentSingleton"; import { ReportingAPIForTesting } from "../../agent/api/ReportingAPIForTesting"; diff --git a/library/vulnerabilities/shell-injection/checkContextForShellInjection.test.ts b/library/vulnerabilities/shell-injection/checkContextForShellInjection.test.ts index cd13d22b1..67b7a22b6 100644 --- a/library/vulnerabilities/shell-injection/checkContextForShellInjection.test.ts +++ b/library/vulnerabilities/shell-injection/checkContextForShellInjection.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { checkContextForShellInjection } from "./checkContextForShellInjection"; t.test("it detects shell injection", async () => { diff --git a/library/vulnerabilities/shell-injection/containsShellSyntax.test.ts b/library/vulnerabilities/shell-injection/containsShellSyntax.test.ts index 72794daaf..26fba85ac 100644 --- a/library/vulnerabilities/shell-injection/containsShellSyntax.test.ts +++ b/library/vulnerabilities/shell-injection/containsShellSyntax.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { containsShellSyntax } from "./containsShellSyntax"; t.test("it detects shell syntax", async (t) => { diff --git a/library/vulnerabilities/shell-injection/detectShellInjection.test.ts b/library/vulnerabilities/shell-injection/detectShellInjection.test.ts index fb7cde07f..76679cfb0 100644 --- a/library/vulnerabilities/shell-injection/detectShellInjection.test.ts +++ b/library/vulnerabilities/shell-injection/detectShellInjection.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { detectShellInjection } from "./detectShellInjection"; import { quote } from "shell-quote"; diff --git a/library/vulnerabilities/shell-injection/isSafelyEncapsulated.test.ts b/library/vulnerabilities/shell-injection/isSafelyEncapsulated.test.ts index 9ea756bb2..f32dd4087 100644 --- a/library/vulnerabilities/shell-injection/isSafelyEncapsulated.test.ts +++ b/library/vulnerabilities/shell-injection/isSafelyEncapsulated.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { isSafelyEncapsulated } from "./isSafelyEncapsulated"; t.test("safe between single quotes", async (t) => { diff --git a/library/vulnerabilities/sql-injection/checkContextForSqlInjection.test.ts b/library/vulnerabilities/sql-injection/checkContextForSqlInjection.test.ts index fd536e73d..3b239b7c7 100644 --- a/library/vulnerabilities/sql-injection/checkContextForSqlInjection.test.ts +++ b/library/vulnerabilities/sql-injection/checkContextForSqlInjection.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { checkContextForSqlInjection } from "./checkContextForSqlInjection"; import { SQLDialectMySQL } from "./dialects/SQLDialectMySQL"; diff --git a/library/vulnerabilities/sql-injection/config.test.ts b/library/vulnerabilities/sql-injection/config.test.ts index ca2ead6a6..37e7acc32 100644 --- a/library/vulnerabilities/sql-injection/config.test.ts +++ b/library/vulnerabilities/sql-injection/config.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { SQL_DANGEROUS_IN_STRING, SQL_ESCAPE_SEQUENCES, diff --git a/library/vulnerabilities/sql-injection/detectSQLInjection.mysql.test.ts b/library/vulnerabilities/sql-injection/detectSQLInjection.mysql.test.ts index 224abe79e..e37524cee 100644 --- a/library/vulnerabilities/sql-injection/detectSQLInjection.mysql.test.ts +++ b/library/vulnerabilities/sql-injection/detectSQLInjection.mysql.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { detectSQLInjection } from "./detectSQLInjection"; import { SQLDialectMySQL } from "./dialects/SQLDialectMySQL"; diff --git a/library/vulnerabilities/sql-injection/detectSQLInjection.postgres.test.ts b/library/vulnerabilities/sql-injection/detectSQLInjection.postgres.test.ts index d9ee2a2f7..7dce7fb79 100644 --- a/library/vulnerabilities/sql-injection/detectSQLInjection.postgres.test.ts +++ b/library/vulnerabilities/sql-injection/detectSQLInjection.postgres.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { detectSQLInjection } from "./detectSQLInjection"; import { SQLDialectPostgres } from "./dialects/SQLDialectPostgres"; diff --git a/library/vulnerabilities/sql-injection/detectSQLInjection.sqlite.test.ts b/library/vulnerabilities/sql-injection/detectSQLInjection.sqlite.test.ts index e5e940f7a..1e8602393 100644 --- a/library/vulnerabilities/sql-injection/detectSQLInjection.sqlite.test.ts +++ b/library/vulnerabilities/sql-injection/detectSQLInjection.sqlite.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { detectSQLInjection } from "./detectSQLInjection"; import { SQLDialectSQLite } from "./dialects/SQLDialectSQLite"; diff --git a/library/vulnerabilities/sql-injection/detectSQLInjection.test.ts b/library/vulnerabilities/sql-injection/detectSQLInjection.test.ts index 488de3d0a..b04062410 100644 --- a/library/vulnerabilities/sql-injection/detectSQLInjection.test.ts +++ b/library/vulnerabilities/sql-injection/detectSQLInjection.test.ts @@ -1,5 +1,5 @@ import { basename, join } from "path"; -import * as t from "tap"; +import t from "tap"; import { readFileSync } from "fs"; import { escapeStringRegexp } from "../../helpers/escapeStringRegexp"; import { SQL_DANGEROUS_IN_STRING, SQL_KEYWORDS } from "./config"; diff --git a/library/vulnerabilities/sql-injection/dialects/SQLDialect.test.ts b/library/vulnerabilities/sql-injection/dialects/SQLDialect.test.ts index 17ac5d1a6..df446c330 100644 --- a/library/vulnerabilities/sql-injection/dialects/SQLDialect.test.ts +++ b/library/vulnerabilities/sql-injection/dialects/SQLDialect.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { SQLDialectMySQL } from "./SQLDialectMySQL"; import { SQLDialectPostgres } from "./SQLDialectPostgres"; diff --git a/library/vulnerabilities/sql-injection/queryContainsUserInput.test.ts b/library/vulnerabilities/sql-injection/queryContainsUserInput.test.ts index 681a29870..080315bc2 100644 --- a/library/vulnerabilities/sql-injection/queryContainsUserInput.test.ts +++ b/library/vulnerabilities/sql-injection/queryContainsUserInput.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { queryContainsUserInput } from "./queryContainsUserInput"; t.test("it checks if query contains user input", async () => { diff --git a/library/vulnerabilities/sql-injection/userInputContainsSQLSyntax.test.ts b/library/vulnerabilities/sql-injection/userInputContainsSQLSyntax.test.ts index d893ee391..a00028759 100644 --- a/library/vulnerabilities/sql-injection/userInputContainsSQLSyntax.test.ts +++ b/library/vulnerabilities/sql-injection/userInputContainsSQLSyntax.test.ts @@ -1,6 +1,6 @@ import { readFileSync } from "fs"; import { join } from "path"; -import * as t from "tap"; +import t from "tap"; import { SQL_DANGEROUS_IN_STRING, SQL_KEYWORDS } from "./config"; import { SQLDialectMySQL } from "./dialects/SQLDialectMySQL"; import { SQLDialectPostgres } from "./dialects/SQLDialectPostgres"; diff --git a/library/vulnerabilities/sql-injection/userInputOccurrencesSafelyEncapsulated.test.ts b/library/vulnerabilities/sql-injection/userInputOccurrencesSafelyEncapsulated.test.ts index 6a9f858e4..daa513557 100644 --- a/library/vulnerabilities/sql-injection/userInputOccurrencesSafelyEncapsulated.test.ts +++ b/library/vulnerabilities/sql-injection/userInputOccurrencesSafelyEncapsulated.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { userInputOccurrencesSafelyEncapsulated } from "./userInputOccurrencesSafelyEncapsulated"; t.test( diff --git a/library/vulnerabilities/ssrf/containsPrivateIPAddress.test.ts b/library/vulnerabilities/ssrf/containsPrivateIPAddress.test.ts index 024c4f606..d763e3a7f 100644 --- a/library/vulnerabilities/ssrf/containsPrivateIPAddress.test.ts +++ b/library/vulnerabilities/ssrf/containsPrivateIPAddress.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { containsPrivateIPAddress } from "./containsPrivateIPAddress"; const publicIPs = [ diff --git a/library/vulnerabilities/ssrf/findHostnameInUserInput.test.ts b/library/vulnerabilities/ssrf/findHostnameInUserInput.test.ts index 362777fbe..df25595b6 100644 --- a/library/vulnerabilities/ssrf/findHostnameInUserInput.test.ts +++ b/library/vulnerabilities/ssrf/findHostnameInUserInput.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { findHostnameInUserInput } from "./findHostnameInUserInput"; t.test("returns false if user input and hostname are empty", async (t) => { diff --git a/library/vulnerabilities/ssrf/getMetadataForSSRFAttack.test.ts b/library/vulnerabilities/ssrf/getMetadataForSSRFAttack.test.ts index 32a29bd90..2167562b7 100644 --- a/library/vulnerabilities/ssrf/getMetadataForSSRFAttack.test.ts +++ b/library/vulnerabilities/ssrf/getMetadataForSSRFAttack.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { getMetadataForSSRFAttack } from "./getMetadataForSSRFAttack"; t.test("port is undefined", async () => { diff --git a/library/vulnerabilities/ssrf/getRedirectOrigin.test.ts b/library/vulnerabilities/ssrf/getRedirectOrigin.test.ts index e5e47b682..2bd808c4c 100644 --- a/library/vulnerabilities/ssrf/getRedirectOrigin.test.ts +++ b/library/vulnerabilities/ssrf/getRedirectOrigin.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { getRedirectOrigin } from "./getRedirectOrigin"; t.test("it gets the origin URL of a redirect", async (t) => { diff --git a/library/vulnerabilities/ssrf/imds.test.ts b/library/vulnerabilities/ssrf/imds.test.ts index 36b6ccbe8..e11df2964 100644 --- a/library/vulnerabilities/ssrf/imds.test.ts +++ b/library/vulnerabilities/ssrf/imds.test.ts @@ -1,4 +1,4 @@ -import * as t from "tap"; +import t from "tap"; import { isIMDSIPAddress } from "./imds"; t.test("it returns true for IMDS IP addresses", async (t) => { diff --git a/library/vulnerabilities/ssrf/inspectDNSLookupCalls.test.ts b/library/vulnerabilities/ssrf/inspectDNSLookupCalls.test.ts index ab186ea13..18e66131d 100644 --- a/library/vulnerabilities/ssrf/inspectDNSLookupCalls.test.ts +++ b/library/vulnerabilities/ssrf/inspectDNSLookupCalls.test.ts @@ -1,5 +1,5 @@ import { LookupAddress, lookup } from "dns"; -import * as t from "tap"; +import t from "tap"; import { Agent } from "../../agent/Agent"; import { ReportingAPIForTesting } from "../../agent/api/ReportingAPIForTesting"; import { Token } from "../../agent/api/Token"; diff --git a/sample-apps/cloud-functions-v1-mongodb/package-lock.json b/sample-apps/cloud-functions-v1-mongodb/package-lock.json index 83c451e93..92adabf27 100644 --- a/sample-apps/cloud-functions-v1-mongodb/package-lock.json +++ b/sample-apps/cloud-functions-v1-mongodb/package-lock.json @@ -17,6 +17,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/cloud-functions-v2-mongodb/package-lock.json b/sample-apps/cloud-functions-v2-mongodb/package-lock.json index a8665f41c..baccee864 100644 --- a/sample-apps/cloud-functions-v2-mongodb/package-lock.json +++ b/sample-apps/cloud-functions-v2-mongodb/package-lock.json @@ -17,6 +17,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/express-graphql/package-lock.json b/sample-apps/express-graphql/package-lock.json index 2d64e6bc4..0c718834a 100644 --- a/sample-apps/express-graphql/package-lock.json +++ b/sample-apps/express-graphql/package-lock.json @@ -21,6 +21,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/express-mariadb/package-lock.json b/sample-apps/express-mariadb/package-lock.json index 34627c88e..2e8dc08f7 100644 --- a/sample-apps/express-mariadb/package-lock.json +++ b/sample-apps/express-mariadb/package-lock.json @@ -21,6 +21,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/express-mongodb/package-lock.json b/sample-apps/express-mongodb/package-lock.json index 84e1efd41..827c2f616 100644 --- a/sample-apps/express-mongodb/package-lock.json +++ b/sample-apps/express-mongodb/package-lock.json @@ -23,6 +23,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/express-mongoose/package-lock.json b/sample-apps/express-mongoose/package-lock.json index 8d3a2adab..7081b9778 100644 --- a/sample-apps/express-mongoose/package-lock.json +++ b/sample-apps/express-mongoose/package-lock.json @@ -21,6 +21,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/express-mysql/package-lock.json b/sample-apps/express-mysql/package-lock.json index d3b9dca88..dcbbe4e32 100644 --- a/sample-apps/express-mysql/package-lock.json +++ b/sample-apps/express-mysql/package-lock.json @@ -22,6 +22,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/express-mysql2/package-lock.json b/sample-apps/express-mysql2/package-lock.json index 034358205..ebde51529 100644 --- a/sample-apps/express-mysql2/package-lock.json +++ b/sample-apps/express-mysql2/package-lock.json @@ -20,6 +20,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/express-path-traversal/package-lock.json b/sample-apps/express-path-traversal/package-lock.json index 108b47a7d..c0075d3d3 100644 --- a/sample-apps/express-path-traversal/package-lock.json +++ b/sample-apps/express-path-traversal/package-lock.json @@ -19,6 +19,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/express-postgres/package-lock.json b/sample-apps/express-postgres/package-lock.json index c6c860574..ff1613282 100644 --- a/sample-apps/express-postgres/package-lock.json +++ b/sample-apps/express-postgres/package-lock.json @@ -20,6 +20,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/hapi-postgres/package-lock.json b/sample-apps/hapi-postgres/package-lock.json index 2d9f30623..6c1eed0ba 100644 --- a/sample-apps/hapi-postgres/package-lock.json +++ b/sample-apps/hapi-postgres/package-lock.json @@ -17,6 +17,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/hono-mongodb/package-lock.json b/sample-apps/hono-mongodb/package-lock.json index f494ed4c6..74089858c 100644 --- a/sample-apps/hono-mongodb/package-lock.json +++ b/sample-apps/hono-mongodb/package-lock.json @@ -15,6 +15,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/hono-sqlite3-esm/Cats.js b/sample-apps/hono-sqlite3-esm/Cats.js new file mode 100644 index 000000000..95019423c --- /dev/null +++ b/sample-apps/hono-sqlite3-esm/Cats.js @@ -0,0 +1,31 @@ +import { promisify } from "util"; + +export class Cats { + /** + * + * @param {import("sqlite3").Database} db + */ + constructor(db) { + this.db = db; + this.all = promisify(this.db.all).bind(this.db); + } + + async add(name) { + const result = await this.all( + `INSERT INTO cats(petname) VALUES ('${name}');` + ); + return result; + } + + async byName(name) { + const cats = await this.all( + `SELECT petname FROM cats WHERE petname = '${name}';` + ); + return cats.map((row) => row.petname); + } + + async getAll() { + const cats = await this.all("SELECT petname FROM cats;"); + return cats.map((row) => row.petname); + } +} diff --git a/sample-apps/hono-sqlite3-esm/app.js b/sample-apps/hono-sqlite3-esm/app.js new file mode 100644 index 000000000..bd4ee92ef --- /dev/null +++ b/sample-apps/hono-sqlite3-esm/app.js @@ -0,0 +1,110 @@ +import { Hono } from "hono"; +import { serve } from "@hono/node-server"; +import { getDB } from "./db.js"; +import Aikido from "@aikidosec/firewall/context"; +import { Cats } from "./Cats.js"; + +const app = new Hono(); + +app.use(async (c, next) => { + Aikido.setUser({ + id: "id", + name: "Name", + }); + + await next(); +}); + +const db = await getDB(); +const cats = new Cats(db); + +app.get("/", async (c) => { + const catNames = await cats.getAll(); + return c.html( + ` + + +

Vulnerable app using SQLite3

+
    + ${catNames.map((name) => `
  • ${name}
  • `).join("")} +
+
+ + + +
+

SQL Injection: Test'), ('Test2');--

+ Clear all cats + + + + ` + ); +}); + +app.post("/add", async (c) => { + const body = await c.req.json(); + + if (typeof body.name !== "string") { + return c.json({ error: "Invalid request" }, 400); + } + + await cats.add(body.name); + return c.json({ success: true }); +}); + +app.get("/clear", async (c) => { + try { + await new Promise((resolve, reject) => { + db.run("DELETE FROM cats;", (result, err) => { + if (err) { + return reject(err); + } + resolve(result); + }); + }); + return c.redirect("/", 302); + } catch (err) { + return c.json({ error: "Failed to clear cats" }, 500); + } +}); + +function getPort() { + const port = parseInt(process.argv[2], 10) || 4000; + + if (isNaN(port)) { + console.error("Invalid port"); + process.exit(1); + } + + return port; +} + +const port = getPort(); +serve({ + fetch: app.fetch, + port: port, +}).on("listening", () => { + console.log(`Server is running on port ${port}`); +}); diff --git a/sample-apps/hono-sqlite3-esm/db.js b/sample-apps/hono-sqlite3-esm/db.js new file mode 100644 index 000000000..80fd1d7ca --- /dev/null +++ b/sample-apps/hono-sqlite3-esm/db.js @@ -0,0 +1,28 @@ +import sqlite3 from "sqlite3"; + +/** @type {sqlite3.Database} */ +let db; + +export async function getDB() { + if (db) { + return db; + } + + db = new sqlite3.Database(":memory:"); + + await new Promise((resolve, reject) => { + db.run( + `CREATE TABLE cats ( + petname TEXT + );`, + (err) => { + if (err) { + return reject(err); + } + resolve(); + } + ); + }); + + return db; +} diff --git a/sample-apps/hono-sqlite3-esm/package-lock.json b/sample-apps/hono-sqlite3-esm/package-lock.json new file mode 100644 index 000000000..90844a14f --- /dev/null +++ b/sample-apps/hono-sqlite3-esm/package-lock.json @@ -0,0 +1,1573 @@ +{ + "name": "hono-sqlite3-esm", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "hono-sqlite3-esm", + "dependencies": { + "@aikidosec/firewall": "file:../../build", + "@hono/node-server": "^1.11.2", + "hono": "^4.4.2", + "sqlite3": "^5.1.7" + } + }, + "../../build": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@aikidosec/firewall": { + "resolved": "../../build", + "link": true + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT", + "optional": true + }, + "node_modules/@hono/node-server": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.13.1.tgz", + "integrity": "sha512-TSxE6cT5RHnawbjnveexVN7H2Dpn1YaLxQrCOLCUwD+hFbqbFsnJBgdWcYtASqtWVjA+Qgi8uqFug39GsHjo5A==", + "license": "MIT", + "engines": { + "node": ">=18.14.1" + }, + "peerDependencies": { + "hono": "^4" + } + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC", + "optional": true + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "license": "MIT", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "license": "ISC", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT", + "optional": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT", + "optional": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC", + "optional": true + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT", + "optional": true + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT", + "optional": true + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT", + "optional": true + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC", + "optional": true + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC", + "optional": true + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC", + "optional": true + }, + "node_modules/hono": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.6.3.tgz", + "integrity": "sha512-0LeEuBNFeSHGqZ9sNVVgZjB1V5fmhkBSB0hZrpqStSMLOWgfLy0dHOvrjbJh0H2khsjet6rbHfWTHY0kpYThKQ==", + "license": "MIT", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC", + "optional": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "optional": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "license": "MIT", + "optional": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "license": "MIT", + "optional": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC", + "optional": true + }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "license": "MIT", + "optional": true + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "license": "ISC", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT", + "optional": true + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abi": { + "version": "3.68.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.68.0.tgz", + "integrity": "sha512-7vbj10trelExNjFSBm5kTvZXXa7pZyKWx9RCKIyqe6I9Ev3IzGpQoqBP3a+cOdxY+pWj6VkP28n/2wWysBHD/A==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "license": "ISC", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT", + "optional": true + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC", + "optional": true + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC", + "optional": true + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "license": "MIT", + "optional": true, + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/sqlite3": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", + "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "optional": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "optional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + } + } +} diff --git a/sample-apps/hono-sqlite3-esm/package.json b/sample-apps/hono-sqlite3-esm/package.json new file mode 100644 index 000000000..cd7c55641 --- /dev/null +++ b/sample-apps/hono-sqlite3-esm/package.json @@ -0,0 +1,13 @@ +{ + "name": "hono-sqlite3-esm", + "type": "module", + "dependencies": { + "@aikidosec/firewall": "file:../../build", + "@hono/node-server": "^1.11.2", + "hono": "^4.4.2", + "sqlite3": "^5.1.7" + }, + "scripts": { + "start": "node --import @aikidosec/firewall/esm app.js" + } +} diff --git a/sample-apps/hono-sqlite3/package-lock.json b/sample-apps/hono-sqlite3/package-lock.json index dadf2a1ed..14ee21416 100644 --- a/sample-apps/hono-sqlite3/package-lock.json +++ b/sample-apps/hono-sqlite3/package-lock.json @@ -16,6 +16,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/hono-xml/package-lock.json b/sample-apps/hono-xml/package-lock.json index 197b77784..152ae26bd 100644 --- a/sample-apps/hono-xml/package-lock.json +++ b/sample-apps/hono-xml/package-lock.json @@ -18,6 +18,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/http2/package-lock.json b/sample-apps/http2/package-lock.json index 0c9de3c3e..4dfbfb2f9 100644 --- a/sample-apps/http2/package-lock.json +++ b/sample-apps/http2/package-lock.json @@ -13,6 +13,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/lambda-mongodb/package-lock.json b/sample-apps/lambda-mongodb/package-lock.json index e901cb424..bd9b4bf85 100644 --- a/sample-apps/lambda-mongodb/package-lock.json +++ b/sample-apps/lambda-mongodb/package-lock.json @@ -16,6 +16,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/micro/package-lock.json b/sample-apps/micro/package-lock.json index 032e0bc96..ac07fae74 100644 --- a/sample-apps/micro/package-lock.json +++ b/sample-apps/micro/package-lock.json @@ -14,6 +14,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/nestjs-sentry/package-lock.json b/sample-apps/nestjs-sentry/package-lock.json index 616d179a5..a5a9bcc34 100644 --- a/sample-apps/nestjs-sentry/package-lock.json +++ b/sample-apps/nestjs-sentry/package-lock.json @@ -46,6 +46,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/nextjs-standalone/package-lock.json b/sample-apps/nextjs-standalone/package-lock.json index 086fb53d2..15020a9a4 100644 --- a/sample-apps/nextjs-standalone/package-lock.json +++ b/sample-apps/nextjs-standalone/package-lock.json @@ -20,6 +20,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/sample-apps/pubsub-mongodb/package-lock.json b/sample-apps/pubsub-mongodb/package-lock.json index 211b6a940..699c49dc0 100644 --- a/sample-apps/pubsub-mongodb/package-lock.json +++ b/sample-apps/pubsub-mongodb/package-lock.json @@ -17,6 +17,74 @@ "name": "@aikidosec/firewall", "version": "0.0.0", "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "engines": { + "node": ">=16" + } + }, + "../../library": { + "name": "@aikidosec/firewall", + "version": "0.0.0", + "extraneous": true, + "license": "AGPL-3.0-or-later", + "dependencies": { + "import-in-the-middle": "^1.11.1" + }, + "devDependencies": { + "@google-cloud/functions-framework": "^3.3.0", + "@google-cloud/pubsub": "^4.3.3", + "@hapi/hapi": "^21.3.10", + "@hono/node-server": "^1.12.2", + "@sinonjs/fake-timers": "^11.2.2", + "@types/aws-lambda": "^8.10.131", + "@types/cookie-parser": "^1.4.6", + "@types/express": "^4.17.21", + "@types/ip": "^1.1.3", + "@types/mysql": "^2.15.25", + "@types/node": "^22.3.0", + "@types/pg": "^8.11.0", + "@types/qs": "^6.9.11", + "@types/shell-quote": "^1.7.5", + "@types/sinonjs__fake-timers": "^8.1.5", + "@types/supertest": "^6.0.2", + "@typescript-eslint/eslint-plugin": "^8.4.0", + "@typescript-eslint/parser": "^8.4.0", + "aws-sdk": "^2.1595.0", + "axios": "^1.7.3", + "better-sqlite3": "^11.2.0", + "bson-objectid": "^2.0.4", + "cookie-parser": "^1.4.6", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "express": "^5.0.0", + "express-async-handler": "^1.2.0", + "fast-xml-parser": "^4.4.0", + "follow-redirects": "^1.15.6", + "graphql": "^16.8.2", + "hono": "^4.4.2", + "mongodb": "^6.3.0", + "mysql": "^2.18.1", + "mysql2": "^3.10.0", + "needle": "^3.3.1", + "node-fetch": "^2", + "percentile": "^1.6.0", + "pg": "^8.11.3", + "prettier": "^3.2.4", + "shell-quote": "^1.8.1", + "shelljs": "^0.8.5", + "sqlite3": "^5.1.7", + "supertest": "^6.3.4", + "tap": "^18.6.1", + "type-fest": "^4.24.0", + "typescript": "^5.3.3", + "undici": "^6.12.0", + "xml-js": "^1.6.11", + "xml2js": "^0.6.2" + }, "engines": { "node": ">=16" } diff --git a/scripts/run-tap.js b/scripts/run-tap.js index cee877b1d..796bdc849 100644 --- a/scripts/run-tap.js +++ b/scripts/run-tap.js @@ -15,7 +15,7 @@ if (major === 22 && minor >= 5) { args += " --node-arg=--experimental-sqlite --node-arg=--no-warnings"; } -execSync(`tap ${args}`, { +execSync(`tap ${args} '!(*node_modules)/**/*.test.ts'`, { stdio: "inherit", env: { ...process.env, AIKIDO_CI: "true" }, });