GitHub App Installation Tokens and Token Length and Format Assumptions - Where Validation Patterns, Storage, Proxies, and Log Redaction Hard-Code the Shape of a Token
First Published:
Last Updated:
ghs_, but their length is now approximately 520 characters, rather than the previous 40. The format is ghs_APPID_JWT, and it includes a JWT. The GITHUB_TOKEN passed to GitHub Actions jobs is also a GitHub App installation access token, and GitHub's April 24, 2026 announcement includes GITHUB_TOKEN in the scope of the new format.The change in length stands out, but GitHub does not ask for checks on length alone. The first item GitHub lists to check is validation that requires exactly 40 characters and patterns written for the legacy format. GitHub also lists logging and secret redaction rules that only match the legacy format's pattern. Even the regular expression that GitHub itself recommended was rewritten once, less than two weeks after it was provided.
This article presents a table, aligned with the four review areas identified by GitHub, showing where in a pipeline the assumption about token format is written. Examples from issuers outside GitHub are limited to those verified through primary sources. Discussions regarding token size (e.g., database column sizes or header buffer sizes) are left to existing articles. The information presented is based on verification conducted on October 8, 2026.
Related articles on this site:
- What Fills an AWS STS Session Token - Session Policies, Session Tags, the Single Size Limit, and How to Measure and Test It
- IAM Authentication to Databases, Caches, and Streams on AWS - Token Lifetime, What Revoking Access Does to Open Connections, and the Identity Inside the Service
- Hardening GitHub Actions for AWS Deployments - Workflow Permissions, Untrusted Triggers, Action Pinning, and What the Trust Policy Cannot Catch
- JWT and JOSE Standards History and Timeline - JWS, JWE, JWK, JWA, JWT, and How the Algorithm Registry Has Changed
- Install-Time Scripts by Package Manager - npm, pnpm, Yarn, Bun, Deno, pip, and uv: What Runs When You Install a Dependency, Since Which Version, and Where the Approval Is Recorded
- Trusted Publishing Beyond npm and PyPI - RubyGems, NuGet.org, crates.io, pub.dev, JSR, and Open VSX: Exchanged or Used Directly, What Trust Is Bound To, and What Each Registry Rejects
Table of Contents
- 1. The Scope of This Article and the Date It Was Verified
- 2. The Assumption Table — Tokens Whose Length or Format Changed
- 3. What Changed in GitHub App Installation Tokens
- 4. When It Changed — The Plan and What Actually Happened
- 5. Where the Assumption Was Written — A Check Table Built from GitHub's Four Items
- 6. Outside GitHub — What Other Issuers Changed, and What They Declare in Advance
- 7. Where the Sources Disagree and Where No Statement Was Found
- 8. Frequently Asked Questions about the GitHub App Installation Token Format
- 9. Summary
- 10. References
1. The Scope of This Article and the Date It Was Verified
This section first checks which lines of a pipeline carry the assumption this article covers. It then sets out the verification date, the materials read, the terms used in this article, and the topics it does not cover.1.1 The Assumption That a Token Has a Fixed Length and Shape
This assumption is embedded throughout the code that receives, stores, transmits, and logs tokens. The code that receives tokens includes conditions that check the length and regular expressions that check the format. The locations where tokens are stored have limitations, such as database column lengths, maximum value sizes in secret stores, and limits on environment variables. The locations where tokens are transmitted have limitations on header sizes for proxies and gateways. The logging infrastructure includes redaction rules tailored to the format of the tokens.A GitHub announcement from April 24, 2026, explicitly referenced this assumption. It stated that if applications expect or rely on installation tokens to have a specific length of exactly 40 characters, they may not be able to correctly handle tokens in the new format.
If your application expects or relies on installation tokens being exactly 40 characters long, it may not handle this new token format correctly.
Two related articles on this site cover other assumptions that CI pipelines silently relied on. The assumption that installing a dependency runs its scripts is covered in Install-Time Scripts by Package Manager. The assumption that publishing needs a long-lived API key is covered in Trusted Publishing Beyond npm and PyPI. This article covers the assumption at the stage of the tokens that CI receives and passes on.
1.2 The Date of Verification and Referenced Materials
The basis for this article was verified on October 8, 2026. The following materials were consulted:- Five GitHub Changelog entries: an announcement from April 24, 2026; a temporary header announcement from May 15, 2026; an announcement of completion from October 2, 2026; and announcements regarding format changes from March 4, 2021, and March 31, 2021. The content was extracted from the WordPress REST API, recording the publication date (
date) and last updated date (modified). The last updated date for the announcement from May 15, 2026, was June 10, 2026, and the last updated date for the announcement from October 2, 2026, was October 7, 2026. - Twelve pages from GitHub Docs, including topics such as generating installation access tokens, authentication as a GitHub App installation, GitHub token formats, the GitHub Apps REST API page,
GITHUB_TOKEN, secret scanning patterns, and the Secure use reference for GitHub Actions. - The GitHub Enterprise Server 3.22 versions of three pages: generating an installation access token, GitHub token formats, and the GitHub Apps REST API page (the latter two were checked on October 9, 2026).
- A GitHub Blog article from April 5, 2021 ("Behind GitHub's new authentication token formats").
- Archived versions of the announcements from May 15, 2026, and October 2, 2026, as preserved by the Internet Archive (Wayback Machine).
External materials consulted included GitLab release notes and documentation, Google's OAuth 2.0 documentation, Microsoft Learn documentation on Microsoft Entra, Slack's changelog from 2016 and token documentation, Stripe's API versioning documentation, the AWS STS API Reference, RFC 7515, and RFC 4648.
This article does not involve the actual issuance or measurement of tokens. All descriptions regarding length and format are based solely on the information found in the referenced materials.
1.3 Terminology Used in This Article
The term "token" is used throughout this article to refer to several different types of tokens. This article uses the following terminology:- Installation Access Token (also referred to as "installation token") is the token that a GitHub App uses to authenticate as an installation. The prefix is
ghs_. GitHub's changelogs also call it a server-to-server token. In this article, "installation token" has the same scope as in GitHub's announcements; where only tokens issued through the REST API (POST /app/installations/{installation_id}/access_tokens) are meant, this article says so. GITHUB_TOKENis the token that GitHub obtains before starting a GitHub Actions job. GitHub's documentation states thatGITHUB_TOKENis an installation access token for a GitHub App. WhereGITHUB_TOKENis treated differently (for example, its lifetime or the temporary header), this article says so.- Personal Access Tokens (
ghp_,github_pat_), OAuth Access Tokens (gho_), User-to-Server Tokens (ghu_– referred to as user access tokens by GitHub's documentation), and Refresh Tokens (ghr_) are all distinct from installation access tokens. - GitLab CI/CD Job Tokens, GitLab Personal Access Tokens, AWS STS Session Tokens, and tokens from other issuers are also distinct.
GitHub uses two formats for installation tokens, which are referred to as follows:
- The new format is in the form
ghs_APPID_JWT. GitHub refers to this as a stateless format or a JWT format. - The legacy format is an earlier format. GitHub refers to this as a stateful format or an opaque format.
The term "validation" is used with three distinct meanings:
- GitHub validating the token, which is a process of authorization.
- A client validating the JWT inside the token. GitHub writes that clients cannot do this and should not (see section 3.3).
- A client checking the format of the token with length checks and regular expressions. GitHub recommends not validating tokens against hardcoded patterns (see section 4.2), but gives a recommended expression for cases where a regular expression is still required (see section 4.3).
The mechanisms for concealing or detecting tokens are categorized into three. The process by which GitHub Actions runners replace secret values in logs is referred to as "runner masking". The process by which the logging infrastructure removes strings that match specified rules is called "log redaction". Finally, identifying credentials in repositories and commits is known as "secret scanning".
1.4 Topics Not Covered
This article does not address the following:- Discussions regarding token size (e.g., database column width, header buffer size, the 4,096-byte limit for AWS STS session tokens). This is covered in What Fills an AWS STS Session Token, in section 7 and FAQ Q8.
- Authentication failures due to token truncation. Regarding tokens used for IAM authentication with Amazon RDS, see IAM Authentication to Databases, Caches, and Streams on AWS, section 3.2.
- Explanations of JWT structure, signatures, and validation. The history of the JOSE standards is covered in JWT and JOSE Standards History and Timeline. This article only quotes one passage from RFC 7515 and refers to the RFC 4648 character set to provide context for the number of dots (section 3.3).
- General discussions about the permissions of
GITHUB_TOKEN, lifetime, workflow triggers, and runner masking. This is addressed in Hardening GitHub Actions for AWS Deployments. - General methods for securely storing tokens.
- How to create tokens that do not match detection rules, or examples of token values. This article will not include any example token values.
- Pricing.
2. The Assumption Table — Tokens Whose Length or Format Changed
This section presents the conclusions of this article in table form. This article calls this table the Assumption Table. One row per change, it lists when and how the assumption that pipelines silently relied on (a token has a fixed length and shape) broke down, and what users now have to declare explicitly.2.1 How to Read the Assumption Table
The Assumption Table has six columns.Tool or Service: This column describes the type of token (or the mechanism that depended on the token's format) and the scope covered by that row.Before: This column describes the length and format (or the behavior of the mechanism) before the change.Now: This column describes the length and format (or the behavior of the mechanism) after the change. Any associated conditions should also be included in this cell. If there are further changes after the initial change described in the row, those should also be noted here.Since: This column indicates the point at which the change occurred. For products with versions, it will be written as<version> (<YYYY-MM-DD>). For services without versions, it will list the date and the significance of that date (e.g., announcement date, completion announcement date).What You Must Declare: This column lists what the token's user must configure and check.Where the Source Says So: This column lists the sources that provide the basis for the information in that row.
The cells in the
Before, Now, and What You Must Declare columns should only contain excerpts from the sources (or summaries thereof). If the source does not address a cell, write The source does not say. Before writing this, thoroughly search the full text of the sources the row cites and related pages from the same issuer, using terms related to the row's subject and the terms length, format, prefix, and characters. When the sources provide conflicting information, present both descriptions, each with its source, without favoring one over the other.This article splits the Assumption Table into two tables: one for the two changes at GitHub and one for the three changes outside GitHub. The row on GitLab's automatic revocation is about the revocation mechanism on the issuer's side, not about a token itself (see section 6.2). Issuers that this article cites mainly for stating in advance that length or format can vary are not included in this table. Instead, these are summarized in a smaller table in section 6.4.
2.2 Two Changes at GitHub
| Tool or Service | Before | Now | Since | What You Must Declare | Where the Source Says So |
|---|---|---|---|---|---|
GitHub App installation tokens (the scope of the new format includes GitHub Actions' GITHUB_TOKEN) | 40 characters. Prefix is ghs_. A short, opaque string that does not contain dots. | The staged rollout that began on April 27, 2026, is complete. Newly issued tokens are in the ghs_APPID_JWT format by default. They are about 520 characters long instead of 40, and the length varies with the data stored within them. They contain two dots. The permissions, repository scoping, one-hour expiration, and endpoint of tokens issued through the REST API are unchanged (the lifetime of GITHUB_TOKEN is described separately on the GITHUB_TOKEN page in GitHub Docs). Tokens issued before the change keep working until they expire. | 2026-10-02 (rollout completion announced) | Treat tokens as opaque strings. Do not assume a fixed length. If a regular expression validates installation tokens, revise it so that it matches both the new and the legacy format. Make token storage columns and header settings accept at least 520 characters. If you use the temporary header X-GitHub-Stateless-S2S-Token, remove it from production code before November 30, 2026. | GitHub Changelog (2026-04-24, 2026-05-15, 2026-10-02), GitHub Docs (GITHUB_TOKEN) |
| GitHub authentication tokens (changed in 2021. Includes personal access tokens, OAuth access tokens, GitHub App user-to-server tokens and server-to-server tokens, and refresh tokens) | Character set is [a-f0-9]. No prefix. The GitHub Blog states that many of the older formats were 40-character strings in hexadecimal. | Character set is [A-Za-z0-9_]. Each token type now has a prefix (ghp_, gho_, ghu_, ghs_, ghr_). The length remains unchanged for the time being (as of March 31, 2021). As noted in the first row, ghs_ tokens have undergone a further change in 2026. | 2021-03-31 (generally available) | Plan to support tokens up to 255 characters in length from June 1, 2021. | GitHub Changelog (2021-03-04, 2021-03-31), GitHub Blog (2021-04-05) |
2.3 Three Changes Outside GitHub
| Tool or Service | Before | Now | Since | What You Must Declare | Where the Source Says So |
|---|---|---|---|---|---|
| GitLab CI/CD Job Token | The source does not say. (The documentation calls it only the legacy format and does not state its length or structure.) | By default, it is in JWT format. Projects can continue to use the legacy format through a top-level group setting. This setting is only available until GitLab 20.0. The GitLab 17.11 version of the page instead gave JWT by default from GitLab 18.0, already used by new projects created on GitLab.com after February 21, 2025 (section 6.1). | 19.0 (2026-05-21) | Follow the section on known issues in the documentation. For example, if you encode the job token using base64 within a job, use base64 -w0 to disable line wrapping. | GitLab Docs (CI/CD job token, current and 17.11 versions), GitLab 19.0 release notes (date) |
| GitLab: Automatic Revocation of Leaked Personal Access Tokens | Revocation only used a single detection rule and only revoked tokens in the legacy format. Tokens created in GitLab 18.3 and later (routable or versioned routable format) were detected and reported, but not revoked. | Revocation now recognizes all three detection rules for GitLab personal access tokens. | 19.4 (2026-09-17) | No configuration changes are required. On instances with automatic response enabled, the wider coverage applies from 19.4 (Ultimate; applies to public projects; enabled by default on GitLab.com). | GitLab 19.4 release notes, GitLab Docs (Automatic response to leaked secrets) |
| Slack Token | Slack previously did not document the length of tokens. | On August 23, 2016, Slack announced that starting the following month (around September 20, 2016), the strings of newly issued user tokens, bot user tokens, and test tokens would become longer, by at least twenty characters. Slack's token documentation states that the final section of a user token is the secret and that user tokens created before August 2016 may have secrets of 6 or 10 characters instead of 32, but it does not state the total length of a token. | 2016-08-23 (announced) | Prepare storage for tokens up to a maximum length of 255 characters (e.g., VARCHAR(255) or TINYTEXT). Do not rely on any meaning that seems readable in the token string. | Slack changelog (2016-08-23), Slack Developer Docs (Tokens) |
For the
Before cell of the GitLab CI/CD job token row, this article searched the GitLab CI/CD job token page (current and 17.11 versions), the token list page (including the table of token prefixes), and the GitLab 19.0 release notes, using the terms legacy, format, length, characters, and prefix. No descriptions were found detailing the length and structure of the legacy format. The token list page states that the prefix for CI/CD job tokens is glcbt-, but it does not specify whether this prefix is also applied to tokens in JWT format.3. What Changed in GitHub App Installation Tokens
This section sets out what changed in the format of GitHub App installation tokens, using only what GitHub's sources state. It looks at the prefix and format, how the length is described, the dots and the JWT, what did not change, and the scope of the change, in that order.3.1 The Prefix Stays ghs_, and What Follows Becomes ghs_APPID_JWT
GitHub's announcement on April 24, 2026, stated that the format for installation tokens (tokens starting with ghs_) would change to ghs_APPID_JWT. However, the same announcement also clarified that the prefixes for each type of GitHub token would remain unchanged, and that installation tokens would continue to begin with ghs_. A subsequent announcement on October 2, 2026, also confirmed that installation tokens continue to use the ghs_ prefix.Installation tokens still start with the ghs_ prefix, but they’re now about 520 characters long instead of 40.
GitHub refers to this new format as a stateless format. The announcement from April 24, 2026, explained that the purpose of this change is to improve the performance of token issuance when load increases, and to enhance the reliability of the API. The announcement on October 2, 2026, stated that this format makes token issuance and validation faster.
3.2 Four Ways of Describing the Length, and a Maximum That Was Not Found
GitHub's sources describe the length of new-format installation tokens in four ways.- Approximately 520 characters (
~520 characters). Mentioned in announcements dated April 24, 2026, and May 15, 2026. - Varies with the data stored within it (
will vary based on the data stored within it). Mentioned in the announcement dated April 24, 2026. - At least 520 characters. Mentioned in a preparation item of the announcement dated April 24, 2026 (
at least a 520 character string), and in a check item of the announcement dated May 15, 2026 (at least 520 characters). Both are written as what database columns (and, in the May 15, 2026 announcement, header settings) should accept. - About 520 characters long instead of 40 (
about 520 characters long instead of 40). Mentioned in the announcement dated October 2, 2026.
The overall length of the tokens will be longer (~520 characters) and will vary based on the data stored within it.
Any database columns for access tokens can fit at least a 520 character string.
Where 520 appears, it is given either as an approximate token length or as the minimum length that database columns and header settings should accept. Within the scope checked for this article, no statement of the maximum length of installation tokens was found. The scope was the five changelog entries in section 1.2 and 12 pages of GitHub Docs. The search terms used were:
maximum, max, length, characters, 520, at least, and vary. The absence of this information does not necessarily mean that there is no maximum value. The 255 characters in the 2021 announcements (section 4.1) were a guideline that GitHub gave at that time, and were not presented as the maximum length for the new format being introduced in 2026.Therefore, assuming that new tokens are a fixed 520 characters long merely rewrites the very assumption that the April 24, 2026 announcement asks applications to avoid. The first preparation item in that announcement is that applications do not depend on the length of access tokens.
3.3 Two Dots, and a JWT That Clients Should Not Validate
The announcement on May 15, 2026, states that new, stateless tokens are JWTs that begin withghs_ and contain two dots. Legacy-format (stateful) tokens are short, opaque strings that do not contain any dots.A stateless token is a ghs_-prefixed JWT. It is longer (~520 characters) and contains two dots. In contrast, a stateful token is a short opaque string with no dots.
GitHub explicitly states that clients should not validate these JWTs. According to the announcement on April 24, 2026, a GitHub-internal issuer signs the JWT, and client applications cannot validate it and should not. The JWT contains details about the token, such as the target installation, the application, and basic validation details. Even so, as with all access tokens, clients must not depend on the contents of this JWT.
The JWT is signed using a GitHub-internal issuer and cannot nor should not be validated by a client app. It contains details about the token such as the target installation, the application, and basic validation details. As with all access tokens, client apps must not take a dependency on the contents of this JWT.
However, the announcement on May 15, 2026, also describes a method for distinguishing between different token types for testing purposes. This involves counting the number of dots following the
ghs_ prefix. New-format tokens have two dots, while legacy-format tokens have none.You can verify the token type by checking the number of dots after the ghs_ prefix: a stateless JWT-format token has two dots, while a stateful opaque token has no dots.
In this article's reading, the two descriptions serve different purposes. The number of dots is a method for verifying the format of a received token during migration testing. The instruction not to rely on the contents applies to how production code handles the token. The May 15, 2026, announcement also lists, among the items to check, that code examining or validating tokens treats
ghs_ tokens as opaque strings.GitHub's changelog does not explain why there are two dots. As background, a signed JWT uses JWS Compact Serialization (RFC 7515), which is a string composed of three base64url parts connected by dots (
.). RFC 7515 defines these base64url components as being encoded using the character set described in Section 5 of RFC 4648, and explicitly excludes any line breaks or whitespace.BASE64URL(UTF8(JWS Protected Header)) || '.' ||
BASE64URL(JWS Payload) || '.' ||
BASE64URL(JWS Signature)
Section 5 of RFC 4648 includes uppercase and lowercase letters, numbers, the hyphen (
-, value 62), and the underscore (_, value 63). This background is also related to a revision of the regular expression in section 4.3, although GitHub has not provided a reason for this revision. This article will simply present these details as specifications, rather than as GitHub's explanation. The structure and signature of the JWT itself are covered in JWT and JOSE Standards History and Timeline.3.4 What Did Not Change
According to the announcement on October 2, 2026, the token permissions, repository scope, one-hour validity period, and the REST API endpoint for issuing installation access tokens are unchanged. Tokens issued before the change will continue to be valid until their expiration.Token permissions, repository scoping, the one-hour expiration, and the installation access token REST API endpoint are unchanged. Tokens minted before the change continue to work until they expire.
The GitHub Docs also state that installation access tokens issued via the REST API expire after one hour. The endpoint for issuing tokens is
POST /app/installations/{installation_id}/access_tokens. The lifetime of GITHUB_TOKEN is described separately. According to the GitHub Docs page for GITHUB_TOKEN, it expires when the job finishes or when a maximum lifetime that depends on the runner type is reached. Details of that lifetime are covered in section 2.2 of Hardening GitHub Actions for AWS Deployments.3.5 Scope of the Change — GITHUB_TOKEN, GitHub Enterprise Server, and User-to-Server Tokens
Announcements dated April 24, 2026, and May 15, 2026, describe the scope of changes as follows:- The new format applies only to server-to-server tokens for GitHub App installations. This includes GitHub Actions'
GITHUB_TOKEN. - The changes apply to GitHub Enterprise Cloud and Data Residency environments. GitHub Enterprise Server is not affected.
- Changes to the format of user-to-server tokens used with Copilot code review are not yet in scope. GitHub stated that they will share details about those plans in the future.
Upcoming rollouts will apply the new token format only to GitHub App installation server-to-server tokens, including Actions GITHUB_TOKEN.
The October 2, 2026 announcement and the notes on three GitHub Docs pages describe the scope as all newly issued GitHub App installation tokens. The sources this article read contain no statement that divides the scope by GitHub plan.
The GitHub Docs page for
GITHUB_TOKEN states that the GITHUB_TOKEN secret is an access token for GitHub App installations. This page does not mention the format or length of the token.The GITHUB_TOKEN secret is a GitHub App installation access token.
The October 2, 2026 completion announcement does not specifically mention
GITHUB_TOKEN, GitHub Enterprise Server, or user-to-server tokens. As of the verification date, this article has found no follow-up on the format change for user-to-server tokens (it searched the GitHub Changelog for user-to-server).4. When It Changed — The Plan and What Actually Happened
This section details the timeline of GitHub's announcements regarding token formats, presented chronologically. It starts with the 2021 change and continues through the 2026 notice, the temporary header, the completion, and the planned deprecation of the header. The planned schedule will be presented separately from the actual events that transpired.
4.1 2021 — Prefixes Added, and Guidance to Plan for Tokens Up to 255 Characters
In 2021, GitHub changed the format of authentication tokens. According to the announcements of March 4, 2021, and March 31, 2021, the changes involved both the character set and the addition of prefixes. The character set was changed from[a-f0-9] to [A-Za-z0-9_], and prefixes were added to differentiate token types. Personal access tokens now have the prefix ghp_, OAuth access tokens have gho_, GitHub App user-to-server tokens have ghu_, server-to-server tokens have ghs_, and refresh tokens have ghr_.The same two announcements also provided guidance regarding future token lengths. While the length remained unchanged for the time being, GitHub indicated that tokens are likely to become longer in future updates. Therefore, it was recommended that systems be prepared to handle tokens up to a maximum length of 255 characters after June 1, 2021. The following is the text of the March 4, 2021 announcement.
The overall length of our tokens will remain the same for now. However, GitHub tokens will likely increase in length in future updates, so integrators should plan to support tokens up to 255 characters after June 1, 2021.
A GitHub Blog post published on April 5, 2021, explained the design behind this change. Previously, many older authentication token formats consisted of 40-character strings encoded in hexadecimal, which could not be distinguished from other encoded data such as SHA hashes. The prefixes, similar to those used by Slack and Stripe, are intended to help identify the type of token. The post further states that a 32-bit checksum is included in the last six digits of each token. This checksum is meant to virtually eliminate false positives in offline secret scanning. The post also noted that this change was implemented without altering the token length.
Many of our old authentication token formats are hex-encoded 40 character strings that are indistinguishable from other encoded data like SHA hashes.
A checksum virtually eliminates false positives for secret scanning offline.
The roughly 520 characters of 2026 exceed even the 255-character guideline that GitHub itself gave in 2021. The three announcements from 2026 do not mention the 255-character guideline. This article has found no statement that shows whether the 2021 guidance was withdrawn.
4.2 April 24, 2026 — The Notice and the Planned Stages
The announcement on April 24, 2026, indicated that a staged rollout would begin on April 27, 2026. The announcement outlines a plan for the following weeks, in two stages, in the future tense.- From April 27, 2026, through mid-May: A staged rollout of the new format will begin for the
GITHUB_TOKENissued by GitHub Actions, as well as for installation tokens issued to GitHub's first-party featured integrations (Dependabot, Slack, Teams, etc.). The announcement states that this is not expected to impact existing Actions workflows. - From mid-May through late June: A staged rollout of the new format will begin for all GitHub App installation tokens. A "brownout" period will be implemented to identify any integrations that still depend on token format assumptions, after which the new format will be broadly enabled.
Mid-May to late-June 2026: We’ll begin a staged rollout of the updated format to all the GitHub App installation tokens. We will be providing more guidance over the coming weeks on how to test these new tokens locally to validate that your GitHub Apps continue to work as expected before we roll out the change more broadly. We’ll introduce a brownout period to identify integrations that still depend on token format assumptions, followed by broad enablement of the updated format.
This is a planned course of action. This article has not confirmed whether
GITHUB_TOKEN was actually switched first. No individual announcements related to the brownout period have been found (a search of the GitHub Changelog for brownout yielded six matching entries from April 2026 onwards, with only one pertaining to the token format, and corresponding to this announcement).The same announcement also recommends treating tokens as opaque strings and avoiding validation using hardcoded patterns, as a preparatory measure.
It’s recommended that you treat tokens as opaque strings and avoid validating them against hardcoded patterns.
Furthermore, the announcement lists three preparatory steps. First, applications should not rely on the length of access tokens. Second, the code should not contain regular expressions like
ghs_[A-Za-z0-9]{36} that validate tokens. Third, database columns used to store access tokens should be able to accommodate strings of at least 520 characters. Regarding the second point, the announcement notes that such regular expressions may not match the new tokens.There are no regexes in your codebase such as ghs_[A-Za-z0-9]{36} that validate a token. These may not match the new tokens.
This regular expression is presented as an example for review, and is not a recommended pattern.
4.3 May 15, 2026 — The Temporary Header and the Revised Recommended Regular Expression
The announcement on May 15, 2026, introduced a temporary request header so that developers can test before the rollout reaches their applications. Adding theX-GitHub-Stateless-S2S-Token header to a request to POST /app/installations/:installation_id/access_tokens (the changelog's notation) overrides the server-side rollout decision for that single request.| Header value | Effect |
|---|---|
enabled | Returns a token in the new format (stateless, JWT format), regardless of where the integration is in the rollout. |
disabled | Returns a token in the legacy format (stateful, opaque format), even if the integration is already included in the rollout. |
| No header | Normal rollout behavior. |
Any other values (e.g.,
true, false, 1, 0) are silently ignored and get the normal rollout behavior. According to the announcement, this header is supported on the REST API that creates installation access tokens. The sources this article read do not describe a way to use this header to select the format of the GITHUB_TOKEN that GitHub Actions obtains for a job.The same announcement lists four items for applications to verify. First, applications should not assume a hardcoded token length. Second, any regular expression used to validate installation tokens is updated to handle additional underscores and the presence of a JWT. Third, database columns for token storage and header settings accept at least 520 characters. Finally, code that examines or validates tokens should treat tokens beginning with
ghs_ as opaque strings.Regarding the second item, the announcement provides the following recommended regular expression, designed to work with both the new and legacy formats:
ghs_[A-Za-z0-9\.\-_]{36,}
A note from the editor, dated May 26, 2026, appears in the body of the announcement, indicating that the information regarding the regular expression format has been updated.
Editor’s note (May 26th, 2026): Updated the regex format guidance.
The specifics of this update can be verified by examining previous versions on the Internet Archive. In versions saved on May 16, 2026, and May 23, 2026, the recommended regular expression was:
ghs_[A-Za-z0-9\._]{36,}
In the version saved on May 28, 2026, and in the version on the verification date, the recommended pattern is
ghs_[A-Za-z0-9\.\-_]{36,}. Comparing the content of the version from May 23, 2026, with the version from May 28, 2026, the only difference is the addition of \- (hyphen) to the character class. The editor's note itself does not appear in the May 28, 2026, version, but first appears in the version saved on June 5, 2026.GitHub does not state the reason for adding the hyphen. As described in section 3.3, the character set for JWT base64url includes both
- and _. However, this article does not present this as GitHub's explanation. What the Internet Archive versions show is that the recommended regular expression GitHub itself provided was rewritten less than two weeks after it was provided. Even the expression provided by those who define the format can be revised after it is initially provided.The announcement also describes a testing method. Request a token with
enabled to receive a new-format token, and confirm that the application accepts it end to end. Request a token with disabled to receive a legacy-format token, and confirm that the application also works with the legacy format. The latter is to ensure that the application can gracefully degrade its functionality if the new token format becomes temporarily unavailable. After testing both, the header should be removed.Test with disabled: Confirm your app also works with the classic opaque format, so it degrades gracefully if stateless tokens are ever temporarily unavailable.
The editor's note from June 10, 2026, for this announcement states that a link to support contact information was removed. This is unrelated to the regular expression.
4.4 October 2, 2026 — Completion, and the Header Deprecation Planned for November 30, 2026
The announcement dated October 2, 2026, confirms the completion of the staged rollout that began on April 27, 2026. Newly issued installation tokens will default to the new format (ghs_APPID_JWT).The staged rollout of the stateless GitHub App installation token format, which began on April 27, 2026, is complete.
According to the same announcement, the temporary header
X-GitHub-Stateless-S2S-Token is scheduled to be deprecated on November 30, 2026. After that date, GitHub will no longer respect this header, and eligible applications will always receive new-format tokens. The announcement requests that users remove the header from their production code before November 30, 2026, after checking their applications and workflows with both formats.The temporary X-GitHub-Stateless-S2S-Token request header, which we introduced so you could validate the new format on demand, will be deprecated on November 30, 2026.
As of the verification date (October 8, 2026), the header deprecation is still planned. After November 30, 2026, it is necessary to confirm that the deprecation has actually taken place by checking the GitHub Changelog.
The last updated date for the announcement from October 2, 2026, was October 7, 2026. This article compared the content of the Internet Archive versions from October 3, 2026, and October 6, 2026, as well as the version from the verification date. The text content was identical. The last updated date embedded in the page was October 2, 2026, in the October 6, 2026, version, and October 7, 2026, in the version from the verification date.
4.5 Where the Plan and the Actual Rollout Diverged
In the April 24, 2026 plan, the rollout to all installation tokens was to begin between mid-May and late June 2026. Completion was actually announced on October 2, 2026. The sources this article read do not state when each planned stage actually switched.The notes in GitHub Docs are also still written as if the rollout were in progress. The pages for generating installation access tokens, GitHub token formats, and the GitHub Apps section of the REST API all contain the same note. This note mentions the staged rollout that began on April 27, 2026, notes that applications relying on exactly 40 characters may not correctly handle the new format, and says that a temporary request header can be used for testing. However, it does not mention the completion of the rollout.
Starting April 27, 2026, GitHub began a staged rollout of a stateless format (ghs_APPID_JWT) to all newly minted GitHub App installation tokens, making them more performant and improving the reliability of our API surface.
5. Where the Assumption Was Written — A Check Table Built from GitHub's Four Items
This section will use the four areas of review that GitHub identified in its announcement on October 2, 2026, as the rows in a table. The number of rows will not be increased or decreased. Each row lists the matching wording in the earlier announcements, the way to check that the sources describe, and the published articles to which this article delegates the discussion.
5.1 How to Read the Check Table
The announcement on October 2, 2026, asks readers to confirm that every system that handles installation tokens treats them as opaque strings, listing four locations to check.If you haven’t already, confirm that every system that handles installation tokens treats them as opaque strings. Look for:
This article makes these four items the rows of a Check Table. The table has five columns.
Where to Check: This column will specify the location to be checked.What GitHub Says to Look For (2026-10-02): This column will list the items from the October 2, 2026, announcement, using the original English wording.Related Wording in Earlier Changelogs: This column will include the corresponding descriptions from the announcements dated April 24, 2026, and May 15, 2026.How to Check: This column includes only the ways to check that the sources describe. If the sources only describe general principles and do not specifically name the subject of that row, that fact should be noted.Delegated To: This column lists the published articles to which this article delegates the discussion of size, truncation, and runner masking.
5.2 The Check Table
| Where to Check | What GitHub Says to Look For (2026-10-02) | Related Wording in Earlier Changelogs | How to Check | Delegated To |
|---|---|---|---|---|
| Validation and Patterns | Validation that requires tokens to be exactly 40 characters or patterns written for the legacy format. | On 2026-04-24, it stated that applications should not rely on the length of access tokens, noting that regular expressions like ghs_[A-Za-z0-9]{36} may not match new tokens. On 2026-05-15, it requested that applications not assume a fixed token length and asked that regular expressions be updated to handle additional underscores and the presence of a JWT, recommending the pattern ghs_[A-Za-z0-9\.\-_]{36,}. On 2026-05-15, it also requested that code validating or examining tokens treat ghs_ tokens as opaque strings. | On 2026-05-15, it asked that tokens be received with both enabled and disabled and that the application be confirmed to accept both formats. The format of a received token can be told from the number of dots after ghs_. | N/A (Main body of this article) |
| Storage Locations (Database Columns, Secret Stores, Environment Variables) | Database columns, secret stores, or environment variables with a fixed or small maximum length. | On 2026-04-24, it stated that database columns should be able to accommodate strings of at least 520 characters. On 2026-05-15, it requested that database columns storing tokens should accept strings of at least 520 characters. | On 2026-05-15, it asked that the application be confirmed to accept, end to end, a token received with enabled. Ways to check secret stores and environment variables are not named. | Size is discussed in section 7.2, section 7.3, and FAQ Q8 of What Fills an AWS STS Session Token. |
| Proxies, Gateways, Middleware | Proxies, gateways, or middleware that truncate or reject long Authorization headers. | On 2026-05-15, it requested that header configurations should accept strings of at least 520 characters. | Ways to check proxy and gateway configurations are not named. | An example where authentication fails due to truncation is described in section 3.2 of IAM Authentication to Databases, Caches, and Streams on AWS. Header buffer information is in section 7.2 of the STS article. |
| Logging and Secret Redaction Rules | Logging and secret redaction rules that only match the legacy token pattern. | Neither 2026-04-24 nor 2026-05-15 contains a corresponding item. | GitHub's three announcements from 2026 do not specify how to check this. As a general rule, the GitHub Actions documentation states that runner masking largely relies on exact matches of secret values and that sensitive values that a workflow generates from secrets should be registered as secrets. Installation tokens are not explicitly mentioned. | General information about runner masking is found in section 8.2 of Hardening GitHub Actions for AWS Deployments. |
The checks in the
How to Check column that use the temporary header's enabled and disabled values apply only when installation tokens are issued through the REST API, and they can be used, at the latest, until the planned deprecation date, November 30, 2026. Paths that go through proxies or gateways can be checked at the same time by passing a token received with enabled through end to end. However, this is a supplementary note from this article, not a way to check proxies that GitHub describes.The second and third rows of the Check Table address areas where size and format issues overlap. This article lists only the lower bounds and ways to check that GitHub gives for these two rows, leaving the determination of column width and buffer size to the STS article. The STS article emphasizes the importance of avoiding hardcoding the current maximum limits directly into the system, referencing AWS documentation.
5.3 Row 1 — Validation and Patterns
Row 1 is the core of this article. Both the condition that checks length and the regular expression that checks format write the shape of the token into the code. The announcements from April 24, 2026, and May 15, 2026, state three things about this row.First, GitHub's basic recommendation is to treat tokens as opaque strings and not to validate them against hardcoded patterns (April 24, 2026). Second, if regular expressions are still necessary, there is a recommended expression that works for both the new and legacy formats (May 15, 2026). Third, that recommended expression itself has been rewritten once, as the note dated May 26, 2026, says (section 4.3).
Taken together, these points demonstrate that simply replacing the existing code with the recommended expression is not sufficient. The recommended expression is the expression as of the verification date, intended as a replacement for the expression in code that validates tokens with a regular expression. GitHub does not recommend performing validation with regular expressions in and of itself.
5.4 The Period When the Two Formats Coexist
Systems that handle installation tokens may receive both formats for some time. Based on the sources as of the verification date, the following can be stated:- Tokens issued before the change keep working until they expire (October 2, 2026 announcement). The expiration of installation tokens issued through the REST API remains one hour. The lifetime of
GITHUB_TOKENis described separately (section 3.4). - By adding the temporary header with
disabledto a REST API request that issues an installation token, systems can receive legacy-format tokens (May 15, 2026 announcement). The announcement dated October 2, 2026, states that after November 30, 2026, GitHub will no longer respect this header. The May 15, 2026 announcement presentsdisabledas a way to opt out temporarily during the rollout while an application is updated, and the October 2, 2026 announcement says that the rollout is complete. It can be read thatdisabledworks until November 30, 2026, but neither announcement says so explicitly. - GitHub Enterprise Server is not affected by this change (April 24, 2026 and May 15, 2026 announcements). If that holds, systems that handle tokens from both GitHub Enterprise Cloud and GitHub Enterprise Server will receive both formats (the GitHub Enterprise Server documentation pages carry the same rollout note as the GitHub Docs pages; section 7.2).
- GitHub asks developers to confirm that their applications also work with the legacy format in case new-format tokens become temporarily unavailable (May 15, 2026 announcement).
Therefore, adapting exclusively to the new format and continuing to support only the legacy format both amount to writing an assumption about the token format into the code.
5.5 Runner Masking and Log Redaction
For row 4, the three GitHub announcements from 2026 do not specify how to check this. The clue lies in the general guidelines within GitHub Actions' Secure use reference. This page states that runner masking (called secret redaction on the page) largely relies on exact matches of specific secret values. Furthermore, it asks that if a workflow creates sensitive values from secrets, those values should also be registered as secrets. The example the page gives is a JWT that the workflow creates by signing with a private key, which is distinct from the JWT found within installation tokens. The general principles of runner masking are discussed in section 8.2 of Hardening GitHub Actions for AWS Deployments.This page provides general guidelines and does not specifically mention installation tokens. In contrast, the announcement dated October 2, 2026, lists logging and secret redaction rules that only match the legacy token pattern. Runner masking relies on matching values, while the redaction rules of the logging infrastructure may rely on patterns. The latter, like row 1, is a place where the shape of a token is written as a pattern.
GitHub's secret scanning also uses patterns to identify tokens. The "Supported secret scanning patterns" page lists the GitHub App installation access token (
github_app_installation_access_token) as a target pattern and includes a link to a note. This note states that service providers periodically update the patterns used to create tokens and may support multiple versions of a single token. It also states that push protection only supports the most recent token versions that secret scanning can identify with confidence.Service providers update the patterns used to generate tokens periodically and may support more than one version of a token. Push protection only supports the most recent token versions that secret scanning can identify with confidence.
This note also provides general guidelines and does not specifically mention new formats. No statement of whether GitHub's secret scanning detects new-format installation tokens was found in the sources this article read (section 7.6).
6. Outside GitHub — What Other Issuers Changed, and What They Declare in Advance
This section presents examples from issuers outside GitHub, based only on verified primary sources. It divides them into two groups by what this article cites them for: those that have altered the length or format, or have announced such changes (GitLab, Slack), and those that proactively declare potential changes in length or format (Google, Microsoft Entra, Stripe, AWS STS). This is not an exhaustive list.6.1 GitLab CI/CD Job Tokens — JWT by Default, with Known Issues Listed in the Documentation
According to the GitLab CI/CD job tokens page, starting with GitLab 19.0, job tokens default to using the JWT standard. GitLab 19.0 was released on May 21, 2026. While projects can continue using the legacy format through a setting at the top-level group level, this setting will only be available until the release of GitLab 20.0. The same page notes that this setting was introduced in GitLab 17.10. The section on known issues also mentions problems with JWT-formatted job tokens in GitLab 18.8 and earlier, indicating that the JWT format was available before version 19.0.Beginning in GitLab 19.0, CI/CD job tokens use the JWT standard by default. Projects can continue to use the legacy format by configuring the top-level group for their project. This setting is only available until the GitLab 20.0 release.
The GitLab 17.11 version of the same page gave a different schedule: JWT by default beginning in GitLab 18.0, already used by all new projects created after February 21, 2025 on GitLab.com or from 17.10 on GitLab Self-Managed, and a legacy-format setting available until the GitLab 19.0 release.
Beginning in GitLab 18.0, CI/CD job tokens use the JWT standard by default. All new projects created after February 21, 2025 on GitLab.com or from 17.10 on GitLab Self-Managed use this standard. Existing projects can continue to use the legacy format by configuring the top-level group for their project. This setting is only available until the GitLab 19.0 release.
The current version of the page lists known issues related to JWT-formatted job tokens, one of which is the
base64 command's line wrapping. GitLab's documentation states that the base64 command, by default, wraps strings longer than 79 characters. When a JWT-formatted job token is encoded using base64 within a job, the token becomes invalid. GitLab recommends using base64 -w0 to disable line wrapping.The default behavior of the base64 command wraps strings that are longer than 79 characters.
To fix this issue, use base64 -w0 to disable automatically wrapping the token.
The section on known issues also highlights a bug with versions 0.5.0 and earlier of the EC2 Fargate custom executor, as well as an issue in GitLab 18.8 and earlier where some jobs (those using
needs, child pipelines, and long-running jobs) could fail with a 403 error. According to the current version of the page, the token passed to jobs on another CI system became JWT by default in 2026, the same year as GitHub's change, and its issuer lists the known issues in its documentation (the Fargate and base64 items already appear in the 17.11 version). The base64 line wrapping issue is an example of how a tool's default behavior can corrupt long tokens.A search of the GitLab 19.0 release notes for
JWT and job token found no item that made JWT the default for job tokens. This article bases the timing on the current version of the job token page and takes only the release date from the release notes.6.2 Automatic Revocation of GitLab Personal Access Tokens — Revocation Was Tied to a Single Detection Rule
GitLab's automatic response, an Ultimate feature, revokes a GitLab personal access token when secret detection finds that token leaked in a public project. According to GitLab's documentation, automatic revocation is enabled by default on GitLab.com, while administrators must enable it in GitLab Self-Managed and GitLab Dedicated environments. The release notes for GitLab 19.4 (released September 17, 2026) describe the scope of revocation prior to version 19.4 as follows:In GitLab versions earlier than 19.4, revocation used only one detection rule and revoked only the legacy token format. Tokens created on GitLab 18.3 and later use the routable or versioned routable format. GitLab detected and reported these tokens without revoking them.
Prior to 19.4, revocation only utilized a single detection rule and only revoked tokens in the legacy format. Tokens created in GitLab 18.3 and later used either the routable or versioned routable format. While GitLab detected and reported these tokens, it did not revoke them. Starting with GitLab 19.4, revocation now recognizes three detection rules:
gitlab_personal_access_token, gitlab_personal_access_token_routable, and gitlab_personal_access_token_routable_versioned. No configuration changes are required.This example is of a type close to row 4 of the Check Table. After the token format changed, the response to a leak (revocation) only worked on legacy-format tokens. In this example, however, what was tied to the legacy format was the revocation on the side of GitLab itself, the issuer of the token, not the system that receives the token.
The Account and limit settings page provides another example where the detection relies on a specific format. Personal access tokens have a default prefix of
glpat-, but administrators of GitLab Self-Managed and GitLab Dedicated environments can change this. By default, client-side secret detection, secret push protection, and pipeline secret detection do not detect tokens with custom prefixes. The same page notes that this can lead to an increase in false negatives and that pipeline secret detection can be customized to detect tokens with custom prefixes.By default, client-side secret detection, secret push protection, and pipeline secret detection do not detect tokens that have a custom prefix.
6.3 Slack — Announcing Longer Tokens in 2016 and Warning Against Relying on Their Meaning
Slack's August 23, 2016, changelog (Token lengthening) announced that, starting the following month, newly issued tokens would be longer than previously. The change, around September 20, 2016, applied to newly issued user tokens, bot user tokens, and test tokens. Slack noted that it had not previously documented the length of token strings.Beginning next month, newly issued tokens will be longer than previously issued tokens.
Newer tokens will be at least twenty characters longer.
The same changelog also advised future-proofing storage and anticipating tokens up to 255 characters long. It provided examples such as
VARCHAR(255) and TINYTEXT, and strongly advised against relying on any potentially readable meaning within the token strings.We strongly recommend not relying on any perceived semantics found in token strings.
As in GitHub's 2021 announcements, a guideline of 255 characters appears here. Both are written as advice on how long a token to prepare for. GitHub's 2026 installation tokens exceeded the 2021 guideline (see section 4.1).
Slack's current token documentation says that user tokens created before August 2016 may have secrets of 6 or 10 characters instead of 32, while Slack's 2016 changelog gives the timing of the lengthening as around September 20, 2016.
6.4 Issuers That Declare in Advance That Length or Format Can Vary
Some issuers state in their documentation, in advance, that length or format can vary. The table below lists the issuers that this article cites mainly for such statements (section 2.1).| Issuer | What the Issuer Says About Length or Format | What It Applies To | Where the Source Says So |
|---|---|---|---|
| The size of tokens can vary within certain limits. Authorization codes are up to 256 bytes, access tokens are up to 2048 bytes, and refresh tokens are up to 512 bytes. Google reserves the right to vary the size of tokens within these limits, and applications must be able to handle tokens of variable size. | OAuth 2.0 tokens for Google APIs (access tokens returned by the Google Cloud Security Token Service API have different limits). | Google for Developers (Token size, within "Using OAuth 2.0 to Access Google APIs"). | |
| Microsoft Entra | Client applications should treat access tokens as opaque strings and should not attempt to validate them. Tokens that Microsoft APIs receive might not always be JWTs that can be decoded. The number of object IDs that can be included in the "groups" claim is capped to fit the size limit of the HTTP header; if the number of groups exceeds the cap, an "overage" claim will be used instead of the "groups" claim. | Microsoft Entra access tokens. | Microsoft Learn (Access tokens, Access token claims reference). |
| Stripe | Stripe considers changes to the length or format of opaque strings (including the addition or removal of a fixed prefix) to be backward-compatible changes. Stripe-generated object IDs can be up to 255 characters long. | The examples the source gives are object IDs, error messages, and similar strings. The passage does not mention API keys (this article does not apply it to API keys). | Stripe Docs (How API versioning works). |
| AWS STS | The size of security tokens returned by the STS API is not fixed, and AWS strongly recommends against assuming a maximum size. | STS session tokens (discussed in the STS article). | AWS STS API Reference (AssumeRole). |
The relevant section from Google's documentation is as follows:
Google reserves the right to change token size within these limits, and your application must support variable token sizes accordingly.
Microsoft Entra's Access tokens page says that clients should not validate access tokens. This aligns with the guidance GitHub provided to clients regarding JWT (see section 3.3).
Although client applications can receive and use access tokens, they should treat them as opaque strings. The client application shouldn't attempt to validate access tokens.
Microsoft Entra's Access Token Claims Reference page discusses the size of the "groups" claim in relation to the maximum size of HTTP headers.
Microsoft Entra ID limits the number of object IDs that it includes in the groups claim to stay within the size limit of the HTTP header.
The description from Stripe appears to refer to object IDs, rather than API keys, based on the examples provided in the documentation. This article does not apply that description to API keys.
Changing the length or format of opaque strings, such as object IDs, error messages, and other human-readable strings.
The AWS STS API Reference states the following. The discussion of session token size, including the longer version 2 tokens, is left to the STS article.
The size of the security token that AWS STS API operations return is not fixed. We strongly recommend that you make no assumptions about the maximum size.
6.5 What the Sources Have in Common
Across the documents reviewed for this article, despite variations in phrasing, there are several common points. Issuers change the length and format of their tokens. GitHub and GitLab have already implemented such changes. Slack announced in 2016 that it would make tokens longer. Google states that it reserves the right to adjust the size of tokens within specified limits. Stripe states that it considers changes to the length and format of opaque strings, such as object IDs, to be backward-compatible changes. GitHub and Microsoft Entra also ask users to treat tokens as opaque strings, and Slack strongly recommends not relying on any perceived meaning in token strings.However, this is what the sources of the seven issuers this article checked say, not a claim about all issuers.
7. Where the Sources Disagree and Where No Statement Was Found
This section outlines the primary areas where the different source materials present conflicting information, as well as the main areas where this article was unable to locate relevant information despite searching. Where sources disagree, this article does not call either one wrong. Where no statement was found, it gives the search terms and scope.7.1 Four Ways of Describing the Length
GitHub's sources describe the length of new installation tokens in four ways: about 520 characters (April 24, 2026 and May 15, 2026), varying with the data stored (April 24, 2026), at least 520 characters (what database columns, and in the May 15, 2026 announcement also header settings, should accept: a preparation item on April 24, 2026, and a check item on May 15, 2026), and about 520 characters instead of 40 (October 2, 2026) (see section 3.2). The four do not contradict each other. None of them gives 520 as an upper limit. This article does not round the four descriptions into one value.7.2 The GitHub Docs Notes and the October 2, 2026 Completion Announcement
As to the rollout's status, the notes on the three GitHub Docs pages state only that the staged rollout began on April 27, 2026, and do not mention completion. The announcement dated October 2, 2026 (section 4.5) states that the rollout is complete. As of the verification date, the Docs notes had not yet caught up with the announcement.The same note also appears on the corresponding pages of the GitHub Enterprise Server documentation (for example, the page on generating an installation access token in version 3.22). The April 24, 2026 and May 15, 2026 announcements say that GitHub Enterprise Server is not affected. This article does not call either the GitHub Enterprise Server note or the announcements wrong.
7.3 The Revision of the Recommended Regular Expression
The recommended regular expression, as announced on May 15, 2026, wasghs_[A-Za-z0-9\._]{36,} in the versions saved on May 16, 2026, and May 23, 2026. In the version saved on May 28, 2026, and the version on the verification date, it was ghs_[A-Za-z0-9\.\-_]{36,} (see section 4.3). The announcement says in a note dated May 26, 2026, that the regex guidance was updated, but it does not say what changed. The differences can be observed by comparing the versions on the Internet Archive. The expression was modified between the versions saved on May 23, 2026, and May 28, 2026, and the note first appears in the version saved on June 5, 2026.7.4 The Revision of the October 2, 2026 Announcement
The last updated date of the announcement dated October 2, 2026, is October 7, 2026. This article compared the text of the version saved on October 6, 2026 (prior to the revision) with the version available on the verification date, and found no differences (see section 4.4). This article cannot tell what the revision changed.7.5 The Number of GitLab Detection Rules
There are discrepancies within GitLab's documentation. The release notes for GitLab 19.4 and the "Automatic response to leaked secrets" page both list three detection rules for personal access tokens. However, the list of rules on the "Detected secrets" page only mentions two:gitlab_personal_access_token and gitlab_personal_access_token_routable, and does not include gitlab_personal_access_token_routable_versioned.7.6 Where No Statement Was Found
For the following items, this article found no statement. Not finding a statement does not mean that none exists.- Maximum length of installation tokens. Scope: the five changelog entries and the 12 GitHub Docs pages. Search terms:
maximum,max,length,characters,520,at least, andvary(section 3.2). - Description of temporary header names and values in GitHub Docs. The column for headers in the endpoint that creates installation access tokens in the GitHub Apps section of the REST API lists only
accept. TheX-GitHub-Stateless-S2S-Tokendoes not appear anywhere in the 12 pages of GitHub Docs. The notes on the three Docs pages mention that a temporary request header exists and include a link to the changelog. Within the sources this article read, header names and values appear only in the changelog. - A way to select the format of
GITHUB_TOKENwith the temporary header (section 4.3). - The dates on which each planned stage actually switched. Individual announcements regarding brownout periods were also not found. The scope is the search results for
brownoutin the GitHub Changelog (sections 4.2 and 4.5). - Whether the 2021 guidance on 255 characters was withdrawn (section 4.1).
- Whether GitHub's secret scanning detects new-format installation tokens. The scope includes the "Supported secret scanning patterns" page (pattern table and token version notes), and the secret scanning changelog for 2026 (search for
ghs_andstateless) (section 5.5). - Further information regarding changes to the format of user-to-server tokens. The scope is the search results for
user-to-serverin the GitHub Changelog (section 3.5). - Length and structure of the legacy format of GitLab CI/CD job tokens, and whether JWT-format tokens also carry the
glcbt-prefix (section 2.3). - An item in the GitLab 19.0 release notes that made JWT the default for job tokens (section 6.1).
- Length of routable tokens in GitLab. The scope includes GitLab product documentation (list of tokens, personal access tokens, admin settings, automatic response, detected secrets, API, CI/CD job token, runner pages). While the GitLab handbook's design documents mention the size of routable tokens, this article does not consider those documents as they are not part of the product documentation.
8. Frequently Asked Questions about the GitHub App Installation Token Format
This article addresses common questions that arise when reviewing pipelines that handle installation tokens.Q1. Is a GitHub App installation token now always about 520 characters long?
No, that is not necessarily the case. While GitHub states that it is approximately 520 characters, it also notes that the length can vary depending on the data stored within it. A preparation item (April 24, 2026) and a check item (May 15, 2026) ask that database columns (and, on May 15, 2026, header settings) accept at least 520 characters. Within the scope checked for this article, no statement of a maximum length was found (see sections 3.2 and 7.1). It is advisable not to assume that 520 characters is a fixed length.Q2. How long do tokens issued in the legacy format remain usable?
Tokens issued before the format change remain usable until they expire (section 3.4). The expiration of installation tokens issued through the REST API remains one hour, and this change does not affect that (the lifetime ofGITHUB_TOKEN is described separately on the GITHUB_TOKEN page in GitHub Docs). Also, it can be read from the sources as of the verification date that if you add the temporary header with disabled to a request that issues an installation token through the REST API, you can still receive newly issued legacy-format tokens until the planned deprecation date, November 30, 2026 (section 5.4). The April 24, 2026 and May 15, 2026 announcements say that GitHub Enterprise Server is not affected (however, the GitHub Enterprise Server documentation pages carry the same rollout note as the GitHub Docs pages; see sections 3.5, 5.4, and 7.2).Q3. Is the GitHub Actions GITHUB_TOKEN also in scope for the new format?
Yes, it is included. The announcements from April 24, 2026, and May 15, 2026, include GITHUB_TOKEN in the scope of the new format. GitHub Docs also states that the GITHUB_TOKEN is an access token for GitHub App installations. The announcement from October 2, 2026, states that the rollout to all newly issued installation tokens is complete, although it does not specifically mention GITHUB_TOKEN. The plan from April 24, 2026, included GITHUB_TOKEN in the first stage, but this article has not confirmed when the switch actually occurred (see sections 3.5 and 4.2).Q4. Do GitHub Enterprise Server installation tokens also change?
The announcements dated April 24, 2026, and May 15, 2026, state that GitHub Enterprise Server is not affected. The completion announcement dated October 2, 2026, does not mention GitHub Enterprise Server. If the two announcements hold, systems that handle both GitHub Enterprise Cloud and GitHub Enterprise Server tokens receive both token formats. However, the GitHub Enterprise Server documentation pages carry the same rollout note as the GitHub Docs pages (see sections 3.5, 5.4, and 7.2).Q5. Should the JWT inside the token be decoded and validated?
No. GitHub states that a GitHub-internal issuer signs this JWT and that client applications cannot validate it and should not. Client applications must not depend on the contents of the JWT. If you only need to tell the format of a token received during testing, GitHub itself gives a method: count the dots afterghs_ (see section 3.3).Q6. Which regular expression should be used to validate installation tokens?
What GitHub recommends first is treating the token as an opaque string and avoiding validation using hardcoded patterns (April 24, 2026, section 4.2). However, if you require a regular expression, the announcement from May 15, 2026, suggestsghs_[A-Za-z0-9\.\-_]{36,} as a recommended pattern that works for both the new and legacy formats. This pattern is the version after the rewrite that the note dated May 26, 2026, mentions; the version before the rewrite did not include a hyphen (sections 4.3 and 5.3).Q7. What will happen to the temporary header X-GitHub-Stateless-S2S-Token after November 30, 2026?
According to the announcement on October 2, 2026, the header is scheduled to be deprecated on November 30, 2026. After that date, GitHub will no longer respect the header, and eligible applications will always receive new-format tokens. GitHub is requesting that developers remove the header from their production code prior to that date. As of the verification date, this is the plan (see section 4.4).Q8. Is it enough to make a database column 520 characters wide?
That is not necessarily the case. What GitHub asks is that database columns accept at least 520 characters (April 24, 2026 and May 15, 2026 announcements). Setting the column size to exactly 520 characters would conflict with the statement that the length varies depending on the data stored within the token (section 3.2). The question of whether the column width or buffer size can be determined based on the current maximum is addressed in FAQ Q8 of What Fills an AWS STS Session Token, which discusses AWS STS session tokens.9. Summary
As of the October 2, 2026 completion announcement, newly issued GitHub App installation tokens use theghs_APPID_JWT format by default. The prefix remains ghs_, but they are about 520 characters long instead of 40, and they contain two dots. The GitHub Actions GITHUB_TOKEN is also in the scope of the new format. GitHub Enterprise Server is not affected (as announced on April 24, 2026, and May 15, 2026; however, the GitHub Enterprise Server documentation pages carry the same rollout note as the GitHub Docs pages; section 7.2). The temporary header X-GitHub-Stateless-S2S-Token is scheduled for deprecation on November 30, 2026.The length stands out, but the core of what to check is the format. GitHub gives the token length only as an approximate value (the figure of at least 520 characters is what database columns and header settings should accept), and within the scope checked for this article no statement of a maximum length was found. The first item GitHub lists to check is validation that requires exactly 40 characters and patterns written for the legacy format. Even GitHub's recommended regular expression was rewritten less than two weeks after it was initially presented. In GitLab, revocation of leaked personal access tokens worked only on legacy-format tokens before 19.4.
When handling installation tokens in pipelines, check the following four places:
- Validation and Patterns: Does any code attempt to validate the token format based on length or regular expressions? If so, can it treat the token as an opaque string instead, as GitHub recommends? If regular expressions are used, do they match both the new and the legacy format?
- Storage Locations: Are there any fixed or small maximum lengths imposed on database columns, secret stores, or environment variables (refer to the STS article for details on size limitations)?
- Proxies, Gateways, and Middleware: Do these components truncate or reject long
Authorizationheaders (see the IAM authentication article for examples of truncation)? - Logging and Secret Redaction Rules: Are there any rules that only match the legacy token pattern (refer to the GitHub Actions article for general principles of runner masking)?
It can be read from the sources as of the verification date that applications that use the REST API to issue installation tokens can, until the planned deprecation date of November 30, 2026, receive tokens of both formats with the temporary header's
enabled and disabled values and confirm that the tokens are accepted end to end (section 5.4). This header should be removed from production code before that date. Also keep in mind that patterns rewritten for the new format can fail in the same way when the format changes again.10. References
- Notice about upcoming new format for GitHub App installation tokens - GitHub Changelog
- GitHub App installation tokens: Per-request override header - GitHub Changelog
- Stateless GitHub App installation tokens rolled out - GitHub Changelog
- Authentication token format updates - GitHub Changelog
- Authentication token format updates are generally available - GitHub Changelog
- Behind GitHub's new authentication token formats - The GitHub Blog
- GitHub App installation tokens: Per-request override header (archived 2026-05-16) - Internet Archive
- GitHub App installation tokens: Per-request override header (archived 2026-05-23) - Internet Archive
- GitHub App installation tokens: Per-request override header (archived 2026-05-28) - Internet Archive
- GitHub App installation tokens: Per-request override header (archived 2026-06-05) - Internet Archive
- Stateless GitHub App installation tokens rolled out (archived 2026-10-03) - Internet Archive
- Stateless GitHub App installation tokens rolled out (archived 2026-10-06) - Internet Archive
- Generating an installation access token for a GitHub App - GitHub Docs
- Generating an installation access token for a GitHub App - GitHub Enterprise Server 3.22 Docs
- Authenticating as a GitHub App installation - GitHub Docs
- About authentication to GitHub - GitHub Docs
- About authentication to GitHub - GitHub Enterprise Server 3.22 Docs
- REST API endpoints for GitHub Apps - GitHub Docs
- REST API endpoints for GitHub Apps - GitHub Enterprise Server 3.22 Docs
- GITHUB_TOKEN - GitHub Docs
- Secure use reference - GitHub Docs
- Supported secret scanning patterns - GitHub Docs
- CI/CD job token - GitLab Docs
- GitLab CI/CD job token (GitLab 17.11) - GitLab Docs
- GitLab 19.0 release notes - GitLab Docs
- GitLab 19.4 release notes - GitLab Docs
- Automatic response to leaked secrets - GitLab Docs
- Detected secrets - GitLab Docs
- GitLab token overview - GitLab Docs
- Account and limit settings - GitLab Docs
- Token lengthening - Slack Developer Docs
- Tokens - Slack Developer Docs
- Using OAuth 2.0 to Access Google APIs - Google for Developers
- Access tokens in the Microsoft identity platform - Microsoft Learn
- Access token claims reference - Microsoft Learn
- How API versioning works - Stripe Docs
- AssumeRole - AWS Security Token Service API Reference
- RFC 7515: JSON Web Signature (JWS)
- RFC 4648: The Base16, Base32, and Base64 Data Encodings
- What Fills an AWS STS Session Token - Session Policies, Session Tags, the Single Size Limit, and How to Measure and Test It
- IAM Authentication to Databases, Caches, and Streams on AWS - Token Lifetime, What Revoking Access Does to Open Connections, and the Identity Inside the Service
- Hardening GitHub Actions for AWS Deployments - Workflow Permissions, Untrusted Triggers, Action Pinning, and What the Trust Policy Cannot Catch
- JWT and JOSE Standards History and Timeline - JWS, JWE, JWK, JWA, JWT, and How the Algorithm Registry Has Changed
- Install-Time Scripts by Package Manager - npm, pnpm, Yarn, Bun, Deno, pip, and uv: What Runs When You Install a Dependency, Since Which Version, and Where the Approval Is Recorded
- Trusted Publishing Beyond npm and PyPI - RubyGems, NuGet.org, crates.io, pub.dev, JSR, and Open VSX: Exchanged or Used Directly, What Trust Is Bound To, and What Each Registry Rejects
References:
Tech Blog with curated related content
Written by Hidekazu Konishi