Skip to content

feat(secret): support new stateless format for GitHub App installation tokens #10591

@nikpivkin

Description

@nikpivkin

GitHub is rolling out a new stateless format for ghs_ installation tokens starting April 27, 2026.
The current detection regex will silently miss all tokens in the new format.

Reference: https://github.blog/changelog/2026-04-24-notice-about-upcoming-new-format-for-github-app-installation-tokens/

What is changing

Property Old format New format
Structure ghs_<alphanumeric> ghs_<APPID>_<JWT>
Length Fixed 36 chars ~520 chars (variable)
Character set [0-9a-zA-Z] [0-9a-zA-Z_]

Rollout timeline:

  • April 27 – mid-May 2026: GITHUB_TOKEN, Dependabot, Slack/Teams
  • Mid-May – late June 2026: All GitHub App installation tokens

Currently affects GitHub Enterprise Cloud and Data Residency only; regular github.com is not
affected yet.

Why the current regex fails

Current: (ghu|ghs)_[0-9a-zA-Z]{36}

  1. {36} — new tokens are ~520 chars; exact-length match will never fire.
  2. [0-9a-zA-Z] — new format contains an internal _ separator (ghs_<APPID>_<JWT>).

Suggested implementation

Update the ghs_ branch to accept variable length and underscores while keeping ghu_ strict:

Regex: MustCompileWithoutWordPrefix(`(?P<secret>(?:ghu_[0-9a-zA-Z]{36}|ghs_[0-9a-zA-Z_]{36,}))`),

Or add a dedicated rule for the new format to keep IDs stable:

{
    ID:       "github-app-installation-token",
    Category: CategoryGitHub,
    Title:    "GitHub App Installation Token (stateless format)",
    Severity: "CRITICAL",
    Regex:    MustCompileWithoutWordPrefix(`(?P<secret>ghs_[0-9a-zA-Z]{1,}_[0-9a-zA-Z_]{100,})`),
    SecretGroupName: "secret",
    Keywords: []string{"ghs_"},
},

Acceptance criteria

  • New ghs_ tokens (~520 chars, with internal _) are detected with severity CRITICAL.
  • Existing ghs_[0-9a-zA-Z]{36} and ghu_[0-9a-zA-Z]{36} tokens remain detected.
  • Unit tests cover both old and new token formats.

Test cases

// synthetic token matching new format ghs_<APPID>_<JWT> — must match
"ghs_A1B2C3_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE3NDU2MDAwMDAsImV4cCI6MTc0NTYwMzYwMH0.signature"

// old-format ghs_ token — must still match
"ghs_16C7e42F292c6912E7710c838347Ae178B4a"

// old-format ghu_ token — must still match
"ghu_16C7e42F292c6912E7710c838347Ae178B4a"

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/featureCategorizes issue or PR as related to a new feature.scan/secretIssues relating to secret scanning

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions