Mass Assignment in Fiber with Api Keys
Mass Assignment in Fiber with Api Keys — how this specific combination creates or exposes the vulnerability
Mass Assignment occurs when an API binds incoming JSON directly to a server-side struct or model without filtering which fields are allowed. In the Fiber web framework for Go, this commonly happens when developers use c.BodyParser(&model) and then pass that model straight into a database create or update function. If the model contains fields such as ID, Role, IsAdmin, or APIKey, an attacker who can control the request body may set these values explicitly and escalate privileges or access other users’ data.
When API Keys are used for authorization, developers sometimes assume that because a key is present and valid, the request is safe. However, if the API key is only checked for existence or scope and the request body is still bound to a permissive struct, Mass Assignment can bypass intended access controls. For example, an API key belonging to a regular user might be accepted, but the JSON payload could include role: "admin", and if unchecked, the server may create or update a record with that elevated role. This is a classic BOLA/IDOR and Privilege Escalation risk, covered by middleBrick’s Authentication and BOLA/IDOR checks.
In practice, this can lead to scenarios where an attacker enumerates endpoints that accept user-controlled structs, crafts requests with forged fields, and observes changes in behavior or data exposure. middleBrick’s checks for Property Authorization and Unsafe Consumption are designed to detect whether bound input is validated against an allowlist and whether authorization is enforced per operation and per object. Without such validation, an API that relies solely on API keys for authorization remains vulnerable to tampered payloads.
Real-world attack patterns mirror CVE-like scenarios where mass assignment in web frameworks leads to unauthorized record updates. While the scanner does not name specific framework exploits, it flags inputs that map to high-risk fields and recommends explicit field filtering. When scanning an API with middleBrick, findings appear in the Property Authorization and Unsafe Consumption sections, each with severity and remediation guidance.
Api Keys-Specific Remediation in Fiber — concrete code fixes
To secure Fiber handlers that use API keys, ensure that authorization is checked after strict input validation and that only intended fields are bound. Prefer binding to a minimal DTO (data transfer object) and then mapping only the allowed fields to your domain models. Below are two approaches with real, syntactically correct code examples.
Approach 1: Bind to a restricted DTO and validate the API key separately
import (
"github.com/gofiber/fiber/v2"
"github.com/google/uuid"
)
type CreateUserDTO struct {
Email string `json:"email" validate:"required,email"`
Name string `json:"name" validate:"required,min=2,max=100"`
}
func CreateUser(c *fiber.Ctx) error {
var dto CreateUserDTO
if err := c.BodyParser(&dto); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid body"})
}
// Validate DTO fields
if err := validator.New().Struct(dto); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": err.Error()})
}
apiKey := c.Get("Authorization")
if apiKey == "" || !isValidKey(apiKey) {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "invalid api key"})
}
// Ensure the DTO does not contain privileged fields; map explicitly if needed
user := domain.User{
ID: uuid.New(),
Email: dto.Email,
Name: dto.Name,
Role: domain.RoleUser, // default, never from user input
}
// save user...
return c.Status(fiber.StatusCreated).JSON(user)
}
Approach 2: Use explicit field selection and reject unknown fields
import (
"encoding/json"
"github.com/gofiber/fiber/v2"
)
type UpdateProfileRequest struct {
Email *string `json:"email"`
Name *string `json:"name"`
// Do not include ID, Role, APIKey, IsAdmin here
}
func UpdateProfile(c *fiber.Ctx) error {
var req UpdateProfileRequest
if err := json.NewDecoder(c.Body()).Decode(&req); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid json"})
}
apiKey := c.Get("Authorization")
if apiKey == "" || !isValidKey(apiKey) {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "invalid api key"})
}
// Build changes map from only provided non-sensitive fields
updates := make(map[string]interface{})
if req.Email != nil {
updates["email"] = *req.Email
}
if req.Name != nil {
updates["name"] = *req.Name
}
// Do not apply updates to role or id from payload
// id := c.Locals("userID") // derive identity from auth, not body
// service.UpdateProfile(id, updates)
return c.SendStatus(fiber.StatusOK)
}
Key practices that align with middleBrick’s findings:
- Do not bind directly to domain models that contain sensitive or privileged fields.
- Validate and sanitize all input, and treat API keys as credentials for authentication, not as a replacement for per-field and per-object authorization.
- Use explicit field selection or strict allowlists to prevent attackers from injecting fields such as
role,is_admin, orid. - Return generic error messages for validation failures to avoid leaking schema details.
By combining API key checks with disciplined input binding and field-level authorization, you reduce the risk of Mass Assignment bypasses. middleBrick’s scans highlight whether your endpoints exhibit unsafe binding and whether property-level checks are present, helping you prioritize fixes.
Related CWEs: propertyAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-915 | Mass Assignment | HIGH |