Overview
Broken Object Property Level Authorization (BOPLA) is a class of vulnerability where an API returns an object’s data without validating that the requester owns or is authorized to access that specific object. This kind of flaw was highlighted by CVE-2026-8026, which affected FlowiseAI Flowise up to 3.0.12 and led to information disclosure via an API response handler. The CVE is categorized under CWE-200 (Information Disclosure) and CWE-284 (Improper Access Control), illustrating how missing per-object checks can leak data even when higher-level authentication exists. Although Flowise is not Go/Gin, the core issue translates to Go services that return object data without enforcing per-object ownership, enabling remote attackers to retrieve other users’ data through crafted requests. This vulnerability manifests in services that trust client-supplied identifiers and assemble responses from stored objects without confirming access rights for each object.,
Affected Versions
Flowise up to 3.0.12 (CVE-2026-8026)
Code Fix Example
Go (Gin) API Security Remediation
package main
import (
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
type Resource struct { ID int64; OwnerID int64; Data string }
type User struct { ID int64 }
var db = map[int64]Resource{
1: {ID: 1, OwnerID: 123, Data: "secret-1"},
2: {ID: 2, OwnerID: 999, Data: "secret-2"},
}
func main() {
r := gin.Default()
r.Use(mockAuthMiddleware())
r.GET("/vulnerable/resources/:id", getResourceVulnerable)
r.GET("/fixed/resources/:id", getResourceFixed)
r.Run(":8080")
}
func mockAuthMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// In production, replace with real auth (e.g., JWT) and extract user from token
c.Set("user", User{ID: 123})
c.Next()
}
}
// Vulnerable: returns the resource without validating ownership
func getResourceVulnerable(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid id"})
return
}
res, ok := db[id]
if !ok {
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
return
}
c.JSON(http.StatusOK, res)
}
// Fixed: enforce object-level authorization by comparing resource owner to authenticated user
func getResourceFixed(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid id"})
return
}
res, ok := db[id]
if !ok {
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
return
}
userVal, exists := c.Get("user")
if !exists {
c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
return
}
user := userVal.(User)
if res.OwnerID != user.ID {
c.JSON(http.StatusForbidden, gin.H{"error": "forbidden"})
return
}
c.JSON(http.StatusOK, res)
}