Docs / Getting Started

Getting Started

Install Arcis, add one line of code, and your application is protected against 20+ attack types. No configuration required.

Requirements

Installation

Install the package for your language. Arcis has zero runtime dependencies beyond the framework you're already using.

Install in your backend project, not the frontend. Arcis is server-side middleware. For separated stacks (Next.js + Express, React + FastAPI, etc.), install it in the server folder where your routes are defined. A frontend bundle would leak the API key into client JS and the middleware never runs there.

npm install @arcis/node dotenv

Or with yarn:

yarn add @arcis/node dotenv

dotenv loads .env at startup. Vanilla Express does not pick it up automatically.

pip install arcis python-dotenv

For Redis store support:

pip install "arcis[redis]"

python-dotenv loads .env at startup. Vanilla FastAPI / Flask do not pick it up automatically.

go get github.com/GagancM/arcis

CLI tools (audit / scan / sca)

The Arcis CLI scanners ship as a single static binary distributed via npm. The binary works regardless of whether your app is Node, Python, or Go:

npm install -g @arcis/cli

The threat database, audit rules, and attack payload catalog are all embedded in the binary. No Python or other runtime required. (Before v1.5.0 the CLI shipped inside the Python SDK; that's no longer the case.)

Environment variables (.env)

The dashboard expects three values in your backend .env:

ARCIS_KEY=ak_live_...
ARCIS_WORKSPACE_ID=your-workspace
ARCIS_ENDPOINT=https://your-dashboard.example.com

Never prefix these with NEXT_PUBLIC_, VITE_, or REACT_APP_. Those frameworks bundle prefixed env vars into client JS, which would leak your ARCIS_KEY to anyone viewing your site source. The .env belongs next to your server entry point (package.json, main.py, main.go), and should be listed in .gitignore.

Basic setup

Pick your framework. Each setup is one install plus one middleware line. The core middleware activates sanitization, rate limiting, and security headers with secure defaults.

// Install: npm install @arcis/node dotenv
import express from 'express';
import { arcis } from '@arcis/node';
import 'dotenv/config';

const app = express();
app.use(express.json());
app.use(arcis({ block: true }));

app.get('/', (req, res) => res.json({ ok: true }));
app.listen(3000);
// Install: npm install @arcis/node
// app.module.ts
import { Module, MiddlewareConsumer, NestModule } from '@nestjs/common';
import { ArcisModule, ArcisMiddleware } from '@arcis/node/nestjs';

@Module({ imports: [ArcisModule.forRoot({ block: true })] })
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(ArcisMiddleware).forRoutes('*');
  }
}
// Install: npm install @arcis/node
// src/hooks.server.ts
import { arcisHandle } from '@arcis/node/sveltekit';

export const handle = arcisHandle({
  rateLimit: { max: 100 },
  bot: true,
});
// Install: npm install @arcis/node
// src/middleware.ts
import { onRequest as arcisOnRequest } from '@arcis/node/astro';

export const onRequest = arcisOnRequest({
  rateLimit: { max: 100 },
  bot: true,
});
// Install: npm install @arcis/node
// server/middleware/arcis.ts
import { defineEventHandler } from 'h3';
import { arcisHandler } from '@arcis/node/nuxt';

export default defineEventHandler(arcisHandler({
  rateLimit: { max: 100 },
}));
// Install: bun add @arcis/node hono
import { Hono } from 'hono';
import { arcisHono } from '@arcis/node/bun';

const app = new Hono();
app.use(arcisHono({ rateLimit: { max: 100 } }));
app.get('/', (c) => c.json({ ok: true }));

export default app;
# Install: pip install arcis python-dotenv
from fastapi import FastAPI
from arcis import ArcisMiddleware
from dotenv import load_dotenv

load_dotenv()
app = FastAPI()
app.add_middleware(ArcisMiddleware, block=True)

@app.get("/")
def root():
    return {"ok": True}
# Install: pip install arcis
from flask import Flask
from arcis import Arcis

app = Flask(__name__)
Arcis(app)  # core protections enabled

@app.route("/")
def root():
    return {"ok": True}
# Install: pip install arcis
# settings.py
MIDDLEWARE = [
    # Place Arcis early so it sees the request before your views.
    'arcis.django.ArcisMiddleware',
    # ... your other middleware
]
// Install: go get github.com/GagancM/arcis
package main

import (
    "github.com/gin-gonic/gin"
    arcisgin "github.com/GagancM/arcis/gin"
)

func main() {
    r := gin.Default()
    r.Use(arcisgin.Middleware())
    r.GET("/", func(c *gin.Context) {
        c.JSON(200, gin.H{"ok": true})
    })
    r.Run()
}
// Install: go get github.com/GagancM/arcis
package main

import (
    "github.com/labstack/echo/v4"
    arcisecho "github.com/GagancM/arcis/echo"
)

func main() {
    e := echo.New()
    e.Use(arcisecho.Middleware())
    e.GET("/", func(c echo.Context) error {
        return c.JSON(200, map[string]any{"ok": true})
    })
    e.Logger.Fatal(e.Start(":3000"))
}
// Install: go get github.com/GagancM/arcis
package main

import (
    "net/http"
    "github.com/GagancM/arcis/middleware"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte(`{"ok":true}`))
    })
    handler := middleware.Sanitize()(mux)
    http.ListenAndServe(":3000", handler)
}

That's it. Your app is now protected against XSS, SQL injection, path traversal, command injection, and 16+ more attack types. Safe input passes through. Attack payloads are stripped.

What's enabled by default

When you call arcis() with no options, the following protections are active:

ProtectionDefault behavior
Input sanitizationXSS, SQL, NoSQL, command, path traversal, SSTI, XXE, JSONP, header injection, prototype pollution
Rate limiting100 requests per 60 seconds, per IP (fixed window)
Security headersCSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, COOP, CORP, COEP (16 headers)
Error scrubbingStack traces, DB errors, internal IPs removed from responses in production

Opt-in middleware

These are powerful but context-dependent. Add them explicitly when you need them.

import {
  arcis,
  corsProtection,
  csrfProtection,
  botProtection,
  cookieSecurity,
} from '@arcis/node';

app.use(arcis());

app.use(corsProtection({ origin: ['https://yourapp.com'] }));
app.use(csrfProtection());
app.use(botProtection());
app.use(cookieSecurity());

Verify it's working

Send a request with an attack payload to any route. Arcis strips it before your code runs.

# Try an XSS attack
curl 'http://localhost:3000/?q=<script>alert(1)</script>'

# Your handler receives req.query.q === ''  (empty. script was stripped)

To see what Arcis blocks, log req.query inside your route. the attack payload will be gone.

Next steps