@aikidosec/runtime
Advanced tools
Comparing version 1.5.18 to 1.5.19
@@ -10,2 +10,3 @@ import { ReportingAPI } from "./api/ReportingAPI"; | ||
import { Source } from "./Source"; | ||
import { Users } from "./Users"; | ||
import { Wrapper } from "./Wrapper"; | ||
@@ -29,2 +30,3 @@ export declare class Agent { | ||
private hostnames; | ||
private users; | ||
private serviceConfig; | ||
@@ -67,2 +69,3 @@ private routes; | ||
private heartbeat; | ||
getUsers(): Users; | ||
getConfig(): ServiceConfig; | ||
@@ -69,0 +72,0 @@ private updateServiceConfig; |
@@ -16,2 +16,3 @@ "use strict"; | ||
const ServiceConfig_1 = require("./ServiceConfig"); | ||
const Users_1 = require("./Users"); | ||
const wrapInstalledPackages_1 = require("./wrapInstalledPackages"); | ||
@@ -36,2 +37,3 @@ class Agent { | ||
this.hostnames = new Hostnames_1.Hostnames(200); | ||
this.users = new Users_1.Users(1000); | ||
this.serviceConfig = new ServiceConfig_1.ServiceConfig([], Date.now()); | ||
@@ -105,2 +107,3 @@ this.routes = new Routes_1.Routes(200); | ||
payload: JSON.stringify(payload).substring(0, 4096), | ||
user: request.user, | ||
}, | ||
@@ -134,2 +137,5 @@ request: { | ||
} | ||
getUsers() { | ||
return this.users; | ||
} | ||
getConfig() { | ||
@@ -170,2 +176,3 @@ return this.serviceConfig; | ||
routes: this.routes.asArray(), | ||
users: this.users.asArray(), | ||
}, timeoutInMS); | ||
@@ -172,0 +179,0 @@ this.updateServiceConfig(response); |
@@ -26,2 +26,6 @@ import { Kind } from "../Attack"; | ||
}; | ||
export type User = { | ||
id: string; | ||
name?: string; | ||
}; | ||
export type DetectedAttack = { | ||
@@ -49,2 +53,3 @@ type: "detected_attack"; | ||
metadata: Record<string, string>; | ||
user: User | undefined; | ||
}; | ||
@@ -90,2 +95,9 @@ agent: AgentInfo; | ||
}[]; | ||
users: { | ||
id: string; | ||
name: string | undefined; | ||
lastIpAddress: string | undefined; | ||
firstSeenAt: number; | ||
lastSeenAt: number; | ||
}[]; | ||
agent: AgentInfo; | ||
@@ -92,0 +104,0 @@ time: number; |
import type { ParsedQs } from "qs"; | ||
export type User = { | ||
id: string; | ||
name?: string; | ||
}; | ||
export type Context = { | ||
@@ -12,2 +16,6 @@ url: string | undefined; | ||
attackDetected?: boolean; | ||
user?: { | ||
id: string; | ||
name?: string; | ||
}; | ||
source: string; | ||
@@ -14,0 +22,0 @@ route: string | undefined; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.runWithContext = exports.getContext = void 0; | ||
const async_hooks_1 = require("async_hooks"); | ||
const requestContext = new async_hooks_1.AsyncLocalStorage(); | ||
const ContextStorage_1 = require("./context/ContextStorage"); | ||
/** | ||
@@ -10,3 +9,3 @@ * Get the current request context that is being handled | ||
function getContext() { | ||
return requestContext.getStore(); | ||
return ContextStorage_1.ContextStorage.getStore(); | ||
} | ||
@@ -22,4 +21,21 @@ exports.getContext = getContext; | ||
function runWithContext(context, fn) { | ||
return requestContext.run(context, fn); | ||
const current = ContextStorage_1.ContextStorage.getStore(); | ||
// If there is already a context, we just update it | ||
// In this way we don't lose the `attackDetected` flag | ||
if (current) { | ||
current.url = context.url; | ||
current.method = context.method; | ||
current.query = context.query; | ||
current.headers = context.headers; | ||
current.routeParams = context.routeParams; | ||
current.remoteAddress = context.remoteAddress; | ||
current.body = context.body; | ||
current.cookies = context.cookies; | ||
current.source = context.source; | ||
current.route = context.route; | ||
return fn(); | ||
} | ||
// If there's no context yet, we create a new context and run the function with it | ||
return ContextStorage_1.ContextStorage.run(context, fn); | ||
} | ||
exports.runWithContext = runWithContext; |
@@ -16,2 +16,3 @@ "use strict"; | ||
const FunctionsFramework_1 = require("../sources/FunctionsFramework"); | ||
const HTTPServer_1 = require("../sources/HTTPServer"); | ||
const Lambda_1 = require("../sources/Lambda"); | ||
@@ -86,2 +87,3 @@ const PubSub_1 = require("../sources/PubSub"); | ||
new Path_1.Path(), | ||
new HTTPServer_1.HTTPServer(), | ||
]; | ||
@@ -88,0 +90,0 @@ } |
{ | ||
"name": "@aikidosec/runtime", | ||
"version": "1.5.18", | ||
"version": "1.5.19", | ||
"description": "Aikido runtime protects your application against NoSQL injections and more", | ||
@@ -5,0 +5,0 @@ "repository": "https://github.com/AikidoSec/runtime-node", |
import { Hooks } from "../agent/hooks/Hooks"; | ||
import { Wrapper } from "../agent/Wrapper"; | ||
export declare class Express implements Wrapper { | ||
private addMiddlewareToRoute; | ||
private addMiddlewareToUse; | ||
private wrapRouteArguments; | ||
private wrapUseArguments; | ||
wrap(hooks: Hooks): void; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Express = void 0; | ||
const Context_1 = require("../agent/Context"); | ||
const http_1 = require("http"); | ||
// eslint-disable-next-line max-lines-per-function | ||
function createMiddleware(agent, path) { | ||
// eslint-disable-next-line max-lines-per-function | ||
const middleware = (req, resp, next) => { | ||
var _a, _b; | ||
let route = path; | ||
if (typeof ((_a = req.route) === null || _a === void 0 ? void 0 : _a.path) === "string") { | ||
route = req.route.path; | ||
} | ||
else if (((_b = req.route) === null || _b === void 0 ? void 0 : _b.path) instanceof RegExp) { | ||
route = req.route.path.toString(); | ||
} | ||
if (route) { | ||
agent.onRouteExecute(req.method, route); | ||
} | ||
(0, Context_1.runWithContext)({ | ||
method: req.method, | ||
remoteAddress: req.ip, | ||
body: req.body ? req.body : undefined, | ||
url: req.protocol + "://" + req.get("host") + req.originalUrl, | ||
headers: req.headers, | ||
routeParams: req.params, | ||
query: req.query, | ||
/* c8 ignore next */ | ||
cookies: req.cookies ? req.cookies : {}, | ||
source: "express", | ||
route: route, | ||
}, () => { | ||
try { | ||
// Run the user's middleware | ||
// Regardless of whether the middleware throws an error or not | ||
// We want to count the request | ||
next(); | ||
const wrapRequestHandler_1 = require("./express/wrapRequestHandler"); | ||
class Express { | ||
// Wrap all the functions passed to app.METHOD(...) | ||
// Examples: | ||
// app.METHOD(path, handler) | ||
// app.METHOD(path, middleware, handler) | ||
// app.METHOD(path, middleware, middleware, ..., handler) | ||
wrapRouteArguments(args, agent) { | ||
return args.map((arg, index) => { | ||
// Ignore non-function arguments | ||
if (typeof arg !== "function") { | ||
return arg; | ||
} | ||
finally { | ||
if (!req.__AIKIDO__) { | ||
req.__AIKIDO__ = { | ||
requestCounted: false, | ||
attackDetected: false, | ||
}; | ||
} | ||
if (!req.__AIKIDO__.requestCounted) { | ||
agent.getInspectionStatistics().onRequest(); | ||
req.__AIKIDO__.requestCounted = true; | ||
} | ||
const context = (0, Context_1.getContext)(); | ||
if (context && | ||
context.attackDetected && | ||
!req.__AIKIDO__.attackDetected) { | ||
agent.getInspectionStatistics().onDetectedAttack({ | ||
blocked: agent.shouldBlock(), | ||
}); | ||
req.__AIKIDO__.attackDetected = true; | ||
} | ||
// The last argument is the route handler | ||
const isLast = index === args.length - 1; | ||
if (isLast) { | ||
return (0, wrapRequestHandler_1.wrapRequestHandler)(arg, agent, undefined); | ||
} | ||
// We grab the first path argument and pass it to the middleware | ||
// Because middleware doesn't have a path argument, we need to pass it | ||
let path = undefined; | ||
if (args.length > 0 && typeof args[0] === "string") { | ||
path = args[0]; | ||
} | ||
return (0, wrapRequestHandler_1.wrapRequestHandler)(arg, agent, path); | ||
}); | ||
}; | ||
return middleware; | ||
} | ||
class Express { | ||
// Whenever app.get, app.post, etc. is called, we want to inject our middleware | ||
// So that runWithContext is called for every request | ||
// Whenever a MongoDB query is made, we want to inspect the filter | ||
// And cross-reference it with the user supplied data of the request | ||
// It's important that our middleware should be the last middleware in the chain | ||
// So that we have access to the parsed body, cookies, etc. | ||
// | ||
// app.get("/path", json(), (req, res) => { ... })) | ||
// we will inject our middleware ^ here | ||
// app.get("/path", json(), middleware(), (req, res) => { ... })) | ||
// | ||
// Without having to change the user's code | ||
addMiddlewareToRoute(args, agent) { | ||
const handler = args.pop(); | ||
args.push(createMiddleware(agent, undefined)); | ||
args.push(handler); | ||
return args; | ||
} | ||
addMiddlewareToUse(args, agent) { | ||
if (args.length > 0 && typeof args[0] === "string") { | ||
return [args[0], createMiddleware(agent, args[0]), ...args.slice(1)]; | ||
} | ||
return [createMiddleware(agent, undefined), ...args]; | ||
// Wrap all the functions passed to app.use(...) | ||
// Examples: | ||
// app.use(middleware) | ||
// app.use(middleware, middleware, ...) | ||
// app.use(path, middleware) | ||
// app.use(path, middleware, middleware, ...) | ||
wrapUseArguments(args, agent) { | ||
return args.map((arg) => { | ||
// Ignore non-function arguments | ||
if (typeof arg !== "function") { | ||
return arg; | ||
} | ||
// We grab the first path argument and pass it to the middleware | ||
// Because middleware doesn't have a path argument, we need to pass it | ||
let path = undefined; | ||
if (args.length > 0 && typeof args[0] === "string") { | ||
path = args[0]; | ||
} | ||
return (0, wrapRequestHandler_1.wrapRequestHandler)(arg, agent, path); | ||
}); | ||
} | ||
@@ -96,3 +59,3 @@ wrap(hooks) { | ||
route.modifyArguments(method, (args, subject, agent) => { | ||
return this.addMiddlewareToRoute(args, agent); | ||
return this.wrapRouteArguments(args, agent); | ||
}); | ||
@@ -104,5 +67,5 @@ }); | ||
}) | ||
.modifyArguments("use", (args, subject, agent) => this.addMiddlewareToUse(args, agent)); | ||
.modifyArguments("use", (args, subject, agent) => this.wrapUseArguments(args, agent)); | ||
} | ||
} | ||
exports.Express = Express; |
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
222935
211
5118
14