Sign in soon
Security & threat model

How we handle your code,
your tokens, and your data.

Story Refiner connects to your repos, clones them into an isolated workspace, and runs a grounded refinement agent against them. The agent has read access. It does not write. Below is exactly how that works, what we’re defending against, and where the limits are.

Last updated 2026-05-01. We update this page when the architecture changes.

Defaults, at a glance

Read-only by default

GitHub OAuth scopes are read:user,repo. The agent cannot push commits, open PRs, or modify your repo.

Encrypted tokens at rest

OAuth tokens are AES-256-GCM encrypted in our database. The browser cookie only holds a session id.

Per-tenant isolation

Every domain query is scoped to your org id at the type level. No helper exists that can return another tenant’s data.

Per-chat workspace

Each chat session gets its own filesystem-isolated clone. Sessions cannot read each other’s files.

Tokens, OAuth scopes, and what we ask for

When you sign in with GitHub, Story Refiner requests the minimum scopes required to read the repos you choose to connect. Microsoft / Azure DevOps follows the same pattern via Microsoft Entra ID.

ProviderScope requestedWhy we need it
GitHubread:user, repoIdentify you and clone the specific repos you connect. Not used to write.
Azure DevOpsvso.code, vso.workRead code repositories and existing work items for grounding context.

We never request write:repo, delete_repo, or any organization-admin scope. If a future feature needed a broader scope, you would re-authorize explicitly.

How your tokens are stored

  • OAuth tokens are encrypted with AES-256-GCM before being written to Postgres. The encryption key lives in an environment secret, never in the database.
  • The session cookie (sid) only holds a session id. The OAuth token is never exposed to the browser, never returned in JSON, never logged.
  • When the agent clones a repo, the token is embedded in the clone URL only for the duration of the git clone, then scrubbed from any error output before any error surfaces in our logs or your chat.
  • You can revoke our access at any time at github.com/settings/applications. Revocation invalidates all subsequent agent runs for your org immediately.

Tenant isolation

Every domain table in our database has org_id as the first component of its primary key. All database access flows through a single gateway in src/lib/server/db/scoped.ts that takes orgId as a required argument. There is no helper that can omit it — a query that would leak across tenants does not compile.

The orgId used for every query is sourced exclusively from the authenticated session, never from a request body, query string, or cookie payload. The agent runtime itself uses a per-session gitHubToken passed via the Copilot SDK’s documented multi-tenant pattern, so two users’ agent sessions never share an identity.

The per-chat workspace

When you start a chat session, Story Refiner clones the selected repos into a fresh directory under os.tmpdir()/story-refiner/<chat_session_id>/ and runs the agent there as a CLI subprocess with that directory as its working dir. The agent cannot read files outside its working directory; it cannot see other users’ workspaces, your environment secrets, or anything else on the host.

Sessions are short-lived. Workspaces are destroyed at the end of the session.

Threat model — what we defend against

Cross-tenant data leakage

Defense: The forOrg(orgId) chokepoint described above. No code path exists that returns another tenant’s data, intentionally or by mistake.

Token theft

Defense: Tokens are encrypted at rest, never returned to the browser, scrubbed from logs and error output, and tied to a session that you can revoke at any time. The recent CVE wave on AI coding agents (Codex, Claude Code, Copilot SWE Agent in 2025–2026) was instructive: most of those attacks turned on tokens being available in the agent’s environment with broader scope than needed. We use the smallest scope and don’t put tokens on PATH or in process env.

Prompt injection from repo content

Defense: The agent has no tools that can write to your repo, open PRs, or trigger CI. Even if a malicious file in a cloned repo successfully injected into the agent, the worst-case action is the agent saying something it shouldn’t. There is no path from prompt injection to credential exfiltration or repo modification. Limit: The agent can still summarize content from a malicious file back to you in the chat — the same way reading any untrusted input would. We treat repo content as untrusted; you should treat agent output as untrusted too.

Supply chain via cloned repos

Defense: Cloned repos are read, not executed. We do not run npm install, pip install, or any other dependency resolution against your code. The agent reads files; it does not execute them.

Account takeover via session theft

Defense: Session cookies are HttpOnly, Secure, and SameSite=Lax. Sessions expire on a bounded TTL; revoking the OAuth grant invalidates all server-side sessions tied to that grant.

What we explicitly don’t do

  • We do not train any model on your code, your tickets, or your conversations.
  • We do not write to your repository. No commits, no PRs, no branch creation.
  • We do not share, sell, or expose your data to other tenants. Ever.
  • We do not request scopes we don’t use. If you see a scope on the consent screen that isn’t in the table above, that’s a bug — tell us.

Compliance & roadmap

We’re early. Here’s the truth about where we are:

  • SOC 2 Type II: in progress. Type I report available under NDA on request once issued.
  • Data residency: EU and US tenants on launch. Customer-chosen residency is on the Enterprise tier.
  • External pen-test: scheduled for Q3. Summary will be linked here when complete.
  • HIPAA / GDPR / DPA: Standard EU SCC and a DPA are available to all paid tenants on request.

Reporting a security issue

If you’ve found a vulnerability, email [email protected] with the subject line "Security disclosure". We acknowledge within one business day. We don’t have a paid bounty program yet, but we publicly credit researchers (with permission) for any valid report and we treat responsibly disclosed issues with priority.

Questions your security team would ask?

Send them a link to this page. Or sign in and try the agent yourself — read-only, no commitment.

Get early access