LanternDocs

Security

Each hop between the caller, the control plane, the data-plane host and the microVM is a trust boundary with its own credential, and untrusted code sits behind all of them.

Every boundary demands its own credential Lantern's trust boundaries, left to right. The caller sends a JWT or a scoped API key to the gateway on :8443 or the control plane on :8080. The gateway reaches the control plane's gRPC port :50051 with the shared x-lantern-service-token; the control plane enforces API-key scopes and Postgres row-level security keyed by app.tenant_id, and mints each VM's agent identity. The control plane reaches the workflow engine (:50052), the model router (:50053, which also receives the tenant's provider key per call), and the runtime-scheduler (:50055) with the same service token; every one of those gRPC ports accepts a tenant_id only from a caller presenting it. On the data plane host, the control plane, workflow engine and scheduler reach the runtime-manager (:50054) with an mTLS client cert plus the service token, and the manager refuses per-VM certificates (OU=lantern-vm) on every RuntimeManager method. The manager calls back to the control plane with X-Lantern-Runtime-Token to resolve secrets and forward reports. Inside the microVM, the harness runs as PID 1, reads spawn.json from a read-only image, and talks to the manager with its per-VM certificate plus the agent instance token. The workload runs as an unprivileged LANTERN_WORKLOAD_UID and reaches the secrets socket, which checks its uid with SO_PEERCRED. In opt-in broker mode (LANTERN_EGRESS_MODE=broker, Firecracker only), outbound requests from the workload leave over vsock through a host egress broker that adds the credential on the host, so no credential crosses into the VM and the VM has no network device. In the default mode the allowlist is enforced in-guest. Every boundary demands its own credential Dashed lines are trust boundaries; the solid line is the microVM wall. The table names what crosses each one. Caller and internet Caller SDK, CLI, dashboard LLM providers Gateway and control plane Gateway :8443 checks the JWT or API key Control plane :8080, gRPC :50051 API-key scopes, RLS on app.tenant_id mints each VM's agent identity Workflow engine :50052 Model router :50053, tenant provider key per call Each gRPC port accepts a tenant_id only from a caller with the service token. Data plane host runtime-scheduler :50055, places VMs runtime-manager :50054, mTLS + service token refuses OU=lantern-vm certs on RuntimeManager methods Host egress broker adds credential on egress (opt-in) microVM Harness, PID 1 per-VM cert OU=lantern-vm reads spawn.json from a read-only image Secrets socket SO_PEERCRED Workload unprivileged uid, secret env withheld no network device (broker mode, opt-in) Upstream APIs What crosses each boundary Caller to gateway or control plane JWT, or an API key carrying scopes Gateway to control plane x-lantern-service-token Control plane to engine, router, scheduler service token; the router also gets the tenant provider key Control plane, engine, scheduler to manager mTLS client cert + service token runtime-manager to control plane X-Lantern-Runtime-Token (secret resolve, reports) Harness to runtime-manager per-VM cert + agent instance token Workload to harness its uid, checked with SO_PEERCRED Workload to upstream (broker mode, opt-in) nothing; the host broker adds the credential on the host side Control plane Trusted host In-VM harness Untrusted guest microVM wall Trust boundary
Four zones and the credential that crosses each boundary. See Egress and credentials for the path out of the VM.

How a sandbox reaches the network, and why it never holds a credential in broker mode: Egress and credentials.

In plain termsThree questions this page answers. Can one customer's agent ever see another customer's data? (No — every record is fenced by tenant, enforced down to the database row.) What happens if an agent runs malicious code? (It runs inside a microVM, with egress limited to a per-sandbox allowlist: structurally in broker mode, where the VM has no network device, and in default mode when the image installs the iptables REDIRECT rule.) Can you prove what an agent did? (Yes. You can issue a signed receipt for any completed run; with an Ed25519 seed configured, anyone can verify it.) Everything below is labeled shipped or planned.
Status note: The controls described below reflect what is shipped and what is planned. Items marked (planned) are designed and documented but not yet implemented. Do not rely on planned features for compliance decisions.

