sinatra.dev

Security

You are handing an autonomous agent a checkout of your codebase and a token that can push to it. This page is what it can do with them, what it cannot, and where we have chosen honesty over a stronger-sounding claim.

It stops at the pull request

The boundary everything else is built around.

Sinatra works on a branch and opens a pull request. There is no merge path in the product: no code calls the merge API, and the agent's standing instructions forbid it explicitly. Merging stays with you, your branch protection rules and your CI.

Pull requests open as drafts. Sinatra reviews its own diff first, and only then marks the PR ready for review, so nobody gets paged for half-finished work. If that review is interrupted, the PR is left as a draft rather than being promoted. It never deploys, never releases, and never runs anything against your production environment.

Worth being precise about: this is a product boundary, not a permission one. The GitHub App holds write access to contents and pull requests, which is what lets it push a branch at all. We are telling you what Sinatra does, not claiming it is technically incapable of more.

Where your code runs

One sandbox per task, and never a shared one.

Each task gets its own managed sandbox with your repository checked out. When the task ends the sandbox is stopped; a sandbox left idle stops after two hours and is archived after a day. We say stopped and archived rather than destroyed because that is what actually happens.

Sandboxes are never shared between workspaces. Reusing one requires either a workspace label stamped at creation or a workspace-scoped name, and a sandbox that cannot be proven yours is treated as not found, so the run creates its own instead. A mismatch always loses, and every refusal is recorded as a metric.

The sandbox cannot reach the open internet. Every one is pinned at the infrastructure layer to a single egress proxy enforcing a default-deny allowlist: GitHub, Linear, the model providers Sinatra can route to, and the standard language package registries. Anything else is refused, and refusals are logged. One honest limit: that allowlist is currently shared across all sandboxes rather than scoped per workspace, so treat it as a floor on where data can go, not as a per-tenant network perimeter.

Credentials

Encrypted per workspace, and bound to it cryptographically.

Model keys and integration tokens are envelope-encrypted: a unique AES-256-GCM data key per secret, wrapped by Google Cloud KMS on a 90-day rotation schedule, with your workspace id bound in as additional authenticated data. Ciphertext from one workspace therefore cannot be decrypted in another. That is a property of the construction, not a check we remember to run.

Inside the sandbox the picture is more mixed, and worth stating plainly rather than rounding off. A model API key you bring is passed to the agent process as environment for a single command and never touches disk. The GitHub, Linear and subscription credentials do: they are handed to their own command line tools, which write them to their credential files inside the sandbox, because that is how those tools authenticate. Nothing is written to logs. What protects those files is the sandbox boundary rather than their absence: one workspace, one task, stopped when the task ends.

Your GitHub credential is a short-lived App installation token that expires within the hour and is re-minted per run rather than held, so what lands in that file is both narrow and stale quickly.

What we store

Never your checkout. Not never anything.

Your repository is never copied into our database. What we keep about a repository is its name, description, primary language and stack; about a task, the branch and pull request we opened, the commit we started from and its status; and about a run, token counts and cost.

Two things go beyond that, and rounding them off would be the dishonest version of this page. We store the raw webhook payloads GitHub and Linear send us, which carry issue titles, descriptions and comment bodies, and on a pull request review comment the diff hunk it was left on. And when the prompt-injection screen below flags a piece of text, that text is kept with the flag so the decision stays auditable. So: no checkout, no wholesale copy of your code, but the parts of it that travel through an issue or a review comment do land in a log.

We don't use your code or content to train our own models, and we don't sell it. Your code is processed by the model provider you choose. Bring your own key and that processing is governed by your agreement with that provider. On the free tier, tasks run on a Sinatra-held provider account under that provider's standard terms. We are not going to tell you we hold zero-retention agreements with model providers, because we don't.

Untrusted input

Issue text is data, not instructions.

An issue body, a comment or a review can be written by anyone who can file one, so Sinatra treats them as untrusted. Before a run starts, that text is screened by a dedicated classifier for prompt-injection and exfiltration attempts; a flagged run is stopped and recorded rather than continued. Untrusted content is also fenced inside the agent's prompt so it cannot pose as an instruction.

This is a screen, not a guarantee. If the classifier itself errors, the run proceeds rather than failing shut, which is a deliberate availability tradeoff and worth knowing about.

GitHub App permissions

Five scopes, and what each is actually for.

Contents: read and write
Clone the repository and push the branch it works on.
Pull requests: read and write
Open the PR, post its own review, and reply to yours.
Issues: read and write
Read the issue that triggered the run and post progress back to it.
Checks: read only
See whether CI passed. Sinatra reads check results; it does not write them, so this is a one-way integration.
Metadata: read only
Mandatory for every GitHub App.

The short answers

Does Sinatra merge its own pull requests?

No. Sinatra opens pull requests and stops there. It has no merge path: merging stays with you, your branch protection and your CI, exactly as it would for a human teammate.

Can one customer's task see another customer's code?

No. Every workspace-scoped database query goes through a client that injects the tenant filter, enforced by a lint gate in CI. Sandboxes are never shared between workspaces: reuse requires a matching workspace label or a workspace-scoped name, and anything that cannot be proven yours is treated as not found.

Do you train models on my code?

We don't use your code or content to train our own models, and we don't sell it. Your code is processed by the model provider you choose, under your agreement with that provider if you bring your own key.

Can the agent reach the internet from the sandbox?

Only through a default-deny allowlist. Each sandbox is pinned at the infrastructure layer to a single egress proxy that permits GitHub, Linear, the model providers and standard package registries. Everything else is refused and logged.

Compliance

Formal compliance work, meaning SOC 2, SSO and SAML, or a custom DPA, is scoped as part of an Enterprise engagement rather than sold off the shelf. If your security review needs one of those, get in touch and we will tell you honestly where we are.

Reporting something

If you think you have found a vulnerability, email contact@sinatra.dev. We don't run a paid bug bounty, and we would rather say so than imply a program that doesn't exist. Reports get a human reply.

Privacy policyDocumentationWho builds Sinatra