UNPKG

@aikidosec/firewall

Version:

Zen by Aikido is an embedded Application Firewall that autonomously protects Node.js apps against common and critical attacks, provides rate limiting, detects malicious traffic (including bots), and more.

129 lines (128 loc) 5.27 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Express = void 0; const http_1 = require("http"); const wrapRequestHandler_1 = require("./express/wrapRequestHandler"); const wrapExport_1 = require("../agent/hooks/wrapExport"); class Express { wrapArgs(args) { return args.map((arg) => { // Ignore non-function arguments if (typeof arg !== "function") { return arg; } // Ignore error handlers if (arg.length > 3) { return arg; } return (0, wrapRequestHandler_1.wrapRequestHandler)(arg); }); } wrapParamArgs(args) { // Don't check the length of the arguments here // app.param(name, (req, res, next, value) => {...}) return args.map((arg) => { // Ignore non-function arguments if (typeof arg !== "function") { return arg; } return (0, wrapRequestHandler_1.wrapRequestHandler)(arg); }); } wrap(hooks) { const expressMethodNames = http_1.METHODS.map((method) => method.toLowerCase()); hooks .addPackage("express") .withVersion("^4.0.0 || ^5.0.0") .onRequire((exports, pkgInfo) => { // Wrap all the functions passed to app.METHOD(...) // Examples: // app.METHOD(path, handler) // app.METHOD(path, middleware, handler) // app.METHOD(path, middleware, middleware, ..., handler) for (const method of expressMethodNames) { (0, wrapExport_1.wrapExport)(exports.Route.prototype, method, pkgInfo, { kind: undefined, modifyArgs: (args) => this.wrapArgs(args), }); } // Wrap all the functions passed to app.use(...) // app.use(middleware) // app.use(middleware, middleware, ...) // app.use(path, middleware) // app.use(path, middleware, middleware, ...) (0, wrapExport_1.wrapExport)(exports.application, "use", pkgInfo, { kind: undefined, modifyArgs: (args) => this.wrapArgs(args), }); // Wrap the functions passed to app.param(...) // app.param(name, handler) (0, wrapExport_1.wrapExport)(exports.application, "param", pkgInfo, { kind: undefined, modifyArgs: (args) => this.wrapParamArgs(args), }); }) .addFileInstrumentation({ path: "lib/application.js", functions: [ { nodeType: "FunctionAssignment", name: "app.use", modifyArgumentsObject: true, operationKind: undefined, modifyArgs: (args) => this.wrapArgs(args), }, { nodeType: "FunctionAssignment", name: "app.param", modifyArgumentsObject: false, operationKind: undefined, modifyArgs: (args) => this.wrapParamArgs(args), }, ], }) // v5 moved the router into a separate "router" npm package. // We grab Router from lib/express.js (not from "router" directly, // since that package can be used without express). // Router.Route exists in v5 but not in v4 — see below for v4. .addFileInstrumentation({ path: "lib/express.js", functions: [], accessLocalVariables: { names: ["Router"], cb: (vars, pkgInfo) => { if (vars.length > 0 && vars[0] && vars[0].Route) { const router = vars[0]; for (const method of expressMethodNames) { (0, wrapExport_1.wrapExport)(router.Route.prototype, method, pkgInfo, { kind: undefined, modifyArgs: (args) => this.wrapArgs(args), }); } } }, }, }) // v4 has its own lib/router/route.js where Route is a local variable. // This file doesn't exist in v5, so this is a no-op there. .addFileInstrumentation({ path: "lib/router/route.js", functions: [], accessLocalVariables: { names: ["Route"], cb: (vars, pkgInfo) => { if (vars.length > 0 && typeof vars[0] === "function") { const Route = vars[0]; for (const method of expressMethodNames) { (0, wrapExport_1.wrapExport)(Route.prototype, method, pkgInfo, { kind: undefined, modifyArgs: (args) => this.wrapArgs(args), }); } } }, }, }); } } exports.Express = Express;