jwtutil

package
v0.4.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 20, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package jwtutil provides shared JSON Web Token parsing and classification for the secret/JWT scanner modules. It centralises compact-JWT decoding and the recognition of low-value tokens — most importantly Cloudflare-Access-style pre-authentication "meta" tokens — so the modules don't each re-implement (and drift on) JWT handling.

Index

Constants

This section is empty.

Variables

View Source
var AuthorizationClaims = []string{
	"scope", "scp", "scopes", "roles", "role", "groups", "permissions", "entitlements",
}

AuthorizationClaims are payload claims that grant scope / roles — another sign the token is a usable bearer credential rather than a metadata token.

View Source
var IdentityClaims = []string{
	"sub", "email", "preferred_username", "upn", "unique_name",
	"user_id", "userid", "uid", "username", "name", "oid",
}

IdentityClaims are payload claims whose presence (with a non-empty value) marks a JWT as carrying a real authenticated identity — i.e. a bearer credential.

Functions

func Classify

func Classify(snippet string) (isJWT, sensitive bool)

Classify reports whether snippet is structurally a JWT (decodable header + payload with an "alg" header) and, if so, whether its payload carries authenticated-credential material (see PayloadIsSensitive). Requiring an "alg" header avoids misclassifying an arbitrary dotted base64 triple that happens to decode to JSON as a JWT.

func CrackHMAC

func CrackHMAC(token string, secrets [][]byte) (secret string, alg string, ok bool)

CrackHMAC attempts to recover the HMAC signing secret of a compact JWT by trying each candidate in secrets against the token's signature. It is the single implementation shared by the jwt_weak_secret scanner module and the `vigolium kit jwt-crack` utility, so the two cannot drift.

For an HS256/384/512 token the matching hash is tried. For a token that declares an asymmetric algorithm (RS*/ES*/PS*) every HMAC variant is tried — the algorithm-confusion attack (CVE-2015-9235), where a server that expects to verify an RSA/EC signature with a public key can be tricked into verifying an HMAC signature keyed by that public key — and the returned alg label notes which HMAC variant matched. Returns ok=false when no candidate matches or the token is malformed / uses an unsupported algorithm.

func Decode

func Decode(token string) (header, payload map[string]any, ok bool)

Decode splits a compact JWT and base64url-decodes its header and payload segments into JSON objects. ok is false unless the snippet is a three-segment token whose first two segments are valid base64url-encoded JSON objects.

func IsChallengeToken

func IsChallengeToken(payload map[string]any) bool

IsChallengeToken reports whether a decoded JWT payload is an edge bot-protection proof-of-work challenge token rather than a credential.

The shape is a `pow` (proof-of-work) claim paired with the puzzle parameters the client must solve — `ch`/`challenge` (the nonce) and `dif`/`difficulty` (the leading-zero-bit target). Netlify's bot-challenge interstitial serves exactly this on its 403 page:

{"iss":"netlify","sub":"<visitor IP>","aud":["sec-challenge.netlify.com"],
 "exp":…,"nbf":…,"iat":…,"ch":"2f91d310872a20e3","dif":16,"pow":true}

It authorizes nothing: it is minted FOR the anonymous visitor, scoped to the challenge service, and expires in well under a minute. Without this guard the IP-valued `sub` reads as an identity claim and the token grades as a leaked High-severity credential on every challenged host.

Both a `pow` claim and one puzzle parameter are required, so a real token that merely happens to carry a `ch`/`dif` claim is untouched — no bearer credential advertises a proof-of-work claim alongside its puzzle.

func IsJWT

func IsJWT(s string) bool

IsJWT reports whether s is structurally a compact JWT: three dot-separated segments whose first two are non-empty base64url. It does not require the segments to decode to JSON (use Decode for that).

func IsLowValue

func IsLowValue(snippet string) bool

IsLowValue reports whether snippet is a JWT we cannot confirm carries authenticated-credential material — either it does not decode as a JWT, or it decodes to a pre-auth / metadata token. Non-JWT snippets return false, so the downgrade this drives stays scoped to JWT findings.

func IsPreAuthMetaToken

func IsPreAuthMetaToken(payload map[string]any) bool

IsPreAuthMetaToken reports whether a decoded JWT payload is a pre-authentication / metadata token: a Cloudflare-Access-style meta token (type=meta, or auth_status=NONE), or an edge bot-challenge token (see IsChallengeToken). These are framework-generated tokens the edge hands to an unauthenticated visitor — embedded in /cdn-cgi/access/login/...?meta=<jwt> URLs and reflected into the login page, or baked into a 403 interstitial — not the application's own JWTs, so they are not credentials and carry no meaningful claim-hygiene or weak-secret signal.

func IsPreAuthMetaTokenString

func IsPreAuthMetaTokenString(token string) bool

IsPreAuthMetaTokenString decodes token and reports whether it is a pre-auth / metadata token (see IsPreAuthMetaToken). Returns false for anything that does not decode as a JWT.

func PayloadIsSensitive

func PayloadIsSensitive(payload map[string]any) bool

PayloadIsSensitive decides whether a decoded JWT payload represents a usable bearer credential (true) or a pre-auth / metadata token (false).

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL