Skip to content

Security OverviewΒΆ

Cello is built with security as a core principle. All security features are implemented in Rust with constant-time operations to prevent timing attacks.

Security FeaturesΒΆ

  • Authentication


    JWT, Basic Auth, API Key authentication with constant-time validation

    Authentication

  • Authorization (Guards)


    Role-based access control with composable guards

    Guards

  • JWT


    JSON Web Token authentication and validation

    JWT

  • Sessions


    Secure cookie-based session management

    Sessions

  • CSRF Protection


    Cross-Site Request Forgery protection

    CSRF

  • Security Headers


    CSP, HSTS, X-Frame-Options, and more

    Headers


Quick SetupΒΆ

Enable comprehensive security with a few lines:

from cello import App
from cello.middleware import (
    JwtConfig, JwtAuth,
    SecurityHeadersConfig,
    SessionConfig,
    CsrfConfig
)

app = App()

# Enable security headers (CSP, HSTS, etc.)
app.enable_security_headers()

# Enable CSRF protection
app.enable_csrf()

# Enable rate limiting
app.enable_rate_limit(requests=100, window=60)

# Configure JWT authentication
jwt_config = JwtConfig(
    secret=b"your-secret-key-minimum-32-bytes-long",
    algorithm="HS256",
    expiration=3600  # 1 hour
)
app.use(JwtAuth(jwt_config).skip_path("/public"))

Security PrinciplesΒΆ

1. Constant-Time OperationsΒΆ

All security-sensitive comparisons use constant-time algorithms:

// Rust implementation using subtle crate
use subtle::ConstantTimeEq;

fn verify_token(provided: &[u8], expected: &[u8]) -> bool {
    provided.ct_eq(expected).into()
}

This prevents timing attacks where attackers measure response times to guess secrets.

2. Defense in DepthΒΆ

Multiple layers of security:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         Rate Limiting               β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚         Security Headers            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚         CSRF Protection             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚         Authentication              β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚         Authorization (Guards)      β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚         Input Validation            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚         Your Handler                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

3. Secure DefaultsΒΆ

All features use secure defaults:

  • Cookies: HttpOnly, Secure, SameSite=Lax
  • Sessions: Cryptographically signed
  • JWT: Strong algorithms required (HS256, RS256)
  • Headers: Modern security headers enabled

Authentication MethodsΒΆ

JWT AuthenticationΒΆ

Best for stateless APIs:

from cello.middleware import JwtConfig, JwtAuth

config = JwtConfig(
    secret=b"your-secret-key-minimum-32-bytes-long",
    algorithm="HS256",
    expiration=3600
)

jwt_auth = JwtAuth(config)
jwt_auth.skip_path("/login")
jwt_auth.skip_path("/public")

app.use(jwt_auth)

@app.get("/protected")
def protected(request):
    claims = request.context.get("jwt_claims")
    return {"user_id": claims["sub"]}

Basic AuthenticationΒΆ

For simple use cases:

from cello.middleware import BasicAuth

def verify_credentials(username, password):
    # Your verification logic
    return username == "admin" and password == "secret"

app.use(BasicAuth(verify_credentials))

API Key AuthenticationΒΆ

For service-to-service communication:

from cello.middleware import ApiKeyAuth

valid_keys = {"key1": "service-a", "key2": "service-b"}

api_auth = ApiKeyAuth(
    keys=valid_keys,
    header="X-API-Key"
)

app.use(api_auth)

Authorization (Guards)ΒΆ

Control access with composable guards:

from cello.guards import RoleGuard, PermissionGuard, And, Or

# Simple role check
admin_only = RoleGuard(["admin"])

# Permission-based
can_edit = PermissionGuard(["posts:edit"])

# Composable guards
admin_or_editor = Or(RoleGuard(["admin"]), RoleGuard(["editor"]))
admin_with_write = And(RoleGuard(["admin"]), PermissionGuard(["write"]))

@app.get("/admin", guards=[admin_only])
def admin_panel(request):
    return {"admin": True}

@app.post("/posts", guards=[can_edit])
def create_post(request):
    return {"created": True}

@app.delete("/posts/{id}", guards=[admin_or_editor])
def delete_post(request):
    return {"deleted": True}

Security HeadersΒΆ

