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.
- What runs where
- One attempt, step by step
- What is encrypted
- Who can see what
- Limits we enforce
- Honest limits
- Reporting a vulnerability
What runs where
| Component | Where | Holds |
|---|---|---|
| Jern Cloud control plane | Fly.io, one region | Session records, encrypted evidence, the inference gateway, GitHub App credentials |
| Runner machine | Fly.io, one per attempt, destroyed afterwards | A pinned checkout, the open-source runtime, short-lived credentials for that attempt only |
| Your repository | GitHub | The protected policy baseline and the pull requests Jern opens |
| Model provider | Anthropic, OpenAI, Google, or Fireworks, whichever key the workspace holds | Prompts and completions for the attempt, forwarded by the gateway |
One attempt, step by step
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- The gateway enforces the admitted model and the token cap, meters usage from the provider's own response, and rejects anything over budget.
- When the agent finishes, the runner verifies that the repository's
.gittree is unchanged, that every changed path is inside the baseline's editable paths, and that no live credential appears in the tree. - 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.
- 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
- Repository access always comes from GitHub. A person sees only the repositories the Jern Cloud App grants them at sign-in, re-checked on every read.
- Workspace membership grants visibility of the workspace, not of repositories or evidence.
- The decrypted trace is returned by exactly one endpoint, to a person already authorized to read that run, and is marked not to be cached.
- Every organization event that matters for audit is recorded and exportable as newline-delimited JSON.
- Request logs carry a request id, method, path, status, and timing. They never contain prompts, traces, or credentials.
Limits we enforce
| Limit | Value |
|---|---|
| Tokens per attempt | The session cap, metered by the gateway |
| Agent phase | The workspace's time limit per attempt, 30 minutes by default, up to the plan's ceiling |
| Whole machine | The time limit plus setup and publication, behind a 25-hour guard |
| Setup command | 10 minutes |
| Processes per domain | 128 |
| Agent output | 10 MiB per phase |
| Attempts per task | 3 |
Honest limits
- Isolation relies on Fly.io's guest boundary and on Linux namespaces and seccomp inside the guest. An independent test of that boundary is planned; until it is published, treat the guest boundary as the vendor's claim rather than ours.
- The orchestration side of the runner runs as root inside the guest by design. The agent does not.
- A repository secret is held by the agent, not attached at the proxy: treat one the agent held as one its shell could have read, and store a key with the least access the work needs. A broker that attaches it at the proxy, so the value never reaches the agent, is planned.
- Conversation text is redacted by retention, not encrypted at rest. Do not put secrets in messages.
- Jern Cloud does not currently claim compliance certification, customer-managed encryption keys, or data residency.
- Jern governs Jern runtime sessions, not sessions from other coding-agent products.
- A pull request is still code you have not read. Review it as you would any contribution.
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.