Back to Optimus Labs
>grokpatrol
LIVE INCIDENT · grok build repository exfiltration

Detects, on your machine, whether the grok build cli collected and queued your git repositories for upload to xAI — and tells you which secrets went with them.

offline · read-only · never runs grok · zero dependencies

confirmed affected: 0.2.93 detects: earliest build with the collector → latest observed platforms: macOS · Linux

why this exists

The wire went silent. The disk still has the story.

In mid-July 2026 the grok build CLI was found to bundle entire git repositories — full history, .env files and all — and stage them for upload to a Google Cloud Storage bucket. The collector ran as a background job, outside the tool-call permission system, so it fired even in sessions where the agent had been denied file access. We independently confirmed the same artifacts on our own machine when a spare laptop ran out of disk space — read the story here.

Most published indicators were network-based. They only helped if you were capturing traffic at the exact moment it happened. Most people weren't.

After the fact, the wire is silent and the disk is the only witness left. grokpatrol reads that evidence — offline, read-only, and never by running grok.

What left your disk

The collector ran outside the tool-call permission system: it fired even in sessions where the model was denied file access. When it packaged a repository, it took every git object reachable from HEAD.

Every tracked file at git HEAD

Your working tree as committed — source, config, and anything checked in alongside it.

Every git object reachable from HEAD

Not just the current files: the whole object graph behind them. Old commits. Old branches. Old blobs.

Files deleted from the checkout, still alive in history

The .env you removed. The .pem you rotated out. Gone from your working tree, still reachable in git, and uploaded with the rest. This is exactly where secrets hide.

you cannot find these by looking at your repo

Deleting the repo does not help. The copy is already at xAI. Once collection is confirmed, every credential reachable from that repository's git history should be treated as disclosed, and rotated.

A verdict you can check, line by line

Every finding points at an artifact you can open yourself: the log line Grok wrote, the archive's destination bucket, the exposed file's git object id. Facts and inference never blur. Queued is a proven local stage; exfiltrated is confirmed, or it says so.

Four verdicts, one order

CLEAN · INDETERMINATE · EXPOSED · COMPROMISED. COMPROMISED requires proof the code left the machine — a finding tagged exfiltration, not merely a high severity. A collected-and-queued host is EXPOSED: still act, but the bytes may not have landed.

Facts, not inference

Queued and Collected are proven local stages. Exfiltrated is CONFIRMED from an upload-completion event, or the report says unconfirmed. EXPOSED never claims bytes reached xAI when only the enqueue was logged.

Deleted-first ordering

Secrets gone from your checkout but alive in history sort to the top: they went out first and you can't find them by looking. Each is named with its git object id, the value the report refuses to quote. A default run never opens the blob; your own git cat-file is the only thing that prints it.

Blind spots, every run

Absence of evidence is not evidence of absence. A drained queue, rotated logs, a TCC-protected folder: the report names what it could not see on every scan, including clean ones. A degraded scan is INDETERMINATE, never CLEAN.

default — summary + what matters most --verbose — every archive, secret & evidence row --json — the full forensic record

Secrets are matched by filename by default; no file is read. --full-secrets-search also scans blob contents against the gitleaks rule set (222 rules, MIT, in memory), reporting the matching rule id, never the value.

Guarantees enforced by grokpatrol

This runs on a host you already distrust, so trust comes from checkability, not reassurance. Each promise below is a test or a linker assertion. Break one and CI goes red; it does not silently degrade.

No network. Ever.

net, net/http and crypto/tls are not linked in, and go.sum is empty — asserted by make verify-deps. A binary with no networking packages cannot phone home. No telemetry, no update ping.

Read-only

Every file open goes through one function, with O_RDONLY. No --out, no cache, no state directory. A test snapshots .git before and after a scan and demands byte-for-byte equality.

Secret values are never printed

It prints the path and git object id of every exposed credential, never the contents. A default run never reads those contents: it matches filenames only. Opt-in --full-secrets-search reads implicated blobs and matches them against the gitleaks rule set (222 rules, MIT-licensed, transcribed, still zero dependencies) in transient memory. model.Evidence and SecretHit carry no field that can hold file contents, and leak tests grep every output channel (stdout, stderr, --json) for planted values.

The grok binary is never executed

Not even grok --version. It carries a collector that runs outside the permission system; launching it to ask a question could itself start a session. Version is inferred passively.

A degraded scan never reports CLEAN

If macOS TCC blocked ~/Documents or a log was unreadable, the verdict is INDETERMINATE and the report says which directories it could not see. A blocked folder cannot be mistaken for a clean host.

Zero third-party dependencies

Standard library only; a single static binary. A tool that hunts for unaudited code should not ship any of its own. Release builds are CGO_ENABLED=0 and carry sigstore provenance.

Install & verify

Three ways in, ranked for trust. The binary you run on a compromised host is exactly the thing you should verify first, so every path below proves what it installs before it installs it.

go install

hermetic

Preferred: builds from source through the Go module proxy. Stdlib-only, so no third-party modules are fetched.

go install github.com/optimuslabs-io/grokpatrol/cmd/grokpatrol@latest

needs the Go toolchain

Verified binary

provable

Download the release asset plus SHA256SUMS, check it, and prove provenance with sigstore before you run it.

gh attestation verify grokpatrol_<version>_darwin_arm64 -R optimuslabs-io/grokpatrol

releases →

Install script

fastest

Non-interactive, no sudo. Detects your platform and verifies the checksum before installing, aborting on any mismatch.

curl -fsSL https://raw.githubusercontent.com/optimuslabs-io/grokpatrol/main/install.sh | sh

macOS & Linux · amd64 · arm64

why provenance, not just a checksum

Prove the binary was built by this repo — before you run it

The checksum proves your download arrived intact. The sigstore attestation proves something stronger: the binary was built from this repository's source by its release workflow, recorded in a transparency log that a compromise of the repo could not rewrite.

gh attestation verify grokpatrol_<version>_darwin_arm64 -R optimuslabs-io/grokpatrol

Then run it: grokpatrol for a summary, --verbose for the full receipt, --json | jq -r .verdict for fleets and CI. Windows is not currently built.

Questions about the Grok CLI incident or grokpatrol

Did the grok build cli upload my git repositories to xAI?

grokpatrol answers this for your machine, from the evidence left on disk: it reports which repositories were collected and queued for upload to gs://grok-code-session-traces/, and whether an upload was confirmed. It cannot speak for machines it did not scan. Run it and read the VERDICT.

Which grok build cli versions are affected?

0.2.93 is the confirmed-affected build — publicly reproduced collecting whole repositories and uploading them. The collector is reported still present through at least 0.2.99. grokpatrol detects from the earliest build where the collector code path exists through the latest observed, and labels each build CONFIRMED AFFECTED, REPORTED AFFECTED, or neither.

How do I check if Grok uploaded my code after the fact?

Most published indicators were network-based — you had to be watching the wire while it happened. grokpatrol is the after-the-fact check: it reads Grok's own logs (including rotated and gzipped), the ~/.grok/upload_queue/, staged archive manifests, and the version, then names the repos and secrets involved. No live capture required.

The upload queue is empty and my logs rotated — does that mean I'm safe?

No. A drained queue means the archives went out, not that they never existed, and rotated-away logs leave no trace. That is why a degraded or blind scan reports INDETERMINATE, never CLEAN, and why the report prints what it could not see on every run.

How do I stop Grok from uploading my repositories?

Set both mitigations in ~/.grok/config.toml: harness.disable_codebase_upload = true and telemetry.trace_upload = false. Either one alone is not enough — grokpatrol reports a host with only one set as EXPOSED, not mitigated.

What secrets were exposed, and which do I rotate first?

The exfiltrated set was every git object reachable from HEAD, so a secret you deleted from your checkout is still in history and went out with it. grokpatrol flags those first: rotate the credentials you can no longer see in your own working tree before the rest.

Does grokpatrol read or transmit my secret values?

It never transmits or prints them. A default run never even reads them: it matches filenames only. With --full-secrets-search it reads implicated file contents in memory to match them against the gitleaks rule set, then reports only the location and rule id — the evidence model has no field that can hold file contents, and leak tests grep every output channel for planted values. It makes no network calls at all, proven by the linker (make verify-deps), which asserts net/net/http/crypto/tls are not linked in.

Is it safe to run on a possibly-compromised host?

That is the design target. grokpatrol is a single static binary, stdlib-only, offline, and read-only (every file open is O_RDONLY; a test proves .git is byte-for-byte unchanged after a scan). It never executes the grok binary. Release binaries carry sigstore provenance, so you can prove one was built by this repo's workflow before running it.

Can I run grokpatrol across a fleet or in CI?

Yes. grokpatrol --json emits the complete forensic record on stdout for collection; the exit code is 0 whenever the scan ran (whatever it found) and 1 only on tool failure, so read the verdict from the report, not the exit status: grokpatrol --json | jq -r .verdict.

Who built grokpatrol?

grokpatrol is built with care by Optimus Labs, the agent security company. It is free, open source, and maintained as a contribution to the incident-response community. If you want to talk about how we secure AI agents, MCP servers, and skills at the endpoint, book a demo.