Broken Object Property Level Authorization

Broken Object Property Level Authorization in Go (Gin) [GHSA-p9ff-h696-f583]

[Updated Apr 2026] Updated GHSA-p9ff-h696-f583

Overview

Broken Object Property Level Authorization (BOPLA) vulnerabilities occur when an API returns properties of a resource without properly validating that the authenticated user should access those properties. In Go applications using the Gin framework, this often happens when the code uses an ID from the URL to fetch a resource and then serializes the full object, including sensitive or restricted fields, without verifying ownership for each property. No CVEs are provided for reference in this guide, but the pattern reflects widely observed insecure practices in API endpoints. In practice, endpoints frequently expose profiles, documents, or nested subobjects. An attacker with a valid session can enumerate resource IDs and retrieve larger payloads than intended, gaining access to internal notes, PII, or other restricted fields simply by manipulating the request or the properties included in the response. Because property-level permissions are not enforced, attackers can effectively perform object-level escalation within the same resource. In Gin-based services, the vulnerability tends to appear when the service fetches a resource by ID and then returns a struct or map that includes sensitive properties, or when subobject fields are included in the JSON response without ownership checks. The impact can breach privacy, violate compliance requirements, and erode trust in the API. Remediation approach summary: implement explicit ownership checks before returning any resource properties; use dedicated response models; enforce authorization at the API boundary; instrument tests to cover property-level access; and consider a policy engine or RBAC/ABAC, along with field filtering and least-privilege defaults.

Code Fix Example

Go (Gin) API Security Remediation
package main

import (
  "net/http"
  "github.com/gin-gonic/gin"
)

type User struct {
  ID int
  Name string
  SSN string
}

var users = map[int]User{1: {ID: 1, Name: "Alice", SSN: "123-45-6789"}}

func main() {
  r := gin.Default()

  // Vulnerable: returns full object including sensitive SSN
  r.GET("/vulnerable/users/:id", func(c *gin.Context) {
    c.JSON(http.StatusOK, users[1])
  })

  // Fixed: return only non-sensitive fields after ownership check
  r.GET("/fix/users/:id", func(c *gin.Context) {
    // In real code, validate ownership here
    // For demonstration, we assume ownership is verified
    c.JSON(http.StatusOK, gin.H{ "id": users[1].ID, "name": users[1].Name })
  })

  r.Run()
}

CVE References

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