From bcc8facf7bccd2d7666156e2ba7d27c490a0f128 Mon Sep 17 00:00:00 2001 From: Hans Ott Date: Thu, 15 Feb 2024 13:19:43 +0100 Subject: [PATCH] Extract install instructions to separate pages --- README.md | 114 ++++-------------------------------- docs/express.md | 37 ++++++++++++ docs/lambda.md | 43 ++++++++++++++ docs/prototype-pollution.md | 27 +++++++++ 4 files changed, 117 insertions(+), 104 deletions(-) create mode 100644 docs/express.md create mode 100644 docs/lambda.md create mode 100644 docs/prototype-pollution.md diff --git a/README.md b/README.md index 317f3ea79..8ad019209 100644 --- a/README.md +++ b/README.md @@ -30,110 +30,8 @@ Aikido guard for Node.js is compatible with $ npm install @aikidosec/guard ``` -### Express - -At the very beginning of your app.js file, add the following line: - -```js -require('@aikidosec/guard').protect(); -``` - -or ESM import style: - -```js -import { protect } from '@aikidosec/guard'; - -// Needs to be called before any other code -protect(); -``` - -That's it! - -If you need to debug the guard, you can set the `debug` option: - -```js -require('@aikidosec/guard').protect({ debug: true }); -``` - -This will output debug information to the console (e.g. if the agent failed to start, no token was found, ...). - -### AWS Lambda - -At the very beginning of your handler.js file, add the following line: - -```js -const protect = require("@aikidosec/guard").lambda(); -``` - -And then wrap your handler function with the `protect` function: - -```js -exports.handler = protect(async (event, context) => { - // Your handler code -}); -``` - -or ESM import style: - -```js -import { lambda } from '@aikidosec/guard'; - -// Needs to be called before any other code -const protect = lambda(); - -// You can call this at any point in your code -export const handler = protect(async (event, context) => { - // Your handler code -}); -``` - -In order for the RASP to work properly, we need the following event properties to be present: - -* `event.body` -* `event.httpMethod` (optional) -* `event.headers` (optional) - -That's it! - -If you need to debug the guard, you can set the `debug` option: - -```js -const protect = require("@aikidosec/guard").lambda({ debug: true }); -``` - -This will output debug information to the console (e.g. if the agent failed to start, no token was found, ...). - -## Protect against prototype pollution - -Aikido guard can also protect your application against [prototype pollution attacks](https://www.aikido.dev/blog/prevent-prototype-pollution). - -It works by calling [Object.freeze](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) for some built-in JavaScript objects. - -> The `Object.freeze()` method freezes an object. A frozen object can no longer be changed; freezing an object prevents new properties from being added to it, existing properties from being removed, prevents changing the enumerability, configurability, or writability of existing properties, and prevents the values of existing properties from being changed. - -We believe that there are legitimate cases of prototype changes, but they should happen only during the initialization step. Hence, we recommend calling `preventPrototypePollution` when your application is initialised. - -```js -import { protect, preventPrototypePollution } from '@aikidosec/guard'; - -// Before main imports -protect(); - -import express from 'express'; - -// After main imports -preventPrototypePollution(); - -const app = express(); - -app.get("/", (req, res) => { - res.send("Hello, world!"); -}); - -app.listen(3000, () => { - console.log("Server is running on port 3000"); -}); -``` +* For express based apps, follow the [Express](docs/express.md) instructions +* For AWS Lambda, follow the [AWS Lambda](docs/lambda.md) instructions ## Reporting to Aikido @@ -175,6 +73,14 @@ See [Reporting NoSQL injections to Aikido](#reporting-nosql-injections-to-aikido We run a benchmark on every commit to make sure that the guard has a minimal impact on your application's performance. +The bench runs [a simple MongoDB query](benchmarks/mongodb/getUser.js) 100 times for warmup and then 1000 times to measure the average time: + +| Without guard | With guard | Difference in ms | Difference in % | +|---------------|------------|------------------|-----------------| +| 0.2355ms | 0.2575ms | +0.022ms | +8.54% | + +(Using Node.js 18.x and MongoDB 6.3.x, results will vary depending on your hardware) + See [benchmarks](benchmarks) for more information. ## Development diff --git a/docs/express.md b/docs/express.md new file mode 100644 index 000000000..fb7df8e45 --- /dev/null +++ b/docs/express.md @@ -0,0 +1,37 @@ +# Express + +At the very beginning of your app.js file, add the following line: + +```js +const { protect, preventPrototypePollution } = require('@aikidosec/guard'); + +protect(); // <-- Call this before any other code or imports + +const express = require('express'); + +preventPrototypePollution(); // <-- Call this after your main imports + +// ... +``` + +You can read more about `preventPrototypePollution` [here](./prototype-pollution.md). + +or ESM import style: + +```js +import { protect, preventPrototypePollution } from '@aikidosec/guard'; + +// ... +``` + +That's it! Your Express app is now protected by Aikido guard. + +## Debug mode + +If you need to debug the guard, you can set the `debug` option to `true`: + +```js +protect({ debug: true }); +``` + +This will output debug information to the console (e.g. if the agent failed to start, no token was found, unsupported packages, ...). diff --git a/docs/lambda.md b/docs/lambda.md new file mode 100644 index 000000000..3ef0c19ee --- /dev/null +++ b/docs/lambda.md @@ -0,0 +1,43 @@ +# AWS Lambda + +At the very beginning of your handler.js file, add the following line: + +```js +const { lambda, preventPrototypePollution } = require("@aikidosec/guard"); + +const protect = lambda(); // <-- Call this before any other code or imports + +const dependency = require("dependency"); + +preventPrototypePollution(); // <-- Call this after your main imports + +exports.handler = protect(async (event, context) => { + // ... +}); +``` + +You can read more about `preventPrototypePollution` [here](./prototype-pollution.md). + +or ESM import style: + +```js +import { lambda, preventPrototypePollution } from '@aikidosec/guard'; +``` + +In order for the RASP to work properly, we need the following event properties to be present: + +* `event.body` +* `event.httpMethod` (optional) +* `event.headers` (optional) + +That's it! Your AWS Lambda function is now protected by Aikido guard. + +## Debug mode + +If you need to debug the guard, you can set the `debug` option to `true`: + +```js +protect({ debug: true }); +``` + +This will output debug information to the console (e.g. if the agent failed to start, no token was found, unsupported packages, ...). diff --git a/docs/prototype-pollution.md b/docs/prototype-pollution.md new file mode 100644 index 000000000..198a13271 --- /dev/null +++ b/docs/prototype-pollution.md @@ -0,0 +1,27 @@ +# Protect against prototype pollution + +Aikido guard can also protect your application against [prototype pollution attacks](https://www.aikido.dev/blog/prevent-prototype-pollution). + +It works by calling [Object.freeze](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) for some built-in JavaScript objects. + +> The `Object.freeze()` method freezes an object. A frozen object can no longer be changed; freezing an object prevents new properties from being added to it, existing properties from being removed, prevents changing the enumerability, configurability, or writability of existing properties, and prevents the values of existing properties from being changed. + +We believe that there are legitimate cases of prototype changes, but they should happen only during the initialization step. Hence, we recommend calling `preventPrototypePollution` when your application is initialised. + +```js +import { preventPrototypePollution } from '@aikidosec/guard'; + +import express from 'express'; + +preventPrototypePollution(); // <-- Call this after your main imports + +const app = express(); + +app.get("/", (req, res) => { + res.send("Hello, world!"); +}); + +app.listen(3000, () => { + console.log("Server is running on port 3000"); +}); +```