Cognition: Security Scanner

Real-time HTTP request scanning for SQL injection, XSS, path traversal, and command injection. Ships as Express middleware or a standalone function, with 16 built-in detection patterns.

The Security Scanner checks incoming HTTP requests for common injection attacks using 16 pre-compiled patterns across four threat categories. It works as Express middleware or as a standalone function you call directly. Anything it detects is sent to the Skytells platform, where the AI reviews it alongside your other event data.

The scanner is built for high recall. It casts a wide net and reports anything that looks suspicious, even if some matches turn out to be false positives. Skytells handles contextual refinement server-side, so you don't need complex detection rules in your application.


Enabling and Disabling

The Security Scanner is enabled by default:

// Enabled by default
Cognition.init({
  apiKey: process.env.SKYTELLS_API_KEY!,
  projectId: process.env.SKYTELLS_PROJECT_ID!,
  captureSecurityThreats: true, // default
});

// Disable entirely
Cognition.init({
  apiKey: process.env.SKYTELLS_API_KEY!,
  projectId: process.env.SKYTELLS_PROJECT_ID!,
  captureSecurityThreats: false,
});

When disabled, scanForThreats() always returns false and the middleware factory produces a no-op.


Express / Connect Middleware

The fastest path to protecting HTTP endpoints is the ready-made middleware:

import express from 'express';
import { Cognition, createSecurityMiddleware } from '@skytells/cognition';

const app = express();
const cognition = Cognition.init({
  apiKey: process.env.SKYTELLS_API_KEY!,
  projectId: process.env.SKYTELLS_PROJECT_ID!,
});

// Body parsing must come before security scanning
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Security scanning middleware — report-only by default
app.use(
  createSecurityMiddleware((event) => {
    cognition.captureEvent(event);
  }),
);

What the Middleware Scans

For every incoming request, the middleware scans:

  1. URL query parameters — Each query string value individually
  2. Request headers — All headers except a safe list (see below)
  3. Request body — String values when the body has been parsed (e.g., by express.json())

Safe headers (skipped by the scanner): host, connection, accept, accept-encoding, accept-language, content-length, content-type, x-api-key, x-project-id, authorization

Middleware Behavior

  • Non-blocking — calls next() regardless of whether a threat was detected
  • Threats are reported asynchronously via the event callback
  • Does not block or reject requests — it only observes

Fastify and Koa

The middleware works with any framework that accepts (req, res, next) handlers — Fastify (with middie), Koa (with koa-connect), or plain HTTP servers.

For Fastify, use a preHandler hook and call scanForThreats() directly:

fastify.addHook('preHandler', async (request, reply) => {
  const body = typeof request.body === 'string'
    ? request.body
    : JSON.stringify(request.body ?? '');

  if (body && cognition.scanForThreats(body, {
    method: request.method,
    url: request.url,
    ip: request.ip,
  })) {
    reply.status(403).send({ error: 'Forbidden' });
  }
});

Manual Scanning

Scan any string directly:

const isThreat = cognition.scanForThreats(userInput, {
  method: 'POST',
  url: '/api/search',
  ip: '192.168.1.100',
  source: 'body.query', // Where the input came from
});

if (isThreat) {
  console.warn('Threat detected in user input');
}

The scanner tests the input against all patterns and emits a SecurityEvent for each matching pattern. Returns true if at least one pattern matched.

Parameters

ParameterTypeDescription
inputstringThe string to scan
context.methodstring?HTTP method (e.g., 'POST')
context.urlstring?Request URL
context.ipstring?Client IP address
context.sourcestring?Where the input came from (e.g., 'body.query', 'header.referer')

Blocking Malicious Requests

The middleware is observe-only by default. To block requests on specific routes:

import { SecurityScanner } from '@skytells/cognition';

const scanner = new SecurityScanner((event) => {
  cognition.captureEvent(event);
});

app.use((req, res, next) => {
  const body = req.body;
  if (body && typeof body === 'object') {
    for (const value of Object.values(body)) {
      if (
        typeof value === 'string' &&
        scanner.scan(value, {
          method: req.method,
          url: req.url,
          ip: req.ip,
          source: 'body',
        })
      ) {
        return res.status(400).json({ error: 'Malicious input detected' });
      }
    }
  }
  next();
});

Threat Patterns

The SDK ships with 16 pre-compiled regex patterns across four categories:

SQL Injection

PatternSeverityExample
SQL union-based injectioncritical1 UNION SELECT * FROM users
SQL comment terminationcritical' OR '1'='1
SQL tautologyhighOR 1=1
SQL batch executionhigh; DROP TABLE users

Cross-Site Scripting (XSS)

PatternSeverityExample
Script tag injectionhigh<script>alert(1)</script>
Event handler injectionhighonload="alert(1)"
JavaScript URImediumjavascript:alert(1)
Data URI with scriptmediumdata:text/html,<script>

Path Traversal

PatternSeverityExample
Directory traversalhigh../../etc/passwd
Null byte injectionhighfile.txt%00.jpg
Encoded traversalmedium%2e%2e%2fetc

Command Injection

PatternSeverityExample
Shell command chainingcritical; rm -rf /
Subshell executioncritical$(cat /etc/passwd)
Pipe to shellhigh| bash

Security Event Structure

interface SecurityEvent {
  type: 'security';
  timestamp: number;

  threatType: ThreatType;   // 'sql_injection' | 'xss' | 'path_traversal' | 'command_injection'
  severity: ThreatSeverity; // 'critical' | 'high' | 'medium' | 'low'
  message: string;          // e.g. "SQL union-based injection detected in body.query"

  request?: {
    method: string;         // 'POST'
    url: string;            // '/api/search'
    headers?: Record<string, string>;
    ip?: string;
  };

  pattern?: string;         // Pattern name that matched
  payload?: string;         // Matched input (truncated to 500 chars)
}

Payload truncation: Matched input strings longer than 500 characters are truncated with '...' appended. This prevents oversized events from consuming excess bandwidth while preserving enough context for analysis.


Custom Patterns

Extend the built-in patterns with your own:

import { SecurityScanner, type ThreatPattern } from '@skytells/cognition';

const customPatterns: ThreatPattern[] = [
  {
    type: 'auth_anomaly',
    severity: 'high',
    name: 'JWT token in URL',
    pattern: /eyJ[A-Za-z0-9-_]+\.eyJ[A-Za-z0-9-_]+\.[A-Za-z0-9-_]+/,
  },
  {
    type: 'command_injection',
    severity: 'critical',
    name: 'Python eval injection',
    pattern: /\beval\s*\(/i,
  },
];

const scanner = new SecurityScanner(
  (event) => cognition.captureEvent(event),
  customPatterns, // Appended to the 16 built-in patterns
);

Each custom pattern must conform to:

interface ThreatPattern {
  type: ThreatType;       // 'sql_injection' | 'xss' | 'path_traversal' | 'command_injection' | 'auth_anomaly' | 'rate_anomaly'
  severity: ThreatSeverity; // 'critical' | 'high' | 'medium' | 'low'
  name: string;
  pattern: RegExp;
}

Threat Types Reference

type ThreatType =
  | 'sql_injection'
  | 'xss'
  | 'path_traversal'
  | 'command_injection'
  | 'auth_anomaly'    // Reserved for future use
  | 'rate_anomaly';   // Reserved for future use

type ThreatSeverity = 'critical' | 'high' | 'medium' | 'low';

  • ConfigurationcaptureSecurityThreats option
  • Analytics — View security threat events in the Console and CLI
  • Examples — Express server with security middleware, blocking pattern

How is this guide?

On this page