Security and data flow

The boundary is explicit.

A Jern Cloud session runs the open-source Jern runtime on a machine created for one attempt and destroyed afterwards. This page describes what runs where, what is encrypted, who can see what, and what the design does not defend against. Every statement is checked against the code and updated in the same change that alters the behaviour.

The concise claim: the repository's policy is verified by digest before the agent starts and cannot change during a session; the agent process holds no GitHub token and no model key, only a token scoped to its run plus any repository secret you declare, and its network goes through a proxy that admits the Jern gateway, the hosts the policy allows, and under the Open profile any public host, refusing private addresses; token, time, and process caps are enforced outside the agent; every trace is encrypted before it reaches a database; and work leaves only as a pull request that Jern never merges.

What runs where

ComponentWhereHolds
Jern Cloud control planeFly.io, one regionSession records, encrypted evidence, the inference gateway, GitHub App credentials
Runner machineFly.io, one per attempt, destroyed afterwardsA pinned checkout, the open-source runtime, short-lived credentials for that attempt only
Your repositoryGitHubThe protected policy baseline and the pull requests Jern opens
Model providerAnthropic, OpenAI, Google, or Fireworks, whichever key the workspace holdsPrompts and completions for the attempt, forwarded by the gateway

One attempt, step by step

  1. You send a message in a session. The session already pins the repository revision, the policy baseline by digest, the environment revision, the model, and the token cap. None of these can change during the session.
  2. The control plane reserves a fresh machine and issues it a single-use credential valid for fifteen minutes. That credential can claim exactly one task and nothing else.
  3. The machine checks out the pinned revision with a read-only GitHub token that is erased immediately after the fetch, then verifies the policy baseline's digest.
  4. If the environment declares a setup command, it runs in its own process and network domain that can reach only the declared package registries. That domain is destroyed before the agent starts.
  5. The agent runs as an unprivileged user inside a private network namespace whose only route is a local relay to the runner's proxy. Its network goes through that proxy over HTTPS: under a governed baseline, only to the public hosts it names; under the Open profile, to any public host; private addresses always refused, and every host it reached counted on the receipt. It holds no GitHub token and no model key: model calls go to the gateway under a run-scoped token, and the gateway holds the provider key. It sees only its own processes, so the runner's, which hold the checkout, evidence and publication credentials, are out of its sight, and no credential is ever on a command line.
  6. A repository secret is the one credential of yours the agent can hold, and only when you store it: its value is released into the agent's environment after setup. Its host is a declaration, not a wall: the proxy passes encrypted tunnels without reading them, so what keeps a secret to its host is that the agent reaches only the hosts the policy allows. Under the Open profile a secret is released only when an administrator turns that on, and then it can reach any public host. Secrets are scanned out of commits and redacted from the trace, and the receipt says when one was released.
  7. The gateway enforces the admitted model and the token cap, meters usage from the provider's own response, and rejects anything over budget.
  8. When the agent finishes, the runner verifies that the repository's .git tree is unchanged, that every changed path is inside the baseline's editable paths, and that no live credential appears in the tree.
  9. The runner uploads the trace, which is encrypted before it reaches the database. Only then does it obtain a publication token, commit on the session's branch, push, and open or update the pull request. Jern never merges.
  10. The machine is destroyed. Nothing from the attempt persists on it.

What is encrypted, what is not

Encrypted before persistence, with versioned keys held in AWS KMS: traces, workspace snapshots, dependency caches, and any provider credential you give us. The database never holds the plaintext of these. The run identifier is bound to the ciphertext so evidence cannot be reassigned to another run.

Stored in plaintext columns: your messages, the agent's final replies, and task prompts, so the dashboard can show your conversation. They are redacted in place once older than your evidence retention window. Retention is enforced by an hourly sweep and can also be run on demand from Settings.

Never stored: GitHub user tokens, installation tokens, runner credentials, or provider keys in plaintext. Only SHA-256 digests of one-time and session credentials are kept.

Who can see what

Limits we enforce

LimitValue
Tokens per attemptThe session cap, metered by the gateway
Agent phaseThe workspace's time limit per attempt, 30 minutes by default, up to the plan's ceiling
Whole machineThe time limit plus setup and publication, behind a 25-hour guard
Setup command10 minutes
Processes per domain128
Agent output10 MiB per phase
Attempts per task3

Honest limits

Reporting a vulnerability

Write to security@jern.ai or use GitHub private vulnerability reporting. A machine-readable contact is published at api.jern.ai/.well-known/security.txt. The runtime security model, policy implementation, receipt derivation, and trace vocabulary are public under Apache-2.0.

Last updated: September 6, 2026.