NestJS Express

NestJS Express

BotBye! anti-phishing integration for NestJS with Express applications.

Install

1
npm i @botbye/nest-express
1
yarn add @botbye/nest-express

Requires @nestjs/common >= 10 and express >= 4 as peer dependencies.

Configuration

Register BotByePhishingModule once in your root module. Anti-phishing is identified by its own clientKey (available in your Phishing Project in the Dashboard), not the server key used by evaluate, so it is registered separately from BotByeModule.

1
2
3
4
5
6
7
8
9
10
11
12
import { Module } from "@nestjs/common";
import { BotByePhishingModule } from "@botbye/nest-express";

@Module({
  imports: [
    BotByePhishingModule.register({
      // clientKey from your Phishing Project in the Dashboard
      clientKey: "00000000-0000-0000-0000-000000000000",
    }),
  ],
})
export class AppModule {}

register options

Option Type Required Description
clientKey string Yes clientKey from your Phishing Project on the Admin Dashboard
url string No Override BotBye API endpoint (default: https://verify.botbye.com)
logger.level `"error" "warn" "info" "debug" "log"` No Log level (default: "info")
logger.logger TLogger No Custom logger instance implementing { error, warn, info, debug, log }
timeouts.fetchCatcher number No Timeout in milliseconds for each fetchCatcher call

Usage

Anti-phishing needs two routes on your own origin, each proxied through fetchCatcher:

SVG route — serves the SVG catcher. This is the URL your client code passes to getCatcher({ url }).

PNG route — serves the PNG that the SVG references (via innerPngUrl).

After registering BotByePhishingModule, inject TBotByePhishingService using BOTBYE_PHISHING_SERVICE_DI_TOKEN and call fetchCatcher from a controller. Pass the Express request as request and the format. For the SVG, innerPngUrl must be the absolute URL of your PNG route — the browser loads that PNG directly from your origin.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { Controller, Get, Inject, Req, Res } from "@nestjs/common";
import { Request, Response } from "express";
import { BOTBYE_PHISHING_SERVICE_DI_TOKEN, TBotByePhishingService } from "@botbye/nest-express";

// Absolute URL of your PNG endpoint — the SVG catcher references it through innerPngUrl.
const PNG_CATCHER_URL = "https://your-site.example/botbye-catcher.png";

@Controller()
export class PhishingCatcherController {
  constructor(
    @Inject(BOTBYE_PHISHING_SERVICE_DI_TOKEN) private readonly phishing: TBotByePhishingService
  ) {}

  // SVG catcher (this URL goes into the catcher element on your pages)
  @Get("/botbye-catcher.svg")
  async svg(@Req() request: Request, @Res() res: Response) {
    const catcher = await this.phishing.fetchCatcher({
      request,
      format: "svg",
      innerPngUrl: PNG_CATCHER_URL,
    });

    res.status(catcher.status).set(catcher.headers).send(Buffer.from(catcher.body));
  }

  // Companion PNG the SVG above references via innerPngUrl
  @Get("/botbye-catcher.png")
  async png(@Req() request: Request, @Res() res: Response) {
    const catcher = await this.phishing.fetchCatcher({ request, format: "png" });

    res.status(catcher.status).set(catcher.headers).send(Buffer.from(catcher.body));
  }
}

We recommend embedding the SVG catcher: it is designed to keep tracking even when a phishing site copies all of your assets to its own infrastructure (the PNG route exists because the SVG catcher relies on it).