vxcontrol/pentagi · error
resource %d not accessible
Error message
resource %d not accessible
What it means
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.
Source
Thrown at backend/pkg/server/services/assistants.go:677
var recs []models.UserResource
if err := db.Model(&models.UserResource{}).Where("id IN (?)", ids).Find(&recs).Error; err != nil {
return nil, fmt.Errorf("failed to fetch resources: %w", err)
}
found := make(map[uint64]models.UserResource, len(recs))
for _, r := range recs {
found[r.ID] = r
}
result := make([]database.UserResource, 0, len(ids))
for _, id := range ids {
r, ok := found[id]
if !ok {
return nil, fmt.Errorf("resource %d not found", id)
}
if !isAdmin && r.UserID != uid {
return nil, fmt.Errorf("resource %d not accessible", id)
}
result = append(result, database.UserResource{
ID: int64(r.ID),
UserID: int64(r.UserID),
Hash: r.Hash,
Name: r.Name,
Path: r.Path,
Size: r.Size,
IsDir: r.IsDir,
CreatedAt: database.TimeToNullTime(r.CreatedAt),
UpdatedAt: database.TimeToNullTime(r.UpdatedAt),
})
}
return result, nil
}
View on GitHub (pinned to ea665308ba)
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).
Defensive patterns
Strategy: validation
Validate before calling
// verify ownership before attaching resources
var rec models.UserResource
if err := db.First(&rec, id).Error; err == nil {
if rec.UserID != uid && !isAdmin {
return fmt.Errorf("resource %d belongs to user %d, not caller %d", id, rec.UserID, uid)
}
} Type guard
func canAccessResource(r models.UserResource, uid uint64, privs []string) bool {
return slices.Contains(privs, "resources.admin") || r.UserID == uid
} Try / catch
_, err := validateServiceResources(ctx, uid, privs, ids)
if err != nil {
if strings.Contains(err.Error(), "not accessible") {
return nil, fmt.Errorf("one or more resources belong to another user; use your own resources or ask an admin")
}
return nil, err
} Prevention
- 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
When it happens
Trigger: CreateFlowAssistant, PatchAssistant, CreateFlow, or PatchFlow where a non-admin user passes a valid resource ID owned by another user.
Common situations: 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).
Related errors
- permission 'resources.view' required to use resource IDs
- Token.Unauthorized
- user has been blocked
- knowledge: get user document %s: %w
- PrivilegesRequired
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/8679601cf8ff9b3c.
Report an issue: GitHub.