Skip to main content

Zero Cleartext: How Arbitex Enforces Encryption at Every Layer

Your AI gateway handles the most sensitive traffic in your organization — prompts containing customer names, financial data, health records, source code, and strategic plans. Every one of those requests crosses network boundaries, hits storage layers, and passes through service-to-service connections.

Most AI gateways handle encryption the same way: they document TLS as a best practice, ship configuration examples, and assume operators will configure it correctly. That assumption is the gap. Misconfigured encryption is not a theoretical risk — it is the number one cause of data exposure in cloud deployments.

Arbitex takes a different approach. The gateway refuses to start if encryption is not configured correctly. No silent fallbacks. No warning-level log lines that operators miss. A hard stop.

This post walks through exactly how that works.

Fail-Fast: The Startup Validator Pattern

When the Arbitex Gateway starts in production mode, a set of startup validators runs before the application accepts any traffic. Each validator checks a specific encryption or security requirement. If any check fails, the process raises an error and terminates immediately.

Here is a simplified view of the pattern, drawn from the actual enforcement code:

def validate_redis_tls(settings):
    """Reject plaintext redis:// URLs in production."""
    if (settings.environment == "production"
            and settings.redis_url
            and settings.redis_url.startswith("redis://")):
        raise ValueError(
            "REDIS_URL uses plaintext redis:// which is not allowed "
            "when ENVIRONMENT=production. Use rediss:// (TLS-encrypted)."
        )

def validate_startup_config(settings):
    """Run all validators — fail on first error."""
    errors = []
    errors.extend(validate_jwt_secret(settings))
    errors.extend(validate_secrets_backend(settings))
    errors.extend(validate_redis_tls(settings))
    errors.extend(validate_ollama_url(settings))
    errors.extend(validate_llamacpp_url(settings))
    errors.extend(validate_otel_endpoint(settings))

    if errors:
        raise ValueError(
            f"Startup validation failed with {len(errors)} error(s):\n"
            + "\n".join(f"  - {e}" for e in errors)
        )

The validators are not advisory. They are blocking. In production mode, the orchestrator collects every misconfiguration and surfaces them all in a single error message — operators see every problem at once instead of fixing them one at a time through repeated restart cycles.

What gets validated at startup:

Validator What It Blocks
JWT secret strength Default, weak, or short secrets — hard abort on the placeholder value
Secrets backend SECRETS_BACKEND=env in production — must use Azure Key Vault or HashiCorp Vault
Redis TLS Plaintext redis:// connections — must use rediss:// (TLS)
Model provider URLs Plaintext http:// connections to Ollama, llama.cpp — must use https://
Telemetry endpoint Plaintext http:// OTLP export — must use https:// or grpcs://

The design philosophy is straightforward: if you can misconfigure it, someone will. The validator catches it before any data flows.

TLS Topology: Every Connection Encrypted

The Arbitex architecture has three network boundaries where encryption is enforced:

┌─────────────┐    TLS 1.3     ┌──────────────────┐    mTLS (EC P-384)    ┌──────────────┐
│   End User  │ ──────────────▶│  Arbitex Gateway  │ ◄───────────────────▶ │   Outpost    │
│  (Browser)  │    HSTS        │  (Control Plane)  │    CA-pinned certs   │  (Data Plane) │
└─────────────┘                └──────────────────┘                       └──────────────┘

                                       │  TLS 1.3

                               ┌──────────────────┐
                               │  LLM Providers   │
                               │  (OpenAI, Azure,  │
                               │   Anthropic, etc.) │
                               └──────────────────┘

User → Gateway (TLS 1.3 + HSTS): All client-facing endpoints require TLS 1.3 with HSTS enforced. No unencrypted HTTP paths exist. The startup validators ensure no downstream connection can fall back to plaintext.

Gateway ↔ Outpost (mTLS with CA Pinning): Hybrid Outpost deployments use mutual TLS for all service-to-service communication. Both sides of the connection present certificates and verify the other’s identity. The gateway validates the full certificate chain — leaf, intermediates, and root CA — against a pinned CA bundle.

The mTLS middleware rejects connections where the certificate is expired, the chain does not trace back to the pinned CA, or any intermediate certificate fails validation. Anti-spoofing middleware strips forged certificate headers from untrusted sources and only accepts certificates forwarded by CIDR-allowlisted proxies.

Gateway → LLM Providers (TLS 1.3): All outbound connections to model providers use TLS. The startup validators reject any provider URL configured with http:// in production mode.

CA Pinning: Trust What You Control

Standard TLS validates certificates against the system trust store — hundreds of certificate authorities that your organization does not control. CA pinning narrows that trust to a specific CA bundle that you manage.

For Outpost deployments, Arbitex pins internal service-to-service connections to a dedicated CA bundle configured via MTLS_CA_BUNDLE. This means a compromised public CA cannot issue a certificate that the gateway would accept for internal traffic. The trust boundary is explicit: only certificates that chain to your pinned CA are valid.

The mTLS middleware stores the verified common name (CN) from the client certificate in the request context. Downstream authorization logic can use this identity for service-level access control — not just “is this connection encrypted?” but “is this the specific service that should be making this request?”

Data at Rest: Infrastructure-Layer Encryption

For data at rest, Arbitex uses AES encryption with HMAC-SHA256 authentication for application-layer secrets: SIEM connector credentials, file attachments, and custom endpoint API keys. Encryption keys are managed through the configured secrets backend — Azure Key Vault or HashiCorp Vault in production, never plain environment variables.

For disk-level encryption, Arbitex relies on infrastructure-layer encryption — Azure Disk Encryption with customer-managed keys in Key Vault for cloud deployments.

Why not roll our own disk encryption? Because it is the wrong abstraction. Application-layer encryption protects specific secrets that the application manages (API keys, credentials, uploaded files). Disk-level encryption protects the storage medium itself — and that is a problem that Azure, AWS, and GCP have solved with dedicated hardware, key management infrastructure, and compliance certifications that no application vendor should try to replicate. Using the right tool for the right job is a security strength, not a weakness.

What This Means for Your Security Posture

The difference between “encryption supported” and “encryption enforced” is the difference between a best-practice document and a security control.

When your security team evaluates an AI gateway, ask one question: what happens if encryption is misconfigured?

If the answer is “it logs a warning,” the system is fail-open. Misconfiguration degrades security silently. The operator may not notice for days, weeks, or until the post-incident review.

If the answer is “the system does not start,” the system is fail-closed. Misconfiguration is impossible to deploy. The feedback loop is immediate: fix the configuration before any data flows.

Arbitex is fail-closed by design. Every connection validated at startup. Every certificate chain verified end-to-end. Every secrets backend enforced. No cleartext paths survive to production.

That is not a feature toggle. It is how the system works.

Arbitex Team

See AI governance in action.

Book a 30-minute technical walkthrough of the Arbitex Gateway.