Skip to content

Security

Tomas Pflanzer edited this page Feb 27, 2026 · 1 revision

Security

Sandcastle is designed for production deployment. Security is built into every layer - from credential storage to sandbox isolation to API access control.

Credential encryption

Module: src/sandcastle/engine/crypto.py

All tool credentials (API keys, tokens, passwords) are encrypted at rest using Fernet symmetric encryption (AES-128-CBC + HMAC-SHA256).

  • Config: Set CREDENTIAL_ENCRYPTION_KEY in .env to enable
  • Graceful fallback: Without the key, credentials are stored in plaintext (with a startup warning)
  • Encryption scope: All 56 tool connection credentials in the database

API authentication

Module: src/sandcastle/api/auth.py

  • HMAC-SHA256 key hashing with server-side pepper (API_KEY_PEPPER)
  • Keys accepted via X-API-Key header or Authorization: Bearer header
  • Public paths excluded: /api/health, /api/docs, /api/templates, /api/agui
  • Admin guard: only admin-flagged keys can create new API keys

API key lifecycle

Rotation

POST /api/api-keys/{id}/rotate
  • Generates new key, old key enters grace period
  • KEY_ROTATION_GRACE_HOURS (default: 24) - both old and new key work during grace
  • After grace period, old key returns 401

Expiry

  • Optional expires_at on key creation
  • Auth middleware checks expiry on every request
  • Expired keys return 401 KEY_EXPIRED with clear error message

IP allowlisting

PUT /api/api-keys/{id}/allowlist
  • Per-key CIDR allowlist (IPv4 + IPv6)
  • Uses Python ipaddress stdlib for validation
  • Empty allowlist = allow all (default)

Rate limiting

Module: src/sandcastle/api/rate_limit.py

Pluggable backend with RateLimitBackend protocol:

Backend Use case Method
InMemoryBackend Single process (default) Sliding window counter
RedisBackend Distributed / multi-process Sorted set with TTL
  • Async check() method
  • Auto-selects Redis backend when REDIS_URL is configured
  • Per-tenant/per-IP tracking

Security headers

Module: src/sandcastle/api/security_headers.py

Applied to all responses:

Header Value
X-Content-Type-Options nosniff
X-Frame-Options DENY
Referrer-Policy strict-origin-when-cross-origin
Permissions-Policy camera=(), microphone=(), geolocation=(), payment=()
Content-Security-Policy Applied on dashboard paths (configurable)

CSP can run in report-only mode via CSP_REPORT_ONLY=true.

Sandbox isolation

Docker backend

Config file: src/sandcastle/engine/seccomp-default.json

When using the Docker sandbox backend:

  • CapDrop ALL - No Linux capabilities
  • Seccomp profile - Restricted syscall whitelist
  • PidsLimit - Configurable process limit (DOCKER_PIDS_LIMIT)
  • CPU quotas - DOCKER_CPU_PERIOD + DOCKER_CPU_QUOTA
  • Custom seccomp - Override via DOCKER_SECCOMP_PROFILE path

E2B backend

  • Full VM-level isolation via E2B cloud
  • Each execution runs in a fresh sandbox
  • Network isolation between sandboxes

Cloudflare backend

  • V8 isolate per execution
  • Edge-level isolation

SSRF prevention

The executor validates URLs in HTTP steps and sandbox network requests to prevent server-side request forgery against internal infrastructure.

Path traversal protection

Runner scripts validate file paths to prevent directory traversal attacks that could escape the sandbox boundary.

CORS

Wildcard CORS filtering - configurable allowed origins. Default allows localhost for development.

License system

Module: src/sandcastle/engine/license.py

Ed25519 asymmetric signature verification:

  • Private key stays with the issuer (never in source)
  • Public key embedded in source for offline verification
  • No phone-home or online validation
  • Three tiers: Community (free), Pro, Enterprise
  • No features are blocked - license is a legal/compliance signal only

Key format: sc_lic_<base64url_payload>.<base64url_signature>

Telemetry safety

Module: src/sandcastle/engine/telemetry.py

Sensitive environment variables are explicitly excluded from any telemetry:

  • LICENSE_KEY
  • API_KEY_PEPPER
  • CREDENTIAL_ENCRYPTION_KEY
  • All provider API keys (Anthropic, OpenAI, etc.)

Security configuration checklist

For production deployments:

# Required
AUTH_REQUIRED=true
API_KEY_PEPPER=<random-32-byte-hex>
CREDENTIAL_ENCRYPTION_KEY=<fernet-key>

# Recommended
SANDBOX_BACKEND=e2b          # or docker with seccomp
KEY_ROTATION_GRACE_HOURS=24
CSP_REPORT_ONLY=false

# Optional
REDIS_URL=redis://...        # For distributed rate limiting
LICENSE_KEY=sc_lic_...        # For compliance

Clone this wiki locally