Broken Object Level Authorization

Broken Object Level Authorization in Go (Gin) [May 2026] [GHSA-55gc-6fmc-fpx9]

[May 2026] Updated GHSA-55gc-6fmc-fpx9

Overview

Broken Object Level Authorization (BOLA) in Go (Gin) enables unauthorized access to resources when an API returns an object based on an ID supplied by the client without ensuring the requester owns or is allowed to access that object. In real-world apps, attackers can enumerate IDs in endpoints like /api/v1/resources/:id and fetch data from other users, potentially exposing sensitive information, audit trails, or system configuration. If write operations are allowed, attackers may also modify or delete other users' resources. In Gin-based services, this vulnerability often appears when the handler retrieves an object by ID from the request path or query and then relies on authentication alone, or applies authorization only at a later layer. Because the code path returns the object before an ownership or policy check, the response can disclose data to unauthorized callers. This class of vulnerability is widely exploited in APIs exposing user data, orders, tickets, or documents. Manifestation in Go/Gin typically involves: using c.Param(`id`) to load a resource; performing a DB query by that ID; returning the resource without verifying owner; or using user-provided IDs in subsequent updates without ownership checks. Attackers can craft requests to access or change resources they do not own, leading to data leakage, integrity breach, and compliance violations. The problem is particularly severe when the API returns 404 instead of 403 to hide the existence of the resource, which can still reveal ownership-based patterns. Remediation strategy includes: implementing strict per-resource authorization in the service layer, centralizing policy checks, adopting RBAC/ABAC, attaching user context via middleware, and writing tests to prove correct access control. Consider returning 403 for unauthorized access and not disclosing existence via 404 for non-owned resources; audit logs to monitor access; limit IDs exposure; and implement nonces or opaque IDs.

Code Fix Example

Go (Gin) API Security Remediation
package main

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

type Resource struct {
  ID      string
  OwnerID string
  Data    string
}

type User struct { ID string }

type InMemoryStore struct { data map[string]Resource }

func (s *InMemoryStore) GetResourceByID(id string) (Resource, bool) {
  r, ok := s.data[id]
  return r, ok
}

var store = &InMemoryStore{data: map[string]Resource{
  "r1": {ID: "r1", OwnerID: "u1", Data: "secret"},
}}

// Vulnerable pattern: fetch by ID without ownership check
func vulnerableGetResource(c *gin.Context) {
  id := c.Param(`id`)
  if res, ok := store.GetResourceByID(id); ok {
    c.JSON(http.StatusOK, res)
  } else {
    c.Status(http.StatusNotFound)
  }
}

// Fixed pattern: enforce ownership before returning resource
func fixedGetResource(c *gin.Context) {
  id := c.Param(`id`)
  u, _ := c.Get(`user`)
  user := u.(*User)
  if res, ok := store.GetResourceByID(id); ok {
    if res.OwnerID != user.ID {
      c.AbortWithStatus(http.StatusForbidden)
      return
    }
    c.JSON(http.StatusOK, res)
  } else {
    c.Status(http.StatusNotFound)
  }
}

func main() {
  r := gin.Default()
  // Mock authentication middleware to attach a user to context
  r.Use(func(c *gin.Context) {
    c.Set(`user`, &User{ID: `u1`})
    c.Next()
  })
  r.GET(`/vulnerable/resources/:id`, vulnerableGetResource)
  r.GET(`/fixed/resources/:id`, fixedGetResource)
  // r.Run()
}

CVE References

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