Broken Object Property Level Authorization

Broken Object Property Level Authorization and Go (Gin) [GHSA-j274-39qw-32c9]

[Updated May 2026] Updated GHSA-j274-39qw-32c9

Overview

Broken Object Property Level Authorization in Go with Gin can lead to unauthorized access to or modification of resources when an API uses a user-supplied object identifier without verifying ownership. In real deployments this enables horizontal privilege escalation: an attacker trivially changes an ID in the request (e.g., /documents/{id}) and retrieves or alters data belonging to another user. This class of flaw often results in data leakage, reputational damage, and potential legal exposure for the application and its operators. In Go applications built with Gin, endpoints frequently fetch resources by ID and return data without confirming that the authenticated user has rights to that specific object. Common patterns include using c.Param("id") to load a record and sending it in the response, or applying a generalized query that does not include an OwnerID/Access control predicate. Attackers exploit this by guessing or enumerating IDs and performing read or write actions if ownership checks are missing or incomplete. Proper handling requires binding the authentication claim (userID, roles) and enforcing ownership or policy checks before returning or mutating resources. Remediation treats authorization as a per-resource concern. Enforce object-level checks in every route that exposes resources, prefer queries that combine the resource ID with the requesting user’s identity (e.g., SELECT ... WHERE id=? AND owner_id=?), and centralize policy logic behind middleware or a policy engine. Add tests that cover ownership scenarios, remove reliance on client-supplied ownership hints, and audit all endpoints for object-level access control gaps. Consider role-based or attribute-based access control, and log authorization decisions for detection and forensics.

Code Fix Example

Go (Gin) API Security Remediation
// Vulnerable pattern
func GetDocument(c *gin.Context) {
  id := c.Param("id")
  doc, err := db.GetDocumentByID(id)
  if err != nil {
    c.AbortWithStatus(404)
    return
  }
  c.JSON(http.StatusOK, doc)
}

// Fixed pattern
func GetDocument(c *gin.Context) {
  user, exists := c.Get("user") // set by auth middleware
  if !exists {
    c.AbortWithStatus(401)
    return
  }
  u := user.(User) // assume a User struct with ID
  id := c.Param("id")
  doc, err := db.GetDocumentByID(id)
  if err != nil {
    c.AbortWithStatus(404)
    return
  }
  if doc.OwnerID != u.ID && !u.IsAdmin {
    c.AbortWithStatus(403)
    return
  }
  c.JSON(http.StatusOK, doc)
}

CVE References

Choose which optional cookies to allow. You can change this any time.