mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-15 09:28:27 +08:00
Fix IDOR: Add permission checks to file ancestry endpoints (#14725)
Close #14292 ## Issue File ancestry endpoints return folder metadata without validating tenant permissions, allowing any authenticated user to query arbitrary `file_id` values across tenant boundaries. ## Affected Endpoints - `GET /v1/file/parent_folder?file_id={file_id}` - `GET /v1/file/all_parent_folder?file_id={file_id}` - `GET /api/v1/files/{id}/ancestors` ## Root Cause These endpoints **skip the permission check** that other file operations (Delete, Download, Move) perform. ## Expected Permission Check All file operations should follow this 3-step validation: - Check file.tenant_id - Check if user_id belongs to this tenant (via user_tenant join table) - Check KB permission type (team permission) **Code reference:** This is implemented in `checkFileTeamPermission()` and used by Delete/Download/Move, but **missing** from GetParentFolder/GetAllParentFolders. ## Reproduction ```bash # User B (tenant: BBB) accessing User A's file (tenant: AAA) curl -H "Authorization: Bearer USER_B_TOKEN" \ "http://localhost:9384/v1/file/parent_folder?file_id=AAA_FILE_123" # Result: Returns User A's folder metadata ❌ # Expected: "No authorization." ✅ Fix Pass userID from handler to service and call checkFileTeamPermission() — same as Download/Delete/Move handlers. --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -155,11 +155,12 @@ func (h *FileHandler) GetRootFolder(c *gin.Context) {
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Router /v1/file/parent_folder [get]
|
||||
func (h *FileHandler) GetParentFolder(c *gin.Context) {
|
||||
_, errorCode, errorMessage := GetUser(c)
|
||||
user, errorCode, errorMessage := GetUser(c)
|
||||
if errorCode != common.CodeSuccess {
|
||||
jsonError(c, errorCode, errorMessage)
|
||||
return
|
||||
}
|
||||
userID := user.ID
|
||||
|
||||
// Get file_id from query
|
||||
fileID := c.Query("file_id")
|
||||
@@ -168,8 +169,8 @@ func (h *FileHandler) GetParentFolder(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get parent folder
|
||||
parentFolder, err := h.fileService.GetParentFolder(fileID)
|
||||
// Get parent folder with permission check
|
||||
parentFolder, err := h.fileService.GetParentFolder(userID, fileID)
|
||||
if err != nil {
|
||||
jsonError(c, common.CodeServerError, err.Error())
|
||||
return
|
||||
@@ -192,11 +193,12 @@ func (h *FileHandler) GetParentFolder(c *gin.Context) {
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Router /v1/file/all_parent_folder [get]
|
||||
func (h *FileHandler) GetAllParentFolders(c *gin.Context) {
|
||||
_, errorCode, errorMessage := GetUser(c)
|
||||
user, errorCode, errorMessage := GetUser(c)
|
||||
if errorCode != common.CodeSuccess {
|
||||
jsonError(c, errorCode, errorMessage)
|
||||
return
|
||||
}
|
||||
userID := user.ID
|
||||
|
||||
// Get file_id from query
|
||||
fileID := c.Query("file_id")
|
||||
@@ -205,8 +207,8 @@ func (h *FileHandler) GetAllParentFolders(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get all parent folders
|
||||
parentFolders, err := h.fileService.GetAllParentFolders(fileID)
|
||||
// Get all parent folders with permission check
|
||||
parentFolders, err := h.fileService.GetAllParentFolders(userID, fileID)
|
||||
if err != nil {
|
||||
jsonError(c, common.CodeServerError, err.Error())
|
||||
return
|
||||
@@ -229,11 +231,12 @@ func (h *FileHandler) GetAllParentFolders(c *gin.Context) {
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Router /api/v1/files/{id}/ancestors [get]
|
||||
func (h *FileHandler) GetFileAncestors(c *gin.Context) {
|
||||
_, errorCode, errorMessage := GetUser(c)
|
||||
user, errorCode, errorMessage := GetUser(c)
|
||||
if errorCode != common.CodeSuccess {
|
||||
jsonError(c, errorCode, errorMessage)
|
||||
return
|
||||
}
|
||||
userID := user.ID
|
||||
|
||||
fileID := c.Param("id")
|
||||
if fileID == "" {
|
||||
@@ -241,7 +244,8 @@ func (h *FileHandler) GetFileAncestors(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
parentFolders, err := h.fileService.GetAllParentFolders(fileID)
|
||||
// Get all parent folders with permission check
|
||||
parentFolders, err := h.fileService.GetAllParentFolders(userID, fileID)
|
||||
if err != nil {
|
||||
jsonError(c, common.CodeServerError, err.Error())
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user