-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
feat(autofix): Add email-based user mapping for Seer Autofix PR review requests #103406
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(autofix): Add email-based user mapping for Seer Autofix PR review requests #103406
Conversation
Users lose track of Seer-authored Autofix PRs because Seer is the PR author. This change enables automatic PR review requests to the triggering user by resolving their GitHub username from multiple sources. Changes: - Add shared `get_github_username_for_user()` helper in committers.py - Check ExternalActor for direct user→GitHub mappings (existing behavior) - Fall back to CommitAuthor email matching (like suspect commits) - Extract GitHub username from CommitAuthor.external_id - Add structured logging to track mapping sources - Update autofix to use shared helper instead of duplicate code - Add 6 new test cases for CommitAuthor fallback scenarios When users trigger Autofix, if their email matches a CommitAuthor with a GitHub external_id, Seer will automatically request their review on the PR, making it easier to track and find their Autofix PRs. Fixes AIML-1597
src/sentry/utils/committers.py
Outdated
| CommitAuthor.objects.filter( | ||
| organization_id=organization_id, | ||
| email__in=[email.lower() for email in user_emails], | ||
| external_id__isnull=False, | ||
| ) | ||
| .exclude(external_id="") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Risk: Affected versions of django are vulnerable to Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection'). The ORM methods QuerySet.filter(), QuerySet.exclude(), QuerySet.get() and the Q() class can be tricked into SQL injection when you pass a specially crafted dictionary via **kwargs that includes a malicious _connector entry. This bypasses the normal query parameterization and lets an attacker inject arbitrary SQL into the WHERE clause.
Fix: Upgrade this library to at least version 5.2.8 at sentry/uv.lock:305.
Reference(s): GHSA-frmv-pr5f-9mcr, CVE-2025-64459
⭐ Fixed in commit 91219f4 ⭐
src/sentry/utils/committers.py
Outdated
| ExternalActor.objects.filter( | ||
| user_id=user.id, | ||
| organization_id=organization_id, | ||
| provider__in=[ | ||
| ExternalProviders.GITHUB.value, | ||
| ExternalProviders.GITHUB_ENTERPRISE.value, | ||
| ], | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Risk: Affected versions of django are vulnerable to Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection'). The ORM methods QuerySet.filter(), QuerySet.exclude(), QuerySet.get() and the Q() class can be tricked into SQL injection when you pass a specially crafted dictionary via **kwargs that includes a malicious _connector entry. This bypasses the normal query parameterization and lets an attacker inject arbitrary SQL into the WHERE clause.
Fix: Upgrade this library to at least version 5.2.8 at sentry/uv.lock:305.
Reference(s): GHSA-frmv-pr5f-9mcr, CVE-2025-64459
🎉 Removed in commit d3ede3f 🎉
|
Semgrep found 1 Risk: Affected versions of django are vulnerable to Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection'). The ORM methods QuerySet.filter(), QuerySet.exclude(), QuerySet.get() and the Q() class can be tricked into SQL injection when you pass a specially crafted dictionary via **kwargs that includes a malicious Fix: Upgrade this library to at least version 5.2.8 at sentry/uv.lock:305. Reference(s): GHSA-frmv-pr5f-9mcr, CVE-2025-64459 |
- Move all imports from inside get_github_username_for_user() to module level - Remove all logging statements from the helper function
src/sentry/utils/committers.py
Outdated
| CommitAuthor.objects.filter( | ||
| organization_id=organization_id, | ||
| email__in=[email.lower() for email in user_emails], | ||
| external_id__isnull=False, | ||
| ) | ||
| .exclude(external_id="") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Risk: Affected versions of django are vulnerable to Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection'). The ORM methods QuerySet.filter(), QuerySet.exclude(), QuerySet.get() and the Q() class can be tricked into SQL injection when you pass a specially crafted dictionary via **kwargs that includes a malicious _connector entry. This bypasses the normal query parameterization and lets an attacker inject arbitrary SQL into the WHERE clause.
Fix: Upgrade this library to at least version 5.2.8 at sentry/uv.lock:305.
Reference(s): GHSA-frmv-pr5f-9mcr, CVE-2025-64459
🍰 Removed in commit d3ede3f 🍰
|
Semgrep found 1 Risk: Affected versions of django are vulnerable to Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection'). The ORM methods QuerySet.filter(), QuerySet.exclude(), QuerySet.get() and the Q() class can be tricked into SQL injection when you pass a specially crafted dictionary via **kwargs that includes a malicious Fix: Upgrade this library to at least version 5.2.8 at sentry/uv.lock:305. Reference(s): GHSA-frmv-pr5f-9mcr, CVE-2025-64459 |
- Move implementation from committers.py directly into _get_github_username_for_user in autofix.py - Remove now-unused shared helper function from committers.py - Remove unused imports from committers.py - Keep all logic in autofix where it's actually used
| CommitAuthor.objects.filter( | ||
| organization_id=organization_id, | ||
| email__in=[email.lower() for email in user_emails], | ||
| external_id__isnull=False, | ||
| ) | ||
| .exclude(external_id="") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical severity and reachable issue identified in your code:
Line 394 has a vulnerable usage of django, introducing a critical severity vulnerability.
ℹ️ Why this is reachable
A reachable issue is a real security risk because your project actually executes the vulnerable code. This issue is reachable because your code uses a certain version of django.
Affected versions of django are vulnerable to Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection'). The ORM methods QuerySet.filter(), QuerySet.exclude(), QuerySet.get() and the Q() class can be tricked into SQL injection when you pass a specially crafted dictionary via **kwargs that includes a malicious _connector entry. This bypasses the normal query parameterization and lets an attacker inject arbitrary SQL into the WHERE clause.
To resolve this comment:
Upgrade this dependency to at least version 5.2.8 at uv.lock.
💬 Ignore this finding
To ignore this, reply with:
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
You can view more details on this finding in the Semgrep AppSec Platform here.
|
Semgrep found 1 Risk: Affected versions of django are vulnerable to Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection'). The ORM methods QuerySet.filter(), QuerySet.exclude(), QuerySet.get() and the Q() class can be tricked into SQL injection when you pass a specially crafted dictionary via **kwargs that includes a malicious Fix: Upgrade this library to at least version 5.2.8 at sentry/uv.lock:305. Reference(s): GHSA-frmv-pr5f-9mcr, CVE-2025-64459 |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #103406 +/- ##
===========================================
+ Coverage 78.11% 80.50% +2.39%
===========================================
Files 9352 9352
Lines 400391 400407 +16
Branches 25700 25700
===========================================
+ Hits 312778 322364 +9586
+ Misses 87145 77575 -9570
Partials 468 468 |
…d-user-mapping-for-seer-autofix-prs
…d-user-mapping-for-seer-autofix-prs
|
This pull request has gone three weeks without activity. In another week, I will close it. But! If you comment or otherwise update it, I will reset the clock, and if you add the label "A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀 |
…d-user-mapping-for-seer-autofix-prs
|
I tested this PR locally to the point where I ensure I make the seer call is made with the correct github user when no ExternalActor object is present but a CommitAuthor is present (I set up a github app integration to populate CommitAuthor). It looks good to me. |
JoshFerge
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm!
…w requests (#103406) ## Summary Implements email-based user mapping for Seer Autofix PRs to automatically request review from the triggering user, making it easier for users to track their Autofix PRs. Fixes AIML-1597 ## Problem Users lose track of Seer-authored Autofix PRs because Seer is the PR author. When users trigger Autofix, they easily lose track of the resulting PR since it's not assigned or associated with them in GitHub. ## Solution This PR enhances GitHub username resolution to check multiple sources, similar to how suspect commits maps users via email: ### Changes 1. **Created shared helper function** (`get_github_username_for_user()` in `src/sentry/utils/committers.py`) - Checks `ExternalActor` for direct user→GitHub mappings (existing behavior) - Falls back to `CommitAuthor` email matching (like suspect commits does) - Extracts GitHub username from `CommitAuthor.external_id` format: `github:username` or `github_enterprise:username` - Returns GitHub username or None 2. **Updated autofix** (`src/sentry/seer/autofix/autofix.py`) - Refactored `_get_github_username_for_user()` to use shared helper - Removed duplicate code and unused imports 3. **Added comprehensive tests** (`tests/sentry/seer/autofix/test_autofix.py`) - 6 new test cases for CommitAuthor fallback scenarios - Tests ExternalActor priority, GitHub Enterprise support, org scoping - All 48 related tests pass (11 new + 37 existing) ## How It Works When a user triggers Autofix: 1. Sentry resolves their GitHub username using the new shared helper 2. Helper checks `ExternalActor` first (fastest, most reliable) 3. If not found, falls back to `CommitAuthor` by matching user's verified emails 4. If matching `CommitAuthor` has GitHub `external_id`, extracts username 5. Sentry passes GitHub username to Seer in the autofix request 6. Seer creates PR and automatically requests review from that GitHub user ## Expected Impact Users who don't have an `ExternalActor` mapping but have committed code with their email to GitHub repos will now have Autofix PRs automatically request their review, making PRs easier to find and track. ## Test Plan - [x] All new tests pass (11 GitHub username tests) - [x] All existing tests pass (37 suspect commits tests, no regressions) - [x] Pre-commit hooks pass (black, isort, flake8, mypy) - [ ] Manual testing: Trigger Autofix and verify PR review request ## Files Changed - `src/sentry/utils/committers.py` - Added shared helper function - `src/sentry/seer/autofix/autofix.py` - Updated to use shared helper - `tests/sentry/seer/autofix/test_autofix.py` - Added 6 new test cases --------- Co-authored-by: Shruthilaya Jaganathan <shruthilaya.jaganathan@sentry.io>
Summary
Implements email-based user mapping for Seer Autofix PRs to automatically request review from the triggering user, making it easier for users to track their Autofix PRs.
Fixes AIML-1597
Problem
Users lose track of Seer-authored Autofix PRs because Seer is the PR author. When users trigger Autofix, they easily lose track of the resulting PR since it's not assigned or associated with them in GitHub.
Solution
This PR enhances GitHub username resolution to check multiple sources, similar to how suspect commits maps users via email:
Changes
Created shared helper function (
get_github_username_for_user()insrc/sentry/utils/committers.py)ExternalActorfor direct user→GitHub mappings (existing behavior)CommitAuthoremail matching (like suspect commits does)CommitAuthor.external_idformat:github:usernameorgithub_enterprise:usernameUpdated autofix (
src/sentry/seer/autofix/autofix.py)_get_github_username_for_user()to use shared helperAdded comprehensive tests (
tests/sentry/seer/autofix/test_autofix.py)How It Works
When a user triggers Autofix:
ExternalActorfirst (fastest, most reliable)CommitAuthorby matching user's verified emailsCommitAuthorhas GitHubexternal_id, extracts usernameExpected Impact
Users who don't have an
ExternalActormapping but have committed code with their email to GitHub repos will now have Autofix PRs automatically request their review, making PRs easier to find and track.Test Plan
Files Changed
src/sentry/utils/committers.py- Added shared helper functionsrc/sentry/seer/autofix/autofix.py- Updated to use shared helpertests/sentry/seer/autofix/test_autofix.py- Added 6 new test cases