Skip to content

fix: prevent cross-organization password resets - #6111

Open
shafeeq27edu-ai wants to merge 1 commit into
Agenta-AI:mainfrom
shafeeq27edu-ai:fix/password-reset-idor
Open

fix: prevent cross-organization password resets#6111
shafeeq27edu-ai wants to merge 1 commit into
Agenta-AI:mainfrom
shafeeq27edu-ai:fix/password-reset-idor

Conversation

@shafeeq27edu-ai

@shafeeq27edu-ai shafeeq27edu-ai commented Aug 19, 2026

Copy link
Copy Markdown

Summary

Fixed an authorization issue in the admin password reset flow where a user with the RESET_PASSWORD permission could potentially generate a password reset link for a user belonging to another organization.

Root cause

The password reset endpoint verified that the requesting user had the RESET_PASSWORD permission, but the target user_id was not validated against the requesting user's organization.

The authorization check therefore verified the caller's permission without verifying whether the caller was authorized to act on the target user.

Fix

The password reset flow now:

  1. Resolves the caller's project to its organization.
  2. Retrieves the target user's organization membership.
  3. Verifies that the target user belongs to the caller's organization.
  4. Rejects cross-organization password reset attempts with 403 Forbidden.

The existing RESET_PASSWORD permission check remains unchanged.

Additionally, the router now handles NoResultFound specifically as 404 Not Found instead of catching all exceptions and incorrectly converting unexpected failures into 404 responses.

Unexpected exceptions continue through Agenta's normal error handling.


Testing

Verified locally

  • Verified the cross-organization authorization flow.
  • Verified the same-organization password reset flow.
  • Verified the missing-user flow.
  • Verified the existing RESET_PASSWORD permission check.
  • ruff format passed.
  • ruff check passed.

The focused IDOR tests and existing access-control tests passed before the final exception-handling refinement.

A subsequent test rerun was blocked by a pre-existing local environment issue while building the litellm dependency due to missing MSVC link.exe. This is unrelated to the changes in this PR.

Added or updated tests

Added test_reset_password_idor.py covering:

  • Cross-organization password reset → 403 Forbidden
  • Same-organization password reset → successful
  • Nonexistent target user → 404 Not Found
  • Caller without RESET_PASSWORD permission → 403 Forbidden

The cross-organization test also verifies that password reset link generation is not reached for an unauthorized target.

QA follow-up

N/A

This is a backend authorization fix with unit-level regression coverage. No UI changes are included.


Demo

Before/after terminal demonstration of the password reset IDOR fix.

Before: The cross-organization password reset regression test fails because the vulnerable implementation returns 200 instead of the expected 403.

image

After: The fixed implementation correctly returns 403 for cross-organization resets, while authorized same-organization resets continue to work.

image

The focused regression suite passes all 4 tests after the fix.


Checklist

  • I have included a video or screen recording for UI changes, or marked Demo as N/A
  • Relevant tests pass locally
  • Relevant linting and formatting pass locally
  • I have signed the CLA, or I will sign it when the bot prompts me

@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Aug 19, 2026
@vercel

vercel Bot commented Aug 19, 2026

Copy link
Copy Markdown

@shafeeq27edu-ai is attempting to deploy a commit to the agenta projects Team on Vercel.

A member of the Team first needs to authorize it.

@dosubot dosubot Bot added bug python Pull requests that update Python code tests labels Aug 19, 2026
@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

✅ Thanks @shafeeq27edu-ai! This PR now meets the contribution requirements and has been reopened. A maintainer will review it soon.

@github-actions github-actions Bot added the incomplete-pr PR is missing required template sections or a demo recording label Aug 19, 2026
@github-actions github-actions Bot closed this Aug 19, 2026
@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 17071692-d789-43ac-9ea3-be330aa2dcb6

📥 Commits

Reviewing files that changed from the base of the PR and between 1df3eed and 0ed0c60.

📒 Files selected for processing (3)
  • api/oss/src/routers/user_profile.py
  • api/oss/src/services/user_service.py
  • api/oss/tests/pytest/unit/access/test_reset_password_idor.py

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.


📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved password-reset security by preventing resets for users outside the caller’s organization.
    • Added clear error responses for unauthorized requests and users who cannot be found.
    • Preserved password-reset functionality for authorized users within the same organization.
  • Tests

    • Added coverage for cross-organization access, valid resets, missing users, and insufficient permissions.

Walkthrough

The password reset flow now passes project scope to the service, validates organization membership, maps permission and missing-user errors to HTTP responses, and adds regression tests for these cases.

Changes

Password reset authorization

Layer / File(s) Summary
Project organization validation
api/oss/src/services/user_service.py
generate_user_password_reset_link now accepts project_id, resolves the project organization, and verifies target-user membership before generating the reset link.
Router error mapping
api/oss/src/routers/user_profile.py
reset_user_password passes project_id and maps PermissionError to 403 and NoResultFound to 404.
Authorization regression coverage
api/oss/tests/pytest/unit/access/test_reset_password_idor.py
Tests cover cross-organization denial, same-organization success, nonexistent users, and callers without RESET_PASSWORD permission.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant reset_user_password
  participant generate_user_password_reset_link
  participant ProjectAndUserData
  Client->>reset_user_password: Request password reset
  reset_user_password->>generate_user_password_reset_link: Pass user_id, admin_user_id, project_id
  generate_user_password_reset_link->>ProjectAndUserData: Resolve project organization and target user
  ProjectAndUserData-->>generate_user_password_reset_link: Return scope data or raise error
  generate_user_password_reset_link-->>reset_user_password: Return reset link or exception
  reset_user_password-->>Client: Return link, 403, or 404
Loading
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot removed the incomplete-pr PR is missing required template sections or a demo recording label Aug 19, 2026
@github-actions github-actions Bot reopened this Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug python Pull requests that update Python code size:M This PR changes 30-99 lines, ignoring generated files. tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant