GitHub's 520-Character App Tokens Will Break the Glue Code Your Agents Run Through
Stateless installation tokens finished rolling out on October 2. The loud failures are length checks and short columns. The one to worry about is the redaction rule that stops recognizing them.
A GitHub App installation token used to be 40 characters long. As of October 2, every new one is about 520. Nothing about what the token can do changed: same permissions, same repository scope, same one-hour expiry. GitHub calls it a format change, and for GitHub that is exactly what it is.
For everything sitting between GitHub and your agents, it is a different story. Code that stores tokens, logs requests, validates headers or scrubs secrets out of transcripts was written against a string that was 13 times shorter and had a fixed shape. Some of that code will fail loudly. Some of it will keep working and stop protecting you.
That second group is what this article is about.
What GitHub changed, and why
GitHub announced the new format on April 24 and gave its reason plainly: the new format "improves token issuance performance under increased load and helps us deliver higher reliability at scale." The rollout started with Actions' GITHUB_TOKEN and featured integrations from April 27, widened in stages, and on October 2 GitHub declared it done. "All newly minted GitHub App installation tokens will be in the stateless ghs_APPID_JWT format."
The token keeps the familiar ghs_ prefix. After it comes the app ID and a JWT that, in GitHub's words, "contains details about the token such as the target installation, the application, and basic validation details." That JWT is not for you. GitHub says it "cannot nor should not be validated by a client app."
Two dates still matter. Tokens minted before the switch keep working until their one-hour lifetime ends, so the transition is already behind you for anything that mints fresh tokens. And the X-GitHub-Stateless-S2S-Token header, which GitHub added in May so apps could force either format per request, stops being respected after November 30. If you set it to disabled to buy time, that time has an end date.
Why agent stacks feel this first
GitHub's changelog never mentions agents. It does not need to. GitHub Apps are one of the standard ways bots, CI helpers and agent integrations authenticate, because an app gets short-lived, scoped tokens instead of a person's credentials. Every coding agent that opens pull requests as an app, every review bot, every internal tool that lets a model touch a repository, runs on these tokens.
And agent stacks tend to have more glue than human tooling. A token gets minted by one service, handed to an orchestrator, passed into a sandbox, written to a job record, logged by a proxy and echoed into a transcript that a model may later read. Each hop is a place where somebody once wrote code that assumed 40 characters.
GitHub's own list of what to audit maps neatly onto those hops:
- hardcoded 40-character length validations
- database columns too short for the new token
- proxies that truncate long Authorization headers
- secret-redaction rules that only match the legacy pattern
The first three fail loudly. A length check rejects the token. A VARCHAR(40) column either errors or truncates, and a truncated token gets you a 401 on the next call. A proxy that clips headers gets you the same 401. Annoying, visible, fixable in an afternoon.
The fourth one fails without a sound.
The redaction rule that stops recognizing tokens
Most secret scanners and log scrubbers recognize GitHub tokens by shape. Take gitleaks, one of the most widely copied rule sets in this space. Its github-app-token rule, as it stands in the project's config today, is:
(?:ghu|ghs)_[0-9a-zA-Z]{36}
Prefix, underscore, then exactly 36 alphanumeric characters. That is a perfect description of the old token. Now look at the new shape GitHub documents: ghs_, then the app ID, then another underscore, then a JWT full of dots and dashes.
I ran that regex against a mock token built to GitHub's documented ghs_APPID_JWT shape. It matched the old 40-character token and missed the new 514-character one. The underscore after the app ID ends the run of alphanumerics long before 36 characters, so the dedicated rule never fires.
Whether something else catches it depends on your setup. Many scanners also carry a generic JWT rule, but gitleaks's own JWT rule starts with a word boundary, and there is none between the underscore and the start of the JWT, so it likely misses the tail too. If your log scrubber is a hand-rolled regex copied from an old config, or a redaction step in your agent framework tuned to known token prefixes, you have no reason to assume it does.
Here is why that matters more for agents than for people. A leaked installation token is only good for an hour. That sounds safe until you think about where agent logs go: trace viewers, shared observability tools, transcripts pasted into tickets, context windows of the next agent run. An hour is plenty for an attacker who is already reading your logs, and a model that sees a valid token in its context can use it too. The point of redaction is that the token never shows up in those places at all.
So the risk is not that GitHub made tokens less safe. GitHub made them a different shape, and a lot of safety tooling is shape-based.
Put this into practice
The good news is that this is a small, mechanical audit. You can do most of it today.
1. Grep your own code for the old assumption. Search for ghs_, for 40 near anything named token, and for regexes containing {36}. Those are your candidates. GitHub's guidance is blunt: "treat tokens as opaque strings and avoid validating them against hardcoded patterns." Delete pattern checks rather than updating them.
2. Widen storage. GitHub says to plan for "at least a 520 character string," and notes the length varies with internal data. Use TEXT or a generous VARCHAR with headroom. Better still, ask why you are persisting a one-hour token at all.
3. Test your proxies and gateways. Mint a token and send a real request through every hop your agents use: egress proxies, API gateways, sandbox network layers. A 401 from a hop that worked last month is the tell.
4. Re-test redaction with a real new token. Mint one, print it into a test log line, and run it through whatever scrubs your logs and transcripts. If it survives unmasked, add a rule that matches ghs_ followed by any long run of token characters, and match by prefix and length range rather than an exact count. Then revoke the token.
5. Find the override header. Search for X-GitHub-Stateless-S2S-Token. If it is in production code, remove it before November 30. If it is set to disabled, you have been postponing every item above, and the postponement expires.
6. Check the vendors in your path. If a third-party agent platform holds your GitHub App credentials, ask whether their storage, logging and redaction handle the new format. That is a two-line email, and the answer tells you a lot.
Honest limitations
A few things this article cannot tell you.
I have not tested every scanner. Gitleaks is one rule set, chosen because so many projects copy it. GitHub's own secret scanning may well recognize the new format; its October changelog does not say either way. Some scanners may catch the token through a generic JWT rule written differently from gitleaks's. The claim here is narrow: shape-based rules written for 36-character suffixes do not match the new token, and you should check yours rather than assume.
The mock token is a mock. I built it to the shape GitHub publishes, not from a live mint, so the exact characters differ. The reason it fails the regex, the underscore after the app ID, comes straight from GitHub's documented format.
And this is mostly a hygiene problem, not a breach. The token still expires in an hour and still carries only the permissions you granted the app. If your logs never leave a tightly controlled system, the stakes are lower.
Tokens are an interface, and interfaces change
The lesson here is bigger than one format. Agents run on credentials passed through layers of code that nobody owns end to end, and each layer bakes in small guesses about what a credential looks like. When a platform changes the shape for its own reasons, the guesses break in two ways: some loudly, and some by letting things through without a sound. The loud ones get fixed because they page someone.
Go find the other kind. Mint a token this week, follow it through every system your agents touch, and see where it shows up in plain text. That one exercise tells you more about your agent security than any policy document will.
Sources: GitHub changelog, October 2, GitHub notice, April 24, GitHub override header, May 15, gitleaks config.
Medium metadata
- Title: GitHub's 520-Character App Tokens Will Break the Glue Code Your Agents Run Through
- Subtitle: Stateless installation tokens finished rolling out on October 2. The loud failures are length checks and short columns. The one to worry about is the redaction rule that stops recognizing them.
- Tags: GitHub, AI Agents, Security, DevOps, Software Development
- Reading time: about 8 minutes
- Canonical: import from the fervorai.dev URL