The agent is untrusted code. We built the product around that.
An autonomous coding agent clones your repository and executes arbitrary commands against it. That is the same risk profile as a CI runner, and we treat it that way. This page describes the isolation architecture in enough detail to forward to your security team. Questions and disclosures: security@fragonstudios.com.
Threat model
Two things must never happen: an agent run touching anything outside its own sandbox, and one customer's data reaching another customer. Everything below exists to enforce those two properties, fail-closed.
One qualifying fact before you read 3,000 words of architecture: FragonForge is a hosted service and connects to your forge over the internet. An instance that is only reachable inside your VPN cannot be connected today; details in the Reachability section below. On the Enterprise tier, a deployment on your own hardware can be arranged by agreement.
- EU residency: yes
- Per-run isolation: yes
- Audit log + CSV export: yes
- TOTP 2FA: yes
- SAML SSO: not yet
- SOC 2 / ISO 27001: not yet
On this page
your forge
calls our public webhook URL; we call its API over HTTPS
control plane
clone, push, and MR calls happen here
forge token + LLM key live here
sandbox
per-run Kubernetes job, egress: deny
zero credentials inside
gateway + LLM proxy
one door out, per-run token; your key attached on the way out
your LLM provider
your contract, your bill; bodies are never stored by us
Execution isolation
Each run executes in a dedicated Kubernetes job, created for that run and destroyed after it.
Hardened runtimes
Sandboxes run under gVisor, a user-space kernel that intercepts syscalls. The Team and Business plans use Kata Containers, which put each run in its own lightweight VM with a separate guest kernel.
Non-root, pinned, scanned
The sandbox image runs as a non-root user, is pinned by digest (not by tag), and is vulnerability-scanned with Trivy in CI before it can be deployed.
Real toolchains, no secrets
The image ships compilers and test runners. It ships no credentials of any kind.
A note on honesty: no sandbox is escape-proof. gVisor and Kata have had CVEs over the years, like every isolation layer. That is why the design assumes the sandbox can turn hostile: no credentials inside it, default-deny networking around it, and one authenticated door out. The runtime is one layer, not the whole defense.
Network isolation
Default-deny egress
A Kubernetes NetworkPolicy denies all outbound traffic from the sandbox by default, enforced by the Calico policy engine. We are aware that some CNIs silently ignore NetworkPolicy; ours does not, and our isolation tests run against a policy-enforcing CNI for exactly that reason.
One door out
The only permitted destination is the platform gateway. It exposes exactly two things to the agent: repository tools (checkout and diff push, executed server-side) and an LLM egress proxy.
Per-run tokens
The sandbox authenticates to the gateway with an opaque per-run token: 256-bit, stored only as a hash, time-limited, and revoked the moment the run reaches a terminal state.
Proxy discipline
The LLM proxy allows only the configured provider endpoints, guards against SSRF, and strips any inbound authentication headers before forwarding.
The sandbox holds no credentials
This is the core design decision. Cloning, pushing, and opening the merge request happen on the control plane, outside the sandbox. Your forge token never enters the sandbox. Your LLM key never enters the sandbox either: the agent calls the egress proxy, and the proxy attaches your key on the way out, scoped to the provider that was fixed when the run token was minted. A compromised run has nothing to steal and nowhere to send it.
Tenant isolation
FragonForge is multi-tenant, and tenant isolation is enforced in depth, not by convention:
- Query-level scoping. Every tenant-scoped row carries a tenant ID, and the data layer applies a global filter to every query. Inserts are stamped centrally, not by hand.
- Fail-closed context. Tenant context starts empty. No tenant means zero rows, not all rows. Background jobs re-establish the tenant from the claimed work item before any data access.
- Compiler-enforced exceptions. Bypassing the tenant filter without a declared, categorized justification is a build error, enforced by a custom static analyzer. The list of exceptions is auditable.
- Leak tests as build gates. Automated two-tenant tests assert that data, credentials, clone URLs, and search indexes never cross tenants. The build fails if any tenant-scoped entity is missing its filter.
Credentials and encryption
- Each organization has its own data encryption key. LLM API keys, forge tokens, webhook secrets, and TOTP seeds are encrypted with it (AES-GCM).
- Inbound webhooks are verified twice: a signed per-tenant URL token and the forge's payload signature against your own webhook secret, compared in constant time.
- Agent output is written to run logs through a secret-redaction filter.
Where your code lives, and for how long
The LLM proxy is a pass-through
It forwards the agent's requests to your configured provider and streams the responses back. It does not log or persist request or response bodies. The flip side, stated as one fact rather than two scattered caveats: because nothing is stored, these calls are not metered in our cost dashboard either. Your provider's logs and bill are the complete record of what the agent sent to the model.
Sandbox workspaces are ephemeral
The repository clone inside the sandbox lives on a pod-local volume that dies with the pod; finished jobs are reaped within minutes. The control plane's own working clone is deleted after every run.
Run logs hold agent output, not your repository
The tenant-visible run log stores the agent's own output, passed through a secret-redaction filter and capped at 64 KiB.
The code search index is the deliberate exception
On paid plans, the optional code index stores chunked source text and embeddings so the agent can search your codebase. It is tenant-isolated at both the database and the vector store, and it is deleted together with everything else when you offboard.
Telemetry carries no content
Traces and metrics record IDs, durations, and token counts. Emails we send never contain repository content.
Account security
- TOTP two-factor authentication, with recovery codes. Enrollment renders the QR code locally, so the secret does not leave the page.
- Scoped personal access tokens for API and CLI use, bounded by the owner's live role.
- Session management: list and revoke sessions, revocation on password change, server-side logout. Refresh tokens live in HttpOnly cookies, not in JavaScript-readable storage.
- Role-based access control (Owner, Admin, Member, Viewer), fail-closed.
- Sensitive actions (logins, credential and role changes, run and billing events) are written to a tenant-scoped audit log, with filtering and CSV export in the dashboard.
- Sign-in is email and password, or Google. SAML SSO does not exist today, and we will not imply otherwise. If SAML gates your rollout, tell us at office@fragonstudios.com; it directly affects prioritization.
Data residency and lifecycle
Two data paths, stated separately. Platform data - the repositories we process, the code index, run logs, keys and tokens - lives on our EU infrastructure, detailed below. Model traffic is different by design: the code the agent sends to a model goes to the LLM provider you chose, under your contract and that provider's region and data terms. BYOK means that boundary is your choice to make; we never route it anywhere else.
- The platform runs on dedicated bare-metal servers in the EU (Hetzner, Germany). Data at rest stays in the EU.
- Databases have point-in-time-recovery backups to EU object storage with a 30-day retention window.
- Run history retention follows your plan (30 days to 1 year).
- Offboarding is a real purge: database rows, the code search index, stored keys and tokens, and billing links. Self-serve from the app.
Reachability
FragonForge is a hosted service. It connects to your forge's API from our infrastructure, over HTTPS, with the per-organization token you provide. That means your GitLab, GitHub Enterprise, Gitea, or Forgejo instance must be reachable from outside your network. An instance that is only reachable inside a VPN or private network cannot be connected today. A quick self-check: if curl -sI https://your-instance/ answers from a machine outside your network (a phone hotspot works), the instance is reachable. On the Enterprise tier, a deployment on your own hardware can be arranged by agreement; on every other plan there is no workaround today. If that constraint rules you out, tell us; it moves the priority.
Webhooks flow the other way: your forge calls our public webhook URL, the same as any other webhook integration. Nothing connects into your network.
Supply chain
- Dependency audits gate the build: a moderate-or-higher advisory in any dependency fails compilation.
- Container images are scanned before deployment; critical findings block the release.
Independent verification
We hold no SOC 2 or ISO 27001 certification today, and we will not pretend otherwise. What we can offer your review now: this architecture description, answers to your vendor security questionnaire, and direct access to the people who built the system. If your process needs a specific document, ask: security@fragonstudios.com.
What we ask of you
Honest boundaries, because they matter more to a reviewer than promises:
Review the merge request
FragonForge never merges its own work. The MR review is a designed-in safety valve, not a missing feature.
Scope the forge token
Connect a token scoped to the repositories you actually want automated, and rotate it on your normal schedule.
Set a spending limit with your provider
Your LLM provider's console can enforce a hard spending limit; use it. Our in-app cost dashboard meters planning and indexing calls today, not the agent's in-sandbox calls, so the provider's numbers are the authoritative ones.
Found something? security@fragonstudios.com. We answer.