Skip to content
DocsCI security

Security and data

CI security

What Graphide CI can access, where your jobs run, how they are kept apart, and what Graphide keeps about them.

How Graphide CI handles your jobs, your code and your secrets.

What it can access

Graphide CI works through the Graphide Review GitHub App on your organization. GitHub shows the App’s permissions when you install it. With them, Graphide CI:

  • registers a just-in-time runner for your jobs, which GitHub removes after the one job it runs;
  • reads your workflow files and your runs, including their logs, through GitHub’s API;
  • reads a repository’s code, with a token for that repository alone that can only read, when one of Graphide’s agents works on it;
  • builds a graph of a repository’s code, from a clone made with a token that can only read; test selection asks the graph which tests a change reaches;
  • opens pull requests that you merge or close, such as the one-line change that moves a workflow and the agents’ proposals, and comments on a pull request when a job was lost and needs a rerun.

A test step that runs through gr ci run signs in to Graphide with the job’s GitHub Actions identity token, which Graphide checks against GitHub’s published keys.

Your jobs get your secrets the way they do on any self-hosted runner: GitHub sends a job its secrets on the machine that runs that job.

Where it runs

On Microsoft Azure, in its West US and West US 2 regions. The service that schedules runners, and its database, are in West US.

  • Runners of 2, 4 and 8 vCPUs are virtual machines (Cloud Hypervisor) on Azure VMs that Graphide runs. Several customers’ machines share one such host.
  • Runners of 16 and 32 vCPUs are an Azure VM each, one per job.

Isolation

  • One job per machine. A machine serves one job of one customer, then is destroyed. Its disk is a fresh copy, and it gets its own clock, randomness and machine ID.
  • Network. No machine can reach the machines of other jobs, or any private address but the Graphide CI service it reports to. A 2, 4 or 8 vCPU machine also cannot reach Azure’s instance metadata service, or its host beyond the package cache the host serves, and cannot send from an address that is not its own. A 16 or 32 vCPU machine can reach the metadata service but has no Azure identity. Every machine can reach any public address on any port but 25 (outgoing mail), as GitHub’s own runners can.
  • Waiting runners. So a job starts within about a second, an idle machine may hold your organization’s single-use runner registration before a job arrives. It still serves one job of yours only.
  • Forks’ pull requests. Graphide decides for each job whether it is trusted, from GitHub and from what the runner received, about a second after the job reaches a runner. A job from a fork is untrusted, and runs on hosts with no trusted machines. Until that decision, a fork’s job runs where it landed, which can be a host with trusted machines. Once it is decided, the machine is moved, while it runs, to a host without them, or it is destroyed and the run is cancelled and started again on an untrusted machine. When we set you up, we suggest turning on GitHub’s “Require approval for all external contributors”.
  • Caches.
    • Your Actions cache saves go to GitHub as usual. A restore may be served from a copy on the host, only after GitHub confirms that the request may read that entry. Trusted and untrusted jobs never share these copies.
    • Each host keeps one cache of public packages (npm, PyPI, Go modules, Ubuntu’s archive and Docker Hub), shared by every job on it. A request that carries credentials, a cookie or a query string is never cached.
    • The tools and packages your jobs install can be prepared in advance as an environment of your own, which only your jobs use. It holds what your setup steps download and install, and for Go your packages already compiled. It holds no logs.
  • Agents. Each agent run gets a throwaway machine of its own, which can reach only Graphide’s model gateway and tools, GitHub, and a fixed list of package registries. It holds no GitHub credential, so it can only read from GitHub.

Before your jobs move

Before a repository moves, Graphide runs its recent jobs again on Graphide’s machines and compares their outcomes and times with your own runs. These runs:

  • get a token that can only read that repository, so anything they try to write fails;
  • leave out jobs that need secrets other than GITHUB_TOKEN;
  • post no check, status or comment, and keep no log;
  • make no copy of your repository on GitHub.

Their Actions cache stays on our host and is deleted after 7 days unused. Artifacts they make are deleted when the run ends, or after 6 hours at most.

Secrets

  • A runner registration is stored encrypted (AES-256-GCM) until the machine starts. Graphide CI’s own keys are kept in Azure Key Vault and read at each start.
  • The token an agent uses to fetch your code never enters the machine the agent runs on.
  • Treat job logs as on any CI service: if a job prints a secret, its log on GitHub holds it.

What we store

  • Job records: which job ran, on which class of machine, when, and for how long.
  • Test results read from your jobs’ test reports and logs: each test’s name, file, outcome and duration, and a fingerprint of its failure. The logs and failure messages themselves are not kept.
  • Environments prepared for your jobs, as above.
  • Agents’ work: what they proposed, the proof behind it, and a transcript of each run.

They are kept in Graphide CI’s own database, an Azure database in West US that is reachable only from Graphide’s private network, and in Azure storage that allows no anonymous access. How long each is kept:

What Kept
Job records 90 days
Each test’s verdict in your own CI runs 30 days
Events about your jobs, with their test results 400 days
Agents’ work, and the evidence they work from 180 days
Agents’ decision records, and the certificates behind an adopted change, which hold no code 1 year

A test step that runs through gr ci run also sends its results to the Graphide API, for your CI results: each test’s name, file, outcome and duration, and for a failing test its error message (at most 2 KB). The API keeps them 90 days.

Who can see it

Your jobs’ logs and results are on GitHub, under GitHub’s own permissions. The results gr ci run sends are shown on your dashboard to the Graphide accounts that may use the repository (Accounts and access). Graphide staff can read the records above.

Deletion

  • Each machine is destroyed when its job ends.
  • When Graphide CI is turned off for your organization, its runners are removed from GitHub and its waiting machines are destroyed.
  • After you uninstall the GitHub App, or remove a repository from it, we delete its records by hand within 30 days, or at once if you ask.

How to have your data deleted: Data, retention and deletion.

Agent signals

Agent signals are on by default; turn them off in your organization’s Settings on the dashboard. They come from hook files (.graphide/agent-signal.sh and the hook settings for Claude Code, Cursor and Codex) in a repository; switching a repository to Graphide CI changes only its runs-on lines. With them, those three coding agents tell Graphide CI when they start work, change a dependency file, or are about to push or merge, so machines are ready when the push arrives.

  • What they send to api.graphide.com: the repository’s name, the branch, the head commit, which coding agent it is, a random session ID and secret, and the kind of event. For a changed dependency or lock file, its path and a SHA-256 hash of its contents. For a merge, the pull request’s number. Never your code, your prompts or your agents’ conversations.
  • A commit you ask to test. If your agent asks Graphide to test a commit (the hosted MCP server’s ci_run_tests), the script pushes that commit to a hidden ref so Graphide can test it.
  • Proof of access. Once per session, the script pushes an empty commit to a hidden ref, refs/graphide/session/<id>, outside your branches and tags. Graphide reads it through the GitHub App, to check that the session can push to the repository, then deletes it.
  • Kept 30 days.
  • Off: for an organization, the switch in its Settings on your dashboard; on one machine, GRAPHIDE_SIGNALS=off in the environment; in one repository, a .graphide/signals-off file.

Third parties

  • Microsoft Azure runs the machines, the database and the storage.
  • GitHub runs your workflows and holds your logs.
  • Anthropic receives the code Graphide works on to speed up your CI. Working on private copies of your code for this is part of the service.

Something wrong or missing? Tell us on Discord or at hello@graphide.com.