Skip to content

Conversation

@JoshFerge
Copy link
Member

@JoshFerge JoshFerge commented Nov 14, 2025

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

  • All new tests pass (11 GitHub username tests)
  • All existing tests pass (37 suspect commits tests, no regressions)
  • 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

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
@linear
Copy link

linear bot commented Nov 14, 2025

@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Nov 14, 2025
Comment on lines 514 to 519
CommitAuthor.objects.filter(
organization_id=organization_id,
email__in=[email.lower() for email in user_emails],
external_id__isnull=False,
)
.exclude(external_id="")
Copy link

@semgrep-code-getsentry semgrep-code-getsentry bot Nov 14, 2025

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

Comment on lines 467 to 474
ExternalActor.objects.filter(
user_id=user.id,
organization_id=organization_id,
provider__in=[
ExternalProviders.GITHUB.value,
ExternalProviders.GITHUB_ENTERPRISE.value,
],
)
Copy link

@semgrep-code-getsentry semgrep-code-getsentry bot Nov 14, 2025

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-code-getsentry
Copy link

Semgrep found 1 ssc-e23b0a49-86b3-48bc-b82c-03656ca7eaee finding:

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

- Move all imports from inside get_github_username_for_user() to module level
- Remove all logging statements from the helper function
Comment on lines 498 to 503
CommitAuthor.objects.filter(
organization_id=organization_id,
email__in=[email.lower() for email in user_emails],
external_id__isnull=False,
)
.exclude(external_id="")
Copy link

@semgrep-code-getsentry semgrep-code-getsentry bot Nov 14, 2025

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-code-getsentry
Copy link

Semgrep found 1 ssc-e23b0a49-86b3-48bc-b82c-03656ca7eaee finding:

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

- 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
Comment on lines +394 to +399
CommitAuthor.objects.filter(
organization_id=organization_id,
email__in=[email.lower() for email in user_emails],
external_id__isnull=False,
)
.exclude(external_id="")

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.

References: GHSA, CVE

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-code-getsentry
Copy link

Semgrep found 1 ssc-e23b0a49-86b3-48bc-b82c-03656ca7eaee finding:

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

@codecov
Copy link

codecov bot commented Nov 14, 2025

Codecov Report

❌ Patch coverage is 68.42105% with 6 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/sentry/seer/autofix/autofix.py 68.42% 6 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##           master   #103406   +/-   ##
========================================
  Coverage   80.67%    80.67%           
========================================
  Files        9241      9242    +1     
  Lines      394795    394825   +30     
  Branches    25147     25147           
========================================
+ Hits       318512    318542   +30     
  Misses      75836     75836           
  Partials      447       447           

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

Labels

Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants