Overview
Broken Object Level Authorization (BOLA) vulnerabilities arise when an API fails to verify a caller's right to access a specific object, instead trusting object identifiers or tokens alone. In real-world systems, this can enable access to files, records, or resources after permissions have been revoked, simply because a previously valid link or token still exists. This class of flaw is especially dangerous in file-sharing interfaces where public links grant access to sensitive assets. If permission revocation is not enforced at request time, attackers may access, download, or preview resources they should no longer be permitted to see.
CVE-2026-35604 exemplifies this risk in the File Browser project: before version 2.63.1, when an admin revokes a user's Share and Download permissions, existing share links created by that user remain fully accessible to unauthenticated users because the public share download handler does not re-check the share owner's current permissions. This specific vulnerability is categorized under CWE-863 and was fixed in 2.63.1. In Go (Gin) applications, similar patterns can occur if handlers rely on a public link or token without re-validating the owner's active permissions on each access, leading to stale or revoked permissions being honored by the system.
In a Go (Gin) context, a vulnerable pattern often looks up a resource via a share identifier and serves the file without reloading and validating the owner’s current rights. Attackers can still access the resource if the share exists even after permissions are revoked, because the authorization check happened only at share creation time. The remediation is to perform a fresh authorization check during each access, ensuring the share is active and the owner still has the necessary rights, before serving any resource.
Remediation involves centralizing the access gate for object-level resources and performing real-time checks against both the share state and the owner's permissions. Do not rely on the presence of a public link or a stored token as proof of ongoing authorization. Implement explicit, server-side permission checks in Go (Gin), and validate the owner’s rights each time a resource is requested, with proper error handling and auditing.
Affected Versions
File Browser < 2.63.1 (i.e., 2.63.0 and earlier)
Code Fix Example
Go (Gin) API Security Remediation
// Vulnerable and fixed patterns in one file (Go with Gin)
package main
import (
"net/http"
log "log"
gin "github.com/gin-gonic/gin"
)
type Share struct {
ID string
FilePath string
OwnerID string
Active bool
}
type Owner struct {
ID string
CanDownload bool
Active bool
}
var shares = map[string]Share{
"s1": {ID: "s1", FilePath: `demo/files/report.pdf`, OwnerID: "u1", Active: true},
}
var owners = map[string]Owner{
"u1": {ID: "u1", CanDownload: true, Active: true},
}
func main() {
r := gin.Default()
// Vulnerable route: does not re-check owner's permissions on access
r.GET("/share/download/:shareID", downloadVulnerable)
// Fixed route: re-validates permissions at access time
r.GET("/secure/share/download/:shareID", downloadFixed)
log.Println("Starting server on :8080")
_ = r.Run(":8080")
}
// Vulnerable handler: relies on a public share link without re-validating permissions
func downloadVulnerable(c *gin.Context) {
shareID := c.Param("shareID")
s, ok := shares[shareID]
if !ok || !s.Active {
c.Status(http.StatusNotFound)
return
}
// Vulnerable: no re-check of the owner's current permissions
c.File(s.FilePath)
}
// Fixed handler: performs real-time authorization checks
func downloadFixed(c *gin.Context) {
shareID := c.Param("shareID")
s, ok := shares[shareID]
if !ok || !s.Active {
c.Status(http.StatusNotFound)
return
}
// Re-check owner's current permissions at access time
ow, ok := owners[s.OwnerID]
if !ok || !ow.Active || !ow.CanDownload {
c.Status(http.StatusForbidden)
return
}
c.File(s.FilePath)
}