highCVSS 7.4Vulnerability

GHSA-fpw6-hrg5-q5x5

## Summary Access tokens created with the "never expire" option have no `exp` JWT claim. Three independent revocation mechanisms fail for this token type. Logout at `internal/handler/auth/auth.go:154` and `:163` dereferences `claims.ExpiresAt.Time`, panicking on the nil field so the token never hits the blacklist. `RevokeToken` at `internal/repository/auth/auth.go:45-50` skips when `remainTTL <= 0`. The admin's "Delete token" panel action at `internal/service/setting/access_token_service.go:183-185` removes the database record but does not call `RevokeToken` to blacklist the JTI. Once a never-expire token leaks, the JWT stays cryptographically valid until the admin rotates the signing key across the entire instance. ## Details Creation path at `internal/util/jwt/jwt.go:103-105`: ```go // expiry = 0 表示永不过期 if expiry > 0 { claims.ExpiresAt = jwt.NewNumericDate(time.Now().UTC().Add(time.Duration(expiry) * time.Second)) } ``` For `NEVER_EXPIRY`, `expiry = 0` and the conditional skips. The resulting JWT has no `exp` claim. The middleware at `internal/middleware/auth.go` accepts it; the `jwt/v5` parser does not require `exp` by default. Failure mode 1, logout panic at `internal/handler/auth/auth.go:163`: ```go // Refresh-token revocation at line 154 (safe in practice: refresh tokens always have exp). // Access-token revocation, same pattern, at line 163 (the bug): if claims, err := jwtUtil.ParseToken(authHeader[7:]); err == nil && claims.ID != "" { remaining := time.Until(claims.ExpiresAt.Time) // nil deref when ExpiresAt is nil h.authService.RevokeToken(claims.ID, remaining) } ``` For a never-expire access token, `claims.ExpiresAt` is nil. `claims.ExpiresAt.Time` panics. Gin's Recovery middleware catches it and returns HTTP 500; the JTI never reaches `RevokeToken`. Line 154 shares the same pattern against refresh tokens, but refresh tokens are always issued with an expiry so the nil dereference does not fire there in practice. Failure mode 2, `Revok

Properties

ghsa_id
GHSA-fpw6-hrg5-q5x5
severity
high
summary
ech0's acess tokens with expiry=never cannot be revoked: logout panics, delete does not blacklist JTI
cvss_score
7.4
cve_id
GHSA-fpw6-hrg5-q5x5
cvss_vector
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
is_ghsa_only
true
ghsa_published
2026-05-07T21:34:01Z
source_url
https://github.com/advisories/GHSA-fpw6-hrg5-q5x5
ghsa_updated
2026-05-07T21:34:01Z

Related Entities (5)

VULNERABLE_TO (1)

[Software]go/github.com/lin-snow/Ech0

AFFECTS (1)

[Software]go/github.com/lin-snow/Ech0

HAS_WEAKNESS (2)

[Weakness]Insufficient Session Expiration
[Weakness]Improper Handling of Exceptional Conditions

REPORTED_BY (1)

[Source]GitHub Advisory Database

Explore deeper with Ninja Signal's threat intelligence graph

GHSA-fpw6-hrg5-q5x5 (CVSS 7.4) — Ninja Signal Threat Intelligence | Ninja Signal