Skip to content
This repository was archived by the owner on Jul 11, 2026. It is now read-only.
This repository was archived by the owner on Jul 11, 2026. It is now read-only.

[Bug]: Authorization Bypass: Points Can Be Awarded to Users Outside the Current Organization #251

Description

@LovelySharma-dev

Summary

Authorization checks are missing when awarding points to a user. The point award flow validates the acting user's organization but does not verify that the target userId belongs to the same organization.

As a result, an authorized user may be able to award points to users outside their organization if they know a valid user ID.

Steps to reproduce

  1. Log in as a user who has permission to award points.
  2. Obtain the ID of a user belonging to a different organization.
  3. Send a point award request using that user's ID.

Example:

{
  "userId": "<user-from-another-organization>",
  "points": 100,
  "reason": "Test award"
}
  1. Observe that the request succeeds and the target user's points are modified.

Actual behavior

The service updates the target user's points based only on the supplied userId.

No validation is performed to ensure the target user belongs to the same organization as the requester.

Expected behavior

Before awarding points, the application should verify that:

  • The target user exists.
  • The target user belongs to the same organization as the requester (or another explicitly authorized organization).

Requests targeting users outside the requester's organization should be rejected.

Reproduction details

  • OS: Any
  • Browser / environment: Any
  • Version: Current repository state
  • Device: Any

Screenshots / Logs

Relevant code path:

await creditPoints({
    userId,
    organizationId,
    ...
});

Service implementation:

const user = await User.findByIdAndUpdate(
    userId,
    {
        $inc: {
            points: amount,
            totalPointsEarned: amount,
        },
    },
    { new: true },
);

The update is performed without validating organization ownership.

Additional context

The transaction record stores the requester's organization:

organization: organizationId

However, the updated user is selected only by _id, creating a potential cross-tenant modification issue if user IDs from other organizations are known.

Proposed fix (optional)

Validate organization ownership before updating the user:

const user = await User.findOneAndUpdate(
    {
        _id: userId,
        organization: organizationId,
    },
    {
        $inc: {
            points: amount,
            totalPointsEarned: amount,
        },
    },
    { new: true },
);

Alternatively, explicitly compare the target user's organization with the requester's organization and reject mismatches with a 403 Forbidden response.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions