Configuración

Con vantor-shield/auto, las opciones se leen de vantor.config.json en el directorio de trabajo. Con protect(), se pasan como argumento. onEvent solo funciona con protect().

Opciones

OpciónTipoPor defectoQué hace
modemonitor, block, offmonitorModo general
rulesobjetoModo por regla, por ejemplo { "sql": "block" }. Reglas: sql, command, path, ssrf, input, ratelimit, decoy, leak
licensetextoTu licencia. Se recomienda usar VANTOR_LICENSE
pactlearn, monitor, block u objetoApagadoVer Pacto
decoyobjetoRutas señuelo activaspaths, values, banMinutes. Ver Carnadas
leakobjetoActivamarkers. Ver Fugas
telemetrybooleano u objetotrueEnviar contadores a tu panel. Nunca valores ni direcciones IP
headersbooleano u objetoActivas en blockVer abajo
rateLimitobjeto o falsefalsemax, windowMs (60000) y routes
trustProxynúmero0Proxies delante de la aplicación
ignorePathslistaPrefijos que se saltean por completo, como /health
ssrfAllowHostslistaHosts permitidos aunque los elija el cliente
maxInspectBytesnúmero5 MBMayor cuerpo de texto inspeccionable
logbooleanotrueEscribir eventos en stderr
logInputsbooleanotrueIncluir en los eventos los primeros 40 caracteres del valor
onEventfunciónRecibe cada evento. Si falla, no afecta la petición

headers

headers: {
  csp: {                   // false para no enviarla
    directives: { 'img-src': "'self'" },
    nonce: true,           // agrega un nonce a script-src
    reportOnly: false,
  },
  hstsMaxAge: 15552000,    // 0 para no enviarla
  custom: {
    'X-Frame-Options': 'DENY',
    'Referrer-Policy': null, // null la quita
  },
}

Variables de entorno

VariableQué hace
VANTOR_LICENSETu licencia
VANTOR_MODEmonitor, block u off. Tiene prioridad sobre la configuración
VANTOR_TELEMETRYoff para no enviar nada al panel

Eventos

Cada hallazgo genera un evento, una sola vez por petición:

interface ShieldEvent {
  id: string;
  at: string;              // ISO 8601
  rule: 'sql' | 'command' | 'path' | 'ssrf' | 'input' | 'ratelimit' | 'pact' | 'decoy' | 'leak';
  action: 'monitored' | 'blocked';
  sink: string;            // por ejemplo "pg.query", "supabase.rest" o "fs.readFile"
  source?: string;         // path, query, body, header, cookie, params
  inputLength?: number;
  inputPreview?: string;   // primeros 40 caracteres, salvo logInputs: false
  detail?: string;         // qué se comparó, en pact, decoy y leak
  location?: string;       // primer frame de tu código, cuando se puede obtener
  request: { id: string; method: string; path: string; ip: string };
}

Privacidad: los eventos completos solo van a stderr y a onEvent, en tu servidor. Al panel llegan solo contadores y rutas sin identificadores. inputPreview puede contener datos del usuario. Si tus logs salen de tu control o guardan datos sensibles, usá logInputs: false. La query string nunca se incluye en request.path.

API

protect(options?)

Inicia Vantor. Devuelve { stop() }, que quita todos los hooks. Llamarlo de nuevo solo actualiza las opciones.

guardSql(query, { dialect? })

Revisa una consulta a mano y la devuelve. Lanza VantorBlockedError si encuentra una inyección y el modo es block. dialect puede ser pg, mysql, sqlite o generic (por defecto).

cspNonce()

El nonce de la petición actual. Requiere headers.csp.nonce.

html y escapeHtml(valor)

Escapan valores para HTML:

import { html } from 'vantor-shield';

res.send(html`<p title="${titulo}">${comentario}</p>`);

Sirven para texto y atributos entre comillas. No son seguros dentro de <script>, <style>, ni en atributos que contienen URLs como href.

VantorBlockedError

PropiedadValor
codeVANTOR_BLOCKED
status, statusCode403
ruleLa regla que bloqueó
sinkDónde se bloqueó
app.use((err, req, res, next) => {
  if (err.code === 'VANTOR_BLOCKED') return res.status(403).json({ error: 'Operación no permitida' });
  next(err);
});

Respuestas de Vantor

Cuando responde directamente, sin pasar por tu código:

EstadoCuerpoCuándo
403{"error":"blocked","rule":"...","requestId":"..."}Regla input, o un bloqueo sin manejador de errores
413{"error":"body_not_inspectable",...}Cuerpo imposible de inspeccionar
429{"error":"too_many_requests",...}Rate limit