{"record":{"id":"8679601cf8ff9b3c","repo":"vxcontrol/pentagi","slug":"resource-d-not-accessible","errorCode":null,"errorMessage":"resource %d not accessible","messagePattern":"resource (.+?) not accessible","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/server/services/assistants.go","lineNumber":677,"sourceCode":"\n\tvar recs []models.UserResource\n\tif err := db.Model(&models.UserResource{}).Where(\"id IN (?)\", ids).Find(&recs).Error; err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to fetch resources: %w\", err)\n\t}\n\n\tfound := make(map[uint64]models.UserResource, len(recs))\n\tfor _, r := range recs {\n\t\tfound[r.ID] = r\n\t}\n\n\tresult := make([]database.UserResource, 0, len(ids))\n\tfor _, id := range ids {\n\t\tr, ok := found[id]\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"resource %d not found\", id)\n\t\t}\n\t\tif !isAdmin && r.UserID != uid {\n\t\t\treturn nil, fmt.Errorf(\"resource %d not accessible\", id)\n\t\t}\n\t\tresult = append(result, database.UserResource{\n\t\t\tID:        int64(r.ID),\n\t\t\tUserID:    int64(r.UserID),\n\t\t\tHash:      r.Hash,\n\t\t\tName:      r.Name,\n\t\t\tPath:      r.Path,\n\t\t\tSize:      r.Size,\n\t\t\tIsDir:     r.IsDir,\n\t\t\tCreatedAt: database.TimeToNullTime(r.CreatedAt),\n\t\t\tUpdatedAt: database.TimeToNullTime(r.UpdatedAt),\n\t\t})\n\t}\n\n\treturn result, nil\n}\n","sourceCodeStart":659,"sourceCodeEnd":694,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/server/services/assistants.go#L659-L694","documentation":"The requested resource exists but belongs to a different user (r.UserID != uid), and the caller is not an admin. validateServiceResources scopes resources per-user: a non-admin may only reference their own resources, preventing horizontal privilege escalation through flow/assistant creation.","triggerScenarios":"CreateFlowAssistant, PatchAssistant, CreateFlow, or PatchFlow where a non-admin user passes a valid resource ID owned by another user.","commonSituations":"Sharing resource IDs between teammates without knowing they are user-scoped; an automation service account trying to attach resources created by a human user; guessing/enumerating other users' resource IDs (correctly rejected).","solutions":["Use resource IDs owned by the authenticated user (list them via the resources endpoint as that user).","Have an admin (privilege 'resources.admin') create the flow/assistant if cross-user resources are required.","Re-create the resource under the calling user's account.","If team sharing is the goal, extend the backend to support resource sharing groups rather than bypassing this check.","Confirm the token used corresponds to the intended user (not another teammate's token)."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// verify ownership before attaching resources\nvar rec models.UserResource\nif err := db.First(&rec, id).Error; err == nil {\n    if rec.UserID != uid && !isAdmin {\n        return fmt.Errorf(\"resource %d belongs to user %d, not caller %d\", id, rec.UserID, uid)\n    }\n}","typeGuard":"func canAccessResource(r models.UserResource, uid uint64, privs []string) bool {\n    return slices.Contains(privs, \"resources.admin\") || r.UserID == uid\n}","tryCatchPattern":"_, err := validateServiceResources(ctx, uid, privs, ids)\nif err != nil {\n    if strings.Contains(err.Error(), \"not accessible\") {\n        return nil, fmt.Errorf(\"one or more resources belong to another user; use your own resources or ask an admin\")\n    }\n    return nil, err\n}","preventionTips":["List resources as the same user that will create the flow","Use an admin account when cross-user resources are required","Re-create shared resources under the service account that runs automation","Document that resources are strictly user-scoped"],"tags":["authorization","ownership","resources","rbac"],"backgroundTag":"resource-not-accessible","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}