sillsdev / sillsdev/languageforge-lexbox

User typeahead can be abused to determine values of admin-only fields

Open
#1,286 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

📦 Lexbox bug
Dominant language
C#
Stars
9
Forks
8
Avg merge
2d 13h
Merged PRs (30d)
49

Description

Describe the bug

We don't explicitly show the email addresses of other users, but by trial and error it's quite easy to figure out what a user's email address is by filtering users by their email. So, that probably shouldn't be allowed (unless you're allowed to see the user's email, probably?)

Fix ideas
I tried adding the admin required policy to filter fields, but you get the error:
1. The specified directive @authorizeis not allowed on the current locationInputFieldDefinition. (LexBoxApi.GraphQL.CustomTypes.UserFilterType).

We could explicitly set email and username to null for users that are not "managed by" the requesting user. Which would effectively disable filtering by those fields. We're already doing that in the scope of an org. I think UsersICanSee is the only query where we'd need to do that. Something like this: 😬

    public IQueryable<User> UserQueryForTypeahead(LexAuthUser user)
    {
        var myOrgIds = user.Orgs.Select(o => o.OrgId).ToList();
        var myManagedOrgIds = user.Orgs.Where(o => o.Role == OrgRole.Admin).Select(o => o.OrgId).ToList();
        var myProjectIds = user.Projects.Select(p => p.ProjectId).ToList();
        var myManagedProjectIds = user.Projects.Where(p => p.Role == ProjectRole.Manager).Select(p => p.ProjectId).ToList();
        return dbContext.Users
            .Select(u => new
            {
                user = u,
                iSee = u.Id == user.Id ||
                    u.Organizations.Any(orgMember => myOrgIds.Contains(orgMember.OrgId)) ||
                    u.Projects.Any(projMember =>
                        myManagedProjectIds.Contains(projMember.ProjectId) ||
                        (projMember.Project != null && projMember.Project.IsConfidential != true && myProjectIds.Contains(projMember.ProjectId))),
                iManage = u.Organizations.Any(orgMember => myManagedOrgIds.Contains(orgMember.OrgId))
            })
            .Where(u => u.iSee)
            .Select(u => u.iManage ? u.user : new User { Id = u.user.Id, Name = u.user.Name });
    }

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with UsersICanSee and UserQueryForTypeahead, then inspect LexBoxApi.GraphQL.CustomTypes.UserFilterType and its authorization handling. Verify how typeahead filtering exposes email and username to users who do not manage the target user. Done means unauthorized users cannot infer those fields through filtering while permitted users retain the intended access.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
api, authorization, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.