Inside-the-app security middleware for Python. One install protects FastAPI, Flask, and Django against XSS, SQL injection, CSRF, SSRF, HPP, prompt injection, bot traffic, rate limiting, and 20+ more attack types. Includes prompt-injection signature library, LLM token-budget middleware, and a 646-pattern bot corpus with consistent API across the Node and Go SDKs. The CLI ships separately at npm install -g @arcis/cli.
Project description
Arcis Python
One-line security middleware for Python web applications. Zero runtime dependencies.
Arcis is a cross-platform security library that provides drop-in protection against common web vulnerabilities. Part of the Arcis ecosystem with implementations for Node.js, Python, and Go.
1,219+ tests passing.
What's new in v1.5.0
- SDK-only release.
pip install arcisships the runtime middleware with zero runtime dependencies. The CLI moved to its own package:npm install -g @arcis/cli. - Litestar adapter (
arcis.litestar.ArcisMiddleware) — pure-ASGI, type-onlylitestarimport. Composes with Litestar viaDefineMiddlewareand with any other ASGI host (Starlette, Quart, Hypercorn) via direct instantiation. verify_email_mx_async— async-safe MX verification. The syncverify_email_mxwas the one user-facing call that blocked the event loop on FastAPI handlers; the async variant usesdns.asyncresolvernatively (or threads toasyncio.to_threadas fallback).- AI-era protections: 28-signature prompt-injection library, per-key
tokenBudgetmiddleware, 646-pattern bot corpus,GuardsAPI for non-HTTP contexts. - Composite helpers:
signup_protection(rate-limit + bot + email-MX) — full recipe for protecting account creation. - The middleware API is unchanged. Existing
Arcis(app)/app.add_middleware(ArcisMiddleware, ...)code keeps working. - See the full release history at gagancm.github.io/arcis/changelog.html.
Installation
# Core middleware (zero runtime deps)
pip install arcis python-dotenv
# With framework integrations
pip install arcis[flask]
pip install arcis[fastapi]
pip install arcis[django]
# All frameworks + dev tools
pip install arcis[dev]
Install in your backend project, not the frontend. Arcis is server-side middleware. Bundling it into a frontend build would leak the API key into client JS and the middleware never runs there.
.envlives next to your server entry point. AddARCIS_KEY=...,ARCIS_WORKSPACE_ID=...,ARCIS_ENDPOINT=...and callload_dotenv()at startup. Add.envto.gitignore.
CLI
The Arcis scanner (arcis audit, arcis scan, arcis sca) is now a standalone native binary distributed via npm:
npm install -g @arcis/cli
arcis --help
This works regardless of whether your app is Node, Python, or Go. The CLI is a single static binary with the threat database embedded. No Python required.
If you previously relied on pip install arcis shipping the arcis command, switch to the npm install above.
Quick Start
Flask
from flask import Flask
from arcis import Arcis
from dotenv import load_dotenv
load_dotenv()
app = Flask(__name__)
Arcis(app, block=True) # block=True returns 403 on detected attacks.
@app.route('/')
def hello():
return 'Hello, World!'
FastAPI
from fastapi import FastAPI
from arcis.fastapi import ArcisMiddleware
from dotenv import load_dotenv
load_dotenv()
app = FastAPI()
# block=True returns 403 on detected attacks. Default is False
# (sanitize + observe) so existing apps don't break on rollout.
app.add_middleware(ArcisMiddleware, block=True)
@app.get('/')
async def hello():
return {'message': 'Hello, World!'}
Django
# settings.py
MIDDLEWARE = [
'arcis.django.ArcisMiddleware',
# ... other middleware
]
# Optional configuration
ARCIS_CONFIG = {
'rate_limit_max': 100,
'rate_limit_window_ms': 60000,
'sanitize_xss': True,
'sanitize_sql': True,
}
Features
Input Sanitization
Automatically sanitize user input to prevent:
- XSS (Cross-Site Scripting)
- SQL Injection
- NoSQL Injection (MongoDB operators)
- Path Traversal (
../attacks) - Prototype Pollution (
__proto__,constructor) - HTTP Header Injection (CRLF, response splitting)
- SSRF (private IPs, cloud metadata, dangerous protocols)
- Open Redirect (absolute URLs,
javascript:, protocol-relative)
from arcis import sanitize_string, sanitize_dict
# Sanitize a string
clean = sanitize_string("<script>alert('xss')</script>")
# Result: "<script>alert('xss')</script>"
# Sanitize a dictionary (including nested objects)
data = {"name": "<script>xss</script>", "$gt": ""}
clean = sanitize_dict(data)
# Result: {"name": "<script>..."} ($gt key removed)
Rate Limiting
Protect against brute force and DDoS attacks with fixed window, sliding window, or token bucket:
from arcis import RateLimiter
from arcis.middleware import SlidingWindowLimiter, TokenBucketLimiter
# Fixed window
limiter = RateLimiter(max_requests=100, window_ms=60000)
# Sliding window — smoother rate enforcement
sliding = SlidingWindowLimiter(max_requests=100, window_ms=60000)
# Token bucket — burst-friendly
bucket = TokenBucketLimiter(capacity=100, refill_rate=10) # 10 tokens/sec
Bot Detection
Detect and categorize bots with 80+ patterns across 7 categories:
from arcis.middleware import BotDetector
detector = BotDetector()
result = detector.detect(user_agent, request_headers)
# result.is_bot, result.category, result.confidence
CSRF Protection
Double-submit cookie pattern with token generation and validation:
from arcis.middleware import CsrfProtection
csrf = CsrfProtection(secret="your-secret-key")
Security Headers
Automatically add security headers to all responses:
Content-Security-PolicyX-Content-Type-Options: nosniffX-Frame-Options: DENYStrict-Transport-SecurityX-XSS-Protection: 0
Input Validation
from arcis import Validator, validate_email, validate_url
# Quick validation
if validate_email(user_input):
print("Valid email!")
# Full validator
assert Validator.email("test@example.com") # True
assert Validator.url("https://example.com") # True
assert Validator.uuid("550e8400-e29b-41d4-a716-446655440000") # True
assert Validator.length("hello", min_len=3, max_len=10) # True
Safe Logging
Log safely without exposing secrets:
from arcis import SafeLogger
logger = SafeLogger()
# Automatically redacts sensitive fields
logger.info("User login", {"email": "user@test.com", "password": "secret"})
# Output: {"email": "user@test.com", "password": "[REDACTED]"}
# Prevents log injection (removes newlines/control characters)
logger.info("User: attacker\nAdmin: true") # Newlines stripped
Configuration
All frameworks support the same configuration options:
# Flask
Arcis(
app,
sanitize=True,
sanitize_xss=True,
sanitize_sql=True,
sanitize_nosql=True,
sanitize_path=True,
rate_limit=True,
rate_limit_max=100,
rate_limit_window_ms=60000,
headers=True,
csp="default-src 'self'",
)
# FastAPI
app.add_middleware(
ArcisMiddleware,
rate_limit_max=50,
sanitize_sql=False,
)
# Django (settings.py)
ARCIS_CONFIG = {
'rate_limit_max': 50,
'sanitize_sql': False,
}
Standalone Middleware (Django)
Use individual components if you only need specific protection:
MIDDLEWARE = [
'arcis.django.ArcisSanitizeMiddleware', # Only sanitization
'arcis.django.ArcisRateLimitMiddleware', # Only rate limiting
'arcis.django.ArcisHeadersMiddleware', # Only security headers
]
Testing
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
pytest tests/ -v
# With coverage
pytest tests/ --cov=arcis --cov-report=html
API Reference
Core Classes
| Class | Description |
|---|---|
Arcis |
Main class - configures all protections |
Sanitizer |
Input sanitization |
RateLimiter |
Fixed window rate limiting |
SlidingWindowLimiter |
Sliding window rate limiting |
TokenBucketLimiter |
Token bucket rate limiting |
BotDetector |
Bot detection with 80+ patterns |
CsrfProtection |
CSRF double-submit cookie protection |
SecurityHeaders |
Security headers |
Validator |
Input validation |
SafeLogger |
Safe logging with redaction |
Exceptions
| Exception | Description |
|---|---|
RateLimitExceeded |
Raised when rate limit is exceeded |
ValidationError |
Raised when validation fails |
Convenience Functions
| Function | Description |
|---|---|
sanitize_string(value) |
Sanitize a single string |
sanitize_dict(data) |
Sanitize a dictionary |
sanitize_xss(value) |
XSS sanitization only |
sanitize_sql(value) |
SQL injection sanitization only |
sanitize_nosql(data) |
NoSQL injection sanitization only |
sanitize_path(value) |
Path traversal sanitization only |
validate_email(value) |
Email validation with disposable blocklist, typo suggestions, MX verify |
validate_url(value) |
Validate URL format |
validate_url_ssrf(value) |
URL validation with SSRF protection |
validate_redirect(value) |
Open redirect prevention |
validate_uuid(value) |
Validate UUID format |
Utilities
| Function | Description |
|---|---|
parse_duration(value) |
Parse duration strings ("5m", "1h") to milliseconds |
get_client_ip(request) |
Platform-aware IP detection (proxy headers, etc.) |
fingerprint_request(request) |
Generate request fingerprint for tracking |
License
MIT License - see LICENSE file for details.
Contributing
- Fork the repo and create your branch from
nwl(the active development branch) - All PRs target
nwl—mainis release-only - All changes must pass existing tests
- New features require test cases aligned with
spec/TEST_VECTORS.json
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file arcis-1.5.2.tar.gz.
File metadata
- Download URL: arcis-1.5.2.tar.gz
- Upload date:
- Size: 164.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d9010e0f5f883c37094f50a1fd0c27dc2ab8af0c6ba8c2f54cd26afa8a755042
|
|
| MD5 |
02fbaf72aac214a2a47799335e229c9b
|
|
| BLAKE2b-256 |
cc76e303f9fd4765312a81ce5a5f4a4410670d7e3b1221ba89923a804c87bb9a
|
File details
Details for the file arcis-1.5.2-py3-none-any.whl.
File metadata
- Download URL: arcis-1.5.2-py3-none-any.whl
- Upload date:
- Size: 179.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
562971568da9728acf05e54f98c8e156cc33edb41f9cfcf590c7db9509191b88
|
|
| MD5 |
24faa3d3a7aa6720a3619bc75376d1cb
|
|
| BLAKE2b-256 |
01ea46352438c0fd6b12e9ce4a77be796114336fbc95e8c86bfb030adc04bc05
|