Broken Object Level Authorization

Broken Object Level Authorization in Go (Gin) [May 2026] [GHSA-rpfr-x88x-xwcw]

[Updated May 2026] Updated GHSA-rpfr-x88x-xwcw

Overview

Broken Object Level Authorization (BOLA) is a real-world risk where a request to access an object by ID is not checked against the caller's rights. In production apps, this can leak sensitive data such as documents, orders, or messages to unauthorized users, enabling privacy violations and regulatory exposure. In Go with Gin, BOLA often appears when a handler retrieves a resource by ID from a route parameter (for example, /resources/:id) and returns it without verifying ownership or required permissions. This allows an authenticated user to infer or access resources that belong to others, especially when IDs are predictable or enumerable. Remediation involves validating authorization at the object level: verify the current user against the resource's owner_id or permissions, enforce this in the service or a middleware layer, and return 403 Forbidden when access is not allowed. Consider centralized policy, RBAC/ABAC, and adding tests to cover BOLA paths.

Code Fix Example

Go (Gin) API Security Remediation
package main\n\nimport (\n  \"net/http\"\n  \"github.com/gin-gonic/gin\"\n)\n\ntype User struct { ID string }\ntype Resource struct { ID string; OwnerID string; Data string }\n\nvar resources = map[string]Resource{\n  \"101\": {ID: \"101\", OwnerID: \"u123\", Data: \"Top secret\"},\n  \"102\": {ID: \"102\", OwnerID: \"u999\", Data: \"Public doc\"},\n}\n\n// Vulnerable pattern: returns resource by ID without ownership check\nfunc vulnerableHandler(c *gin.Context) {\n  id := c.Param(\"id\")\n  res, ok := resources[id]\n  if !ok {\n    c.Status(http.StatusNotFound)\n    return\n  }\n  c.JSON(http.StatusOK, res)\n}\n\n// Secure fix: verify ownership before returning\nfunc secureHandler(c *gin.Context) {\n  user := User{ID: \"u123\"} // in real app, extract from JWT\n  id := c.Param(\"id\")\n  res, ok := resources[id]\n  if !ok {\n    c.Status(http.StatusNotFound)\n    return\n  }\n  if res.OwnerID != user.ID {\n    c.Status(http.StatusForbidden)\n    return\n  }\n  c.JSON(http.StatusOK, res)\n}\n\nfunc main() {\n  r := gin.Default()\n  r.GET(\"/vulnerable/resources/:id\", vulnerableHandler)\n  r.GET(\"/secure/resources/:id\", secureHandler)\n  r.Run()\n}\n

CVE References

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