fix(redaction): catch ghs_ JWT-format app tokens - #18
Merged
Conversation
GitHub is migrating App installation tokens (and Actions GITHUB_TOKEN)
from short opaque strings to a ghs_-prefixed JWT. Format only -- scopes
and permissions are unchanged.
Verified empirically against this app's own installation, minting both
formats via the temporary X-GitHub-Stateless-S2S-Token override header:
disabled -> ghs_ opaque, 40 chars, 0 dots
enabled -> ghs_ JWT, 383 chars, 2 dots (segments 48/247/86)
The existing named rule /\bgh[ousr]_[A-Za-z0-9]{36}\b/ does NOT match the
new format (wrong length, contains dots, no word boundary). The entropy
backstop still catches it (segment Shannon 4.77/5.52/5.44, all >= 4.2),
so this was a defence-in-depth gap, not an open hole -- but a named,
labelled hit is what makes a scanner report actionable.
Adds a JWT-shaped rule alongside the existing one; both formats coexist
during rollout. Fail-safe: worst case is an extra redaction.
Ref: https://github.blog/changelog/2026-05-15-github-app-installation-tokens-per-request-override-header/
Contributor
Author
Review:
|
| 樣本 | 新 pattern | 舊 gh[ousr]_{36} |
|---|---|---|
ghs_eyJhbGciOiJIUzI1NiJ9.eyJ...J9.abc-DEF_123(JWT 形) |
✅ 中 | ❌ 漏 ← 本 PR 要補的洞 |
ghs_ + 36 字元(classic) |
❌ | ✅ 中(既有那條顧著) |
→ 覆蓋面確實補上、且與既有那條互補不重疊。ReDoS 探測:20k 字元無點輸入 0.07ms,三個 + 被字面 . 隔開,沒有 catastrophic backtracking。
Non-blocking:false positive 方向
[A-Za-z0-9_-]+ 無上界又沒收尾 \b,散文型 ghs_docs.example.com、ghs_token.json.bak 也會中 → HARD block。失敗方向是安全的(擋住而非漏出),而且 docs/redaction.md:104-107 已經把「寫 secret pattern 的文件會自己踩到 pin」記成明文教訓,屬已知取捨。真被誤擋再收斂即可,不擋這 PR。
merge:flightdeck 慣例人閘在 <@615684814736982038>,我只放行不按鍵。
(注:本 PR 由 jonatw-eagle[bot] 開,同一 App 無法 approve 自己的 PR → 以 comment 形式留結論。mergeable_state=blocked 需人類 review 放行。)
jonatw
approved these changes
Jul 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a redaction rule for the new
ghs_-prefixed JWT format that GitHub is rolling out for App installation tokens and ActionsGITHUB_TOKEN. Format change only — scopes and permissions are unchanged.Why — the existing rule goes blind
Current named rule:
It requires exactly 36 alphanumerics and a word boundary. The new token has dots and is ~10x longer, so it does not match.
Evidence (not speculation)
Minted both formats against this app's own installation using the temporary
X-GitHub-Stateless-S2S-Tokenoverride header from the changelog:disabledghs_opaqueenabledghs_JWTRan both regexes against a real new-format token:
So this was a defence-in-depth gap, not an open hole — the entropy backstop already catches it. But a generic
high-entropy token (383 chars)report is much weaker signal for a human than a namedGitHub app token (JWT)hit.Also confirmed the new format works end-to-end against the API (
GET /repos/...-> 200), so no tooling changes are needed anywhere else.Risk
Fail-safe. The rule only ever adds matches; worst case is one extra redaction. The old rule stays — both formats coexist during rollout.
Ref: https://github.blog/changelog/2026-05-15-github-app-installation-tokens-per-request-override-header/