Skip to content

Security

Prerequisites: API and Deployment.


Security considerations for running FluxRules in production.

Authentication (API)

By default, the API has no authentication. Add it for production:

# python skip
from fastapi import Depends, FastAPI, HTTPException
from fastapi.security import HTTPBearer

app = FastAPI()
security = HTTPBearer()


@app.post("/api/v1/evaluate")
async def evaluate(request: EvaluateRequest, credentials=Depends(security)):
    """Endpoint requiring valid bearer token."""
    token = credentials.credentials
    if not validate_token(token):
        raise HTTPException(status_code=401)

    # Proceed with evaluation
    return engine.evaluate(request.facts)

For production, use OAuth2 or API keys via a gateway (nginx, AWS API Gateway, etc.).

Input validation

All facts are validated before evaluation:

# python skip
from fluxrules.domain.dsl.validation import validate_dsl, DSLValidationError
from fastapi import HTTPException

# Validate rule DSL before accepting from API
try:
    validate_dsl(rule.condition_dsl)
except DSLValidationError as e:
    raise HTTPException(status_code=400, detail=str(e))

Database security

If using persistence, secure the database:

# Use SSL for database connections
export DATABASE_URL="postgresql://user:pass@db.example.com/fluxrules?sslmode=require"

# Restrict database access to app instances only
# Use VPC/security groups to isolate database

Audit logging

Track all rule changes and evaluations:

# Enable audit trail (requires [sql])
from fluxrules.initialization import initialize_persistence

initialize_persistence(env="prod")  # Enables audit logging

Check audit logs:

# Via REST API (if available)
curl http://localhost:8000/api/v1/audit?limit=100

Secrets management

Use environment variables for secrets, never hardcode:

import os

db_url = os.getenv("DATABASE_URL")  # From environment
api_key = os.getenv("API_KEY")  # From secret store

# Never do this:
# db_url = "postgresql://user:password@db.example.com/db"

Threat model

A short, honest model of the surfaces an operator is responsible for. FluxRules is a library plus an optional HTTP service; most controls are the operator's to apply.

Trust boundaries

Boundary Who is trusted Primary risk
Rule authors Whoever can create/modify rules A malicious or buggy rule can match/act incorrectly; custom operators/actions/engines run arbitrary Python in-process
Fact producers Callers of evaluate() / the HTTP API Malformed or oversized facts; injection into downstream actions
HTTP clients API consumers Unauthenticated access, DoS via large payloads/rulesets
Persistence The database Tampered rules loaded from storage; connection credentials

Assets

  • Rule definitions and their execution results/audit trail.
  • The evaluation process (availability and correctness).
  • Persistence credentials and the API SECRET_KEY.

Threats and mitigations

Threat Mitigation in FluxRules Operator responsibility
Arbitrary code via custom operators/actions/engines Extension registration is explicit; entry-point discovery is opt-in (never an import side effect) Only load trusted plugins; review load_plugins() sources
Malicious rule DSL validate_dsl / ValidationService reject malformed logic; the engine evaluates data, not eval Validate rules at the API boundary before persisting
SQL injection ORM + parameterized queries; internal DDL uses constant table names (bandit/ruff-gated) Use least-privilege DB accounts
Unauthenticated API access Auth primitives shipped (bcrypt, PyJWT) Enforce auth + network restrictions (no auth by default)
Tampered stored rules Audit trail with integrity hashing Restrict who can write to the rule store
Supply-chain compromise Pinned dev tooling, Dependabot, CI security job (bandit + pip-audit), signed releases + SBOM Verify release signatures/SBOM before deploying
Denial of service Working-memory high-water mark; bounded evaluation Rate-limit and size-limit inputs at the gateway

Out of scope

FluxRules does not sandbox custom Python extensions, does not provide authentication middleware by default, and does not manage secrets - these are delegated to the deployment environment and the guidance above.

Dependency advisory status

The API extra was installed non-editably in a clean Python 3.11 environment and audited with pip-audit on 2026-09-30. The audit found no known vulnerabilities in its resolved dependencies (FastAPI 0.142.2, Starlette 1.7.0, and PyJWT 2.15.1). The API now uses PyJWT rather than python-jose, removing the ECDSA dependency path. The Starlette lower bound excludes the versions identified by the current audit advisories.

Starlette 1.x represents included routers lazily, so app.routes is no longer a flat inventory of endpoint routes. FluxRules verifies the stable API contract through OpenAPI paths/methods and integration tests rather than Starlette's internal route representation. CI separately audits a fresh non-editable install of the api extra; the core package still does not install the API/web dependencies by default.


Next Steps