NestJS

Add Nyoxis threat detection to a NestJS application using a guard that calls /v0/predict before each request is handled.

Prerequisites

  • Node.js 18 or later
  • NestJS 10 or later
  • A Nyoxis workspace API key — get one here

No extra install required

NestJS ships with @nestjs/axios (wraps axios). You can also use the native fetch API available in Node.js 18+, which this guide uses to keep dependencies minimal.

Guard

Create src/guards/nyoxis.guard.ts:

typescript
import { CanActivate, ExecutionContext, Injectable, Logger, } from "@nestjs/common"; import { Request, Response } from "express"; const NYO_API = "https://api.nyoxis.com"; @Injectable() export class NyoxisGuard implements CanActivate { private readonly logger = new Logger(NyoxisGuard.name); constructor( private readonly apiKey: string, private readonly options: { blockOnHigh?: boolean; onError?: "open" | "closed"; } = {}, ) {} async canActivate(context: ExecutionContext): Promise<boolean> { const req = context.switchToHttp().getRequest<Request>(); const res = context.switchToHttp().getResponse<Response>(); const payload = { method: req.method, path: req.path, query: Object.keys(req.query).length ? new URLSearchParams(req.query as Record<string, string>).toString() : undefined, headers: req.headers as Record<string, string>, ip_addr: req.ip, body: typeof req.body === "string" ? req.body : req.body ? JSON.stringify(req.body) : undefined, }; try { const response = await fetch( `${NYO_API}/v0/predict?api_key=${this.apiKey}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload), signal: AbortSignal.timeout(3000), }, ); const verdict = await response.json(); // Attach verdict to request for controller access (req as any).nyoxis = verdict; if (this.options.blockOnHigh && verdict.prediction?.risk === "high") { res.status(403).json({ error: "Forbidden" }); return false; } return true; } catch (err) { this.logger.warn(`Prediction error: ${(err as Error).message}`); if (this.options.onError === "closed") { res.status(503).json({ error: "Service unavailable" }); return false; } // Fail open return true; } } }

Register globally

typescript
// src/main.ts import { NestFactory } from "@nestjs/core"; import { AppModule } from "./app.module"; import { NyoxisGuard } from "./guards/nyoxis.guard"; async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalGuards( new NyoxisGuard(process.env.NYOXIS_API_KEY!, { blockOnHigh: true }), ); await app.listen(3000); } bootstrap();

Alternatively, apply per-controller or per-route:

typescript
// src/app.controller.ts import { Controller, Get, Req, UseGuards } from "@nestjs/common"; import { NyoxisGuard } from "./guards/nyoxis.guard"; import { Request } from "express"; @Controller() @UseGuards(new NyoxisGuard(process.env.NYOXIS_API_KEY!)) export class AppController { @Get() getRoot(@Req() req: Request) { const risk = (req as any).nyoxis?.prediction?.risk ?? "unknown"; return { ok: true, risk }; } }

Acting on the verdict

typescript
import { Get, Req, ForbiddenException } from "@nestjs/common"; import { Request } from "express"; @Get("sensitive") getSensitive(@Req() req: Request) { const verdict = (req as any).nyoxis ?? {}; const prediction = verdict.prediction ?? {}; if (["medium", "high"].includes(prediction.risk)) { throw new ForbiddenException("Blocked by WAF"); } const sqli = prediction.attacks?.find( (a: { kind: string; confidence: number }) => a.kind === "sql_injection" && a.confidence > 0.8, ); if (sqli) { console.warn("[security] SQL injection detected", { path: req.path, ip: req.ip, }); } return { data: "sensitive content" }; }

Next steps

  • API Reference — complete field descriptions and status codes.
  • Overview — how the classifier and redaction pipeline work.

Cookie preferences

Nyoxis uses essential cookies for authentication and session security. We only enable Analytics after you consent. See our Cookie Policy for details.