What is shipped today

  • AES-256-GCM encryption at rest for connector credentials and LLM provider keys. Active only when LANTERN_CREDENTIAL_KEY is set — when unset, these columns are stored as plaintext pass-through, so set the key in any real deployment.
  • HttpOnly session cookie -- dashboard auth uses an HttpOnly session cookie; the JWT is also kept in localStorage for client-side API calls.
  • Row-Level Security (RLS) policies on every tenant-scoped table (USING + WITH CHECK), guarded by a catalog gate-test — a new tenant table without RLS (or an explicit exemption) fails CI. Enforcement is staged per-environment via LANTERN_RLS_ENFORCE=1; the handler cutover is complete and make rls-validate proves the policies end-to-end against a live database.
  • gRPC service-token auth on every internal gRPC port -- control-plane :50051, workflow-engine :50052, model-router :50053, runtime-manager :50054 and runtime-scheduler :50055. Constant-time check, runs before tenant extraction, fail-closed in production.
  • Runtime report binding -- step events and exit reports from a microVM are bound to that VM's own run: a report carrying another run's run_id is rejected with 403, so a compromised harness cannot spoof another tenant's audit or log stream.
  • Signed run receipts -- issued on request for a completed run (POST /v1/runs/{id}/receipt); a SHA-256 of the run's full journal_events stream is signed with Ed25519 when LANTERN_RECEIPT_ED25519_SEED is set (verifiable with no Lantern account at /proof against the key at /.well-known/lantern-receipts), HMAC-SHA256 dev fallback otherwise (verifiable only by the deployment).
  • Per-endpoint API-key scopes -- mutating endpoints are annotated with required scopes (agents:write, runs:execute, …). Enforcement is flag-gated via LANTERN_AUTHZ_ENFORCE and default-OFF today; when off, missing scopes are logged, not rejected.
  • Fail-closed token gates -- the gateway's API-key introspection endpoint refuses (403) in production when LANTERN_GRPC_SERVICE_TOKEN is unset (dev allows it with a warning); the personal /v1/signals endpoint refuses (401) whenever LANTERN_SIGNAL_TOKEN is unset. Both validate with constant-time compares when set.
  • A2A tenant isolation -- GetAgentCard / InvokeAgent gate on is_public OR caller-tenant; private agents return 404 to cross-tenant callers.
  • Bridge retry + surface-gateway tenant resolution -- the surface gateway resolves a real Lantern LANTERN_TENANT_ID instead of using platform IDs; unknown installs are rejected.
  • LLM idempotency keys on all provider calls -- derived from (run_id, step_id, attempt), reused across same-provider retries.
  • Dependency vuln gate -- govulncheck, cargo-audit, and npm audit run on every CI build.
  • OTel traces with tenant_id -- every control-plane HTTP request and gRPC call carries a span enriched with tenant_id, run_id, and step_id.

Privacy levels (planned)

The following privacy levels are part of the architecture design and are not yet implemented. They are documented here for reference.

  • Standard -- default level. Data is encrypted at rest and in transit. Logs include input/output for debugging. Suitable for most use cases.
  • Strict (planned) -- inputs and outputs are not logged. PII is automatically detected and redacted in traces. Audit log entries are created for all data access.
  • Paranoid (planned) -- end-to-end encryption. Data is encrypted before leaving the client and decrypted only inside the microVM. The control plane never sees plaintext data. Designed for healthcare, finance, and legal use cases.
Note: Privacy levels can be set per agent and per connector once the feature ships.

Runtime controls

These constraints are enforced by the platform, outside the model, so a prompt injection cannot talk its way past them.

  • Budgets: per-agent caps on cost per day and runs per day, and a tenant-wide daily cost cap. A hard-fail budget returns HTTP 402 before the run starts. Tokens/day is enforced at the same gates. The per-run cap is enforced mid-run in workflows and reported after the fact elsewhere; per-tool limits apply to workflow tool and connector nodes. Hard-fail budgets fail closed (503 on run create) when the budget cannot be read.
  • Egress allowlist: declared per spawn. In broker mode anything not on the allowlist is denied structurally (there is no network device). In default mode the allowlist binds only when the VM host/image installs the iptables REDIRECT rule. See Egress and credentials.
  • Human approval: workflow approval nodes block on a takeover request until an operator grants it. Nested approvals inside child runs fail today rather than wait.
  • Confidence gate: low-confidence tool and connector steps divert to approval. Off by default (LANTERN_CONFIDENCE_GATE).

