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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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