Home/Developers/Security

Security architecture

Kaldera's design assumption fits in one sentence: the host is not trusted. In a marketplace the machine's owner is not our employee, it is the other party. The whole architecture is built on that assumption.

We claim no certification. SOC 2 Type I is planned as a process — it has not been obtained.

Core principles

How do you protect a job running on an untrusted machine?

These three rules are engineering constraints, not marketing lines: break one and the product does not build and the flow does not run.

Customer secrets never land on the host's disk

Environment variables, tokens and API keys are held encrypted at the application layer; we leave no plaintext secret on the machine's disk. The host cannot read a secret injected into your container off the file system.

Images are signed cosign

The signature of every image that runs is verified; a request for an unsigned image is refused with invalid_argument. The point is that neither the host nor anyone on the path can quietly swap the image you are running.

The connection is always outbound Phase 1 · agent

The host agent connects to the control plane itself; no listening port is opened on the host side, and it works behind NAT. There is no inbound route into the machine owner's home — traffic is always established from the inside out.

Workload and data

Inside the container is yours, outside it is our responsibility.

Container isolation

Workloads run on containerd with GPU access separated by the NVIDIA Container Toolkit. No k8s is installed on the host machine; our own scheduler does the placement, because cluster management is not handed to an untrusted machine.

Encrypted persistent volumes

Persistent disks are kept encrypted and live independently of the pod: terminate the pod and the data stays; when you want it gone you delete it explicitly with ?delete_volume=1. A delete request is single and unambiguous; we do not keep data around "just in case".

The region pin is enforced server-side

A region restriction is not a UI filter. A request to create a pod on an offer outside the pin is refused at the API layer with 400 · region_pin_violation. A UI filter does not count as a security boundary — the detail is on the Sovereignty page.

PII masking in logs and events

Personal data and secret values are written to logs masked. Every change in the admin panel lands, together with its stated reason, in an append-only audit record that cannot be altered afterwards; a change without a reason is refused.

API surface

Permission the size of the key, limits the size of the request.

API keys start with kld_, are stored hashed on the server, and the full value is shown only once at creation. The console talks over a separate path, with an HttpOnly session cookie.

ControlRuleWhy
Key scopesoffers:read · pods:write · billing:read · host:writeIf the key in CI has no need to read the invoice, it does not read it.
IdempotencyIdempotency-Key · 24 hoursA request resent after a network drop does not produce a second pod and a second charge.
Rate limitsanonymous 60/min · authenticated 600/min · pod creation 10/minBrakes abuse and scripts that accidentally end up in a loop.
Role matrixowner · admin · member · billing · hostThe person who reads the invoice does not have to be the person who opens a terminal.
Unauthorised actionsnot hidden, shown disabledWhat the product can do stays visible to everyone; the user asks their admin for it.
Audit recordappend-only, reason requiredA record that can be edited afterwards is not a record.

This table is the target contract. In Phase 0 the control plane performs no authentication for local development; key generation, scope checks and rate limiting open with the first beta.

Terminal session

A shell from the browser, without touching your key.

The web terminal is a WebSocket ↔ SSH bridge. The bridge never sees the user's personal SSH private key; when a pod is created, a key pair specific to that pod is generated and the private key is stored encrypted.

The token lives 60 seconds and is single-use; it is bound to the user, the pod and the IP address.
Session content is not recorded. Only metadata goes into the audit record: who, which pod, when, how long.
It closes after 15 idle minutes; there is a concurrent session limit per organisation and a rate limit per channel.
Role restriction: the terminal requires the member role or above; the billing role cannot open one.
terminal session
# 1) Ask for a short-lived, single-use session
POST /v1/pods/{id}/terminal/session

{ "ws_url": "wss://…/terminal",
  "token": "single-use",
  "expires_at": "+60 s" }

# 2) Upgrade to the WebSocket with the token
GET /v1/pods/{id}/terminal?token=…

# 3) Frames
client → server  binary  = raw stdin
client → server  text    = {"t":"resize"}
server → client  binary  = raw stdout
server → client  text    = {"t":"status"}

# The token is used once; even if it lands
# in a log, it will not open a second time.

Compliance status

We write down what is planned, not what has been obtained.

The company is not incorporated yet and the product is in Phase 0. That is why none of the lines below says "we are certified".

Secret isolation and encrypted secret storagedesign settled · implementation under way
Signature verification (cosign)design settled · image pipeline being built
Server-side enforcement of the region pindefined in the contract · implementation under way
API keys, scopes and rate limitsfirst beta
Audit record (append-only) and admin panelPhase 0 delivery slice 6
Web terminal and single-use tokensend of Phase 0
KVKK (Turkish personal data protection law) / GDPR / AI Act compliance packagePhase 3
SOC 2 Type Iplanned as a process · not obtained
Verified tier and on-site auditPhase 3
KVKKGDPREU AI ActRegion pinningSOC 2 Type I — in progress

You will not see an audit firm, a certificate number or a badge; even the mildest hint at a document we do not hold would be a lie. When the process starts, its scope and the firm running it will be written here.

Vulnerability reports

If you found a hole, tell us first.

We work by the principle of responsible disclosure. Send your report to merhaba@kaldera.ai — a dedicated security address and a PGP key will be published with the first beta; until that day this address is a placeholder and we make no commitment about response times.

What a report should contain

  • The endpoint, screen or component affected; a sample request and response if you can.
  • Steps to reproduce — that is the shortest path to a fix.
  • Your impact assessment: which data can be reached, with which privileges.

What we ask of you

  • Do not access anyone else's data; use your own account for the proof of concept.
  • Do not run tests that degrade the service: no load testing, no data deletion, no persistent changes.
  • Do not disclose the issue publicly until a fix is out; let us agree together on a reasonable window.

What we promise you

  • We will not pursue legal action against good-faith research.
  • When we publish the fix we will credit you by name if you want us to.
  • We have no bug bounty programme and we do not pretend to; if one is set up, its rules will be published here.

Next

Security and sovereignty are two sides of the same decision.

You choose where your data will sit; we enforce it server-side. The promise is the same: you don't pay for seconds that don't work, a hard budget cap, per-second billing.