Null Pointer Dereference in Fiber with Jwt Tokens
Null Pointer Dereference in Fiber with Jwt Tokens — how this specific combination creates or exposes the vulnerability
A null pointer dereference in a Fiber application that uses JWT tokens typically occurs when the code attempts to access properties or methods on a JWT payload or on the parsed token object without first confirming the object is non-nil. In Go, a nil pointer or nil map access triggers a runtime panic, which can crash the handler or, in some configurations, return a 500 error that reveals stack traces.
When JWT tokens are parsed, the resulting claims structure may be nil if parsing fails, if the token is malformed, or if required claims are missing. If the handler proceeds to access claims without validation, it dereferences a nil pointer. For example, retrieving a subject claim (sub) or roles without checking for existence can directly cause this condition.
This risk is heightened when the application mixes authentication and authorization logic. A handler might assume a valid JWT always results in a populated claims map or struct, but middleware may skip parsing under certain routes or when tokens are missing. In such cases, the unauthenticated attack surface exposed by tools like middleBrick can detect endpoints where missing or malformed tokens bypass expected checks and lead to null dereferences.
Another common scenario involves extracting roles or permissions from JWT claims to enforce access control. If the roles claim is absent or the claims map itself is nil, iterating or indexing without guards will panic. Because these paths are often not covered by standard unit tests that use valid tokens, they remain vulnerable in production when attackers supply edge-case tokens.
Tools that scan API endpoints without credentials, such as middleBrick, exercise unauthenticated routes and can surface endpoints where missing or malformed JWT handling leads to server errors. These findings highlight the importance of validating token presence and claims before any property access in Fiber handlers.
Jwt Tokens-Specific Remediation in Fiber — concrete code fixes
To prevent null pointer dereferences when working with JWT tokens in Fiber, always validate the token and its claims before accessing any properties. Use explicit checks for nil maps and struct fields, and ensure middleware only proceeds when parsing succeeds.
Example 1: Safe parsing and claims validation with a struct.
func ProtectedRoute(c *fiber.Ctx) error {
tokenString := c.Get("Authorization")
if tokenString == "" {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "missing authorization header"})
}
// Remove "Bearer " prefix if present
if strings.HasPrefix(tokenString, "Bearer ") {
tokenString = tokenString[len("Bearer "):]
}
token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(secretKey), nil
})
if err != nil || token == nil || !token.Valid {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "invalid token"})
}
claims, ok := token.Claims.(*CustomClaims)
if !ok || claims == nil {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "invalid claims"})
}
// Now it is safe to access claims fields
if claims.Role == "" {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "insufficient permissions"})
}
return c.JSON(fiber.Map{"role": claims.Role, "sub": claims.StandardClaims.Subject})
}
Example 2: Safe access with a map-based claims representation.
func AdminRoute(c *fiber.Ctx) error {
raw := c.Locals("user")
if raw == nil {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "user context missing"})
}
claims, ok := raw.(map[string]interface{})
if !ok {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "invalid user context type"})
}
roles, ok := claims["roles"]
if !ok {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "roles claim missing"})
}
roleList, ok := roles.([]interface{})
if !ok || len(roleList) == 0 {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "invalid or missing roles"})
}
// Check role values safely
for _, r := range roleList {
if role, ok := r.(string); ok && role == "admin" {
return c.JSON(fiber.Map{"allowed": true})
}
}
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "admin access required"})
}
Key practices include checking token validity, verifying non-nil claims, using type assertions for map or struct representations, and returning appropriate HTTP status codes instead of allowing nil dereferences. These steps reduce the attack surface that scanners like middleBrick can identify in unauthenticated tests.