The dashboard also has output filters (blocked topics and similar). These run in the browser on displayed output. They are a convenience, not a security control.

PII redaction (planned)

Automatic PII detection and redaction in agent inputs, outputs and traces is not implemented. Do not rely on it.

Data encryption

At rest

  • Connector credentials and LLM provider API keys are AES-256-GCM encrypted at the application layer when LANTERN_CREDENTIAL_KEY is configured; when it is unset they are stored unencrypted (plaintext pass-through). Other Postgres columns use standard Postgres storage — disk-level encryption is the responsibility of the host.
  • S3/MinIO objects (agent bundles, snapshots): encryption is a bucket setting you configure on your storage. Lantern does not set it.

In transit

  • All external traffic uses modern TLS — the gateway is built on rustls safe defaults (TLS 1.2 and 1.3)
  • Internal gRPC traffic is authenticated with a pre-shared service token (LANTERN_GRPC_SERVICE_TOKEN) validated via constant-time compare — a UnaryServiceAuthInterceptor runs before tenant extraction, fail-closed in production. mTLS is the planned stronger follow-up and is not yet implemented.
  • Default egress mode: in-VM secret vending uses kernel-attested peer auth (SO_PEERCRED) on the Unix domain socket — only the expected workload uid may receive secrets, and the harness refuses any other peer at the kernel level.

Bring your own key (BYOK) (planned)

Enterprise customers will be able to provide their own encryption keys via AWS KMS, Google Cloud KMS, or Azure Key Vault. This feature is on the roadmap and not yet available.

Audit logging (partial)

Run-level events are recorded in journal_events (the run event journal). A full immutable audit log covering secret access, role changes, and dashboard actions is on the roadmap. The following are tracked today:

  • Run start, completion, and failure (via journal_events)
  • A2A agent card access (tenant-scoped; cross-tenant requests return 404)

SIEM export via webhook or S3 is planned but not yet available.

Isolation

Agent runs execute inside isolated sandboxes. The isolation class depends on the workload type. The default backend is Kubernetes (RUNTIME_BACKEND=k8s); Docker is available for local development (RUNTIME_BACKEND=docker). In production, the runtime-manager supports gVisor (standard), Kata microVM (hostile), and Firecracker-backed Kata for the highest isolation tier. Fail-closed: untrusted/hostile workloads are refused unless the appropriate RuntimeClass is configured -- never silently downgraded to a bare pod.

All isolation tiers provide:

  • Process isolation -- separate filesystem and network namespace per run; microVM classes add their own guest kernel
  • seccomp filtering -- syscall restriction is a property of the configured RuntimeClass (gVisor / Kata), not a Lantern-shipped profile
  • Egress control -- default mode: an in-guest allowlist CONNECT proxy, fail-closed in production, which needs the iptables REDIRECT rule on the VM host/image (proxy env vars alone are advisory). Opt-in broker mode (LANTERN_EGRESS_MODE=broker, Firecracker only): the VM has no network device and a host broker enforces the allowlist and injects credentials, so they never enter the VM
  • Resource limits -- CPU, memory, and disk are capped per run
Important: User-supplied code, Python exec, browser automation, and anything that loads packages from the internet MUST run inside a microVM. This is an architectural invariant. Never run untrusted code in a bare container.

Secret management

Secrets (API keys, OAuth tokens, credentials) are referenced via the lantern.secret/... form and resolved at execution time by the runtime-manager's secret resolver (via the control-plane relay); stored credentials are AES-256-GCM encrypted when LANTERN_CREDENTIAL_KEY is configured. Resolved values never appear in:

  • Logs or traces
  • Run state or step outputs
  • Dashboard UI
  • API responses
Tip: Rotate LLM provider keys from Settings > LLM Providers; rotate connector credentials by re-installing the connector from Integrations.