Protect against common attacks:

from cello.middleware import SecurityHeadersConfig, CSP

config = SecurityHeadersConfig(
    # Content Security Policy
    csp=CSP(
        default_src=["'self'"],
        script_src=["'self'", "https://cdn.example.com"],
        style_src=["'self'", "'unsafe-inline'"],
        img_src=["'self'", "data:", "https:"],
        connect_src=["'self'", "https://api.example.com"]
    ),

    # HTTP Strict Transport Security
    hsts_max_age=31536000,  # 1 year
    hsts_include_subdomains=True,
    hsts_preload=True,

    # Other headers
    x_frame_options="DENY",
    x_content_type_options="nosniff",
    referrer_policy="strict-origin-when-cross-origin",
    permissions_policy="geolocation=(), microphone=()"
)

app.enable_security_headers(config)

Session SecurityΒΆ

Secure cookie-based sessions:

from cello.middleware import SessionConfig

config = SessionConfig(
    secret=b"session-secret-minimum-32-bytes-long",
    cookie_name="session_id",
    max_age=86400,  # 24 hours
    http_only=True,
    secure=True,     # HTTPS only
    same_site="Lax"
)

app.enable_sessions(config)

@app.get("/login")
def login(request):
    request.session["user_id"] = "123"
    return {"logged_in": True}

@app.get("/profile")
def profile(request):
    user_id = request.session.get("user_id")
    return {"user_id": user_id}

CSRF ProtectionΒΆ

Protect against Cross-Site Request Forgery:

from cello.middleware import CsrfConfig

config = CsrfConfig(
    secret=b"csrf-secret-minimum-32-bytes-long",
    cookie_name="_csrf",
    header_name="X-CSRF-Token",
    safe_methods=["GET", "HEAD", "OPTIONS"]
)

app.enable_csrf(config)

# Token available in request
@app.get("/form")
def get_form(request):
    csrf_token = request.csrf_token
    return Response.html(f'''
        <form method="POST">
            <input type="hidden" name="_csrf" value="{csrf_token}">
            <button type="submit">Submit</button>
        </form>
    ''')

Rate LimitingΒΆ

Prevent abuse and DoS attacks:

from cello.middleware import RateLimitConfig

# Basic rate limiting
app.enable_rate_limit(requests=100, window=60)  # 100 req/min

# Advanced configuration
config = RateLimitConfig(
    requests=100,
    window=60,
    algorithm="token_bucket",  # or "sliding_window"
    key_func=lambda req: req.get_header("X-API-Key") or req.client_ip,
    exempt_paths=["/health", "/metrics"]
)

app.enable_rate_limit(config)

Adaptive Rate LimitingΒΆ

Adjust limits based on server load:

from cello.middleware import AdaptiveRateLimitConfig

config = AdaptiveRateLimitConfig(
    base_requests=100,
    window=60,
    cpu_threshold=0.8,      # Reduce limits above 80% CPU
    memory_threshold=0.9,   # Reduce limits above 90% memory
    latency_threshold=100   # ms - reduce if latency exceeds
)

app.enable_rate_limit(config)

Security ChecklistΒΆ

DevelopmentΒΆ

  • Use environment variables for secrets
  • Enable all security headers
  • Implement proper error handling (don't leak info)
  • Validate all input
  • Use parameterized queries

ProductionΒΆ

  • Use HTTPS everywhere
  • Set Secure flag on cookies
  • Enable HSTS with preload
  • Configure CSP properly
  • Set up rate limiting
  • Enable request logging
  • Monitor for anomalies

API SecurityΒΆ

  • Authenticate all endpoints
  • Implement proper authorization
  • Use short-lived tokens
  • Implement token refresh
  • Log authentication failures
  • Rate limit authentication attempts

Common Vulnerabilities ProtectedΒΆ

Vulnerability Protection Feature
XSS CSP, auto-escaping Security Headers
CSRF Double-submit cookies CSRF Middleware
SQL Injection Parameterized queries Validation
Clickjacking X-Frame-Options Security Headers
MIME Sniffing X-Content-Type-Options Security Headers
Timing Attacks Constant-time comparison Auth Middleware
DoS Rate limiting Rate Limit Middleware
Session Hijacking Secure cookies Session Middleware

Next StepsΒΆ