Docs / Configuration

Configuration

Arcis works out of the box with secure defaults. Every option is tunable when you need it. You only opt out of protection, never in.

Passing config

All configuration goes through a single options object passed to arcis():

app.use(arcis({
  sanitize: true,
  sanitizeXss: true,
  rateLimit: true,
  rateLimitMax: 100,
  rateLimitWindow: 60000,  // ms
  headers: true,
  isDev: process.env.NODE_ENV === 'development',
}));

Sanitization options

OptionDefaultDescription
sanitizetrueMaster switch. Disables all sanitization if false.
sanitizeXsstrueStrip XSS patterns and HTML-encode output.
sanitizeSqltrueStrip SQL injection patterns.
sanitizeNoSqltrueBlock 35 MongoDB operators ($gt, $where, etc.).
sanitizePathtrueStrip path traversal (../, %2e%2e, etc.).
sanitizeCmdtrueStrip command injection patterns.
sanitizeSstitrueStrip SSTI patterns (Jinja2, Twig, ERB, Pug).
sanitizeXxetrueStrip XXE patterns from XML input.
maxInputSize1_000_000Max input size in bytes. Inputs over this are truncated.

Rate limiting

OptionDefaultDescription
rateLimittrueEnable rate limiting.
rateLimitMax100Max requests per window.
rateLimitWindow60000Window in milliseconds.
rateLimitStorememoryStorage: memory, Redis, or custom.
rateLimitSkipFunction (req) => boolean. Return true to skip rate limiting.

Using Redis

import { arcis, RedisStore } from '@arcis/node';
import { createClient } from 'redis';

const redis = createClient();
await redis.connect();

app.use(arcis({
  rateLimitStore: new RedisStore({ client: redis }),
}));

Security headers

OptionDefault
headerstrue
cspstrict policy (see below)
frameOptionsDENY
hstsMaxAge31536000 (1 year)
hstsSubdomainstrue
referrerPolicystrict-origin-when-cross-origin
crossOriginOpenerPolicysame-origin
crossOriginResourcePolicysame-origin
crossOriginEmbedderPolicyrequire-corp

Default CSP:

default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';
img-src 'self' data: https:; font-src 'self'; object-src 'none';
frame-ancestors 'none';

CORS

corsProtection() is opt-in middleware. Pass allowed origins explicitly:

import { corsProtection } from '@arcis/node';

app.use(corsProtection({
  origin: ['https://yourapp.com', 'https://admin.yourapp.com'],
  methods: ['GET', 'POST'],
  credentials: true,
}));

CSRF

import { csrfProtection } from '@arcis/node';

app.use(csrfProtection({
  cookieName: '__Host-csrf',   // __Host- prefix requires Secure + Path=/
  useHostPrefix: true,
  skipCsrf: (req) => req.path.startsWith('/api/webhook/'),
}));

Development mode

In dev, show detailed error info. In production (default), scrub all sensitive info from errors.

app.use(arcis({
  isDev: process.env.NODE_ENV === 'development',
}));