Skip to content

Set fuzzer author as reporter for bugs from external fuzzers#5312

Open
jr2bg wants to merge 4 commits into
masterfrom
feature/report-by-fuzzer-owner
Open

Set fuzzer author as reporter for bugs from external fuzzers#5312
jr2bg wants to merge 4 commits into
masterfrom
feature/report-by-fuzzer-owner

Conversation

@jr2bg

@jr2bg jr2bg commented Jun 4, 2026

Copy link
Copy Markdown

Changes:

  • Added primary_owner field to Fuzzer model in data_types.py.
  • Added "Primary owner" input field to the fuzzer edit form in edit-form.html.
  • Updated fuzzers.py handler to save the primary_owner field.
  • Updated file_issue in issue_filer.py to use fuzzer.primary_owner as the reporter if available.
  • Added unit tests in issue_filer_test.py to verify the new behavior.

Feature tests


Show “owner” textbox

Preconditions

  1. Code already on dev instance

Steps

  1. Enter to https://gosst.development.clusterfuzz.com/fuzzers
  2. Click “CREATE NEW”
  3. Screenshot on the popup, highlighting the “Primary owner (email)” textbox

Evidence

Step 3
Screenshot 2026-07-16 at 9 18 28 a m


Show owner entry on Pantheon Audit Logs

Preconditions

  1. Code already on dev instance

Steps

  1. Enter to https://gosst.development.clusterfuzz.com/fuzzers
  2. Click “CREATE NEW”
  3. Fill the form with the next information
    • Name: new_fuzzer_with_owner_jabg
    • Select/modify jobs: libfuzzer_chrome_asan
    • Owner: jabgonzalez@google.com
    • Corpus: None
    • Fuzzer archive: ???
    • Environment variables: None
    • External contribution: True
  4. Click “Submit”
  5. Go to dev logs https://pantheon.corp.google.com/logs/query;cursorTimestamp=2026-04-21T13:41:59.977146Z?e=-13802955&mods=logs_tg_prod&project=clusterfuzz-development and search for the new fuzzer
  6. Take a screenshot of the result, highlighting the “Primary owner (email)” entry
  7. Go to https://gosst.development.clusterfuzz.com/fuzzers
  8. Search the recently created fuzzer new_fuzzer_with_owner_jabg
  9. Take a screenshot

Evidence

Step 6
Screenshot 2026-07-16 at 1 48 59 p m

Step 10
Screenshot 2026-07-16 at 1 52 00 p m

@jr2bg jr2bg requested a review from dylanjew June 4, 2026 14:11
@jr2bg jr2bg requested a review from a team as a code owner June 4, 2026 14:11

@dylanjew dylanjew left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job overall!

A couple things:

  1. Change the branch to merge this into master

  2. Please run python butler.py format and python butler.py lint

  3. Could you add a section to your description explaining the steps that you went through to test this? It would be great to include screenshots of this is in dev and then verifying the field in the Datastore. Let me know if you have any questions

  4. Similarly, the backfill script component of this bug probably warrants another section in the PR description. It should cover the order of operations for rolling out this change and how you're going to get the primary owner data for the backfill. Again, lmk if I can help with this. The state of our blackbox fuzzers is not great, and there are many that we need to track down their status/owners.

Comment thread scripts/migrate_fuzzer_owners.py Outdated
Comment thread scripts/migrate_fuzzer_owners.py Outdated
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Backfill primary_owner for Fuzzers.')
parser.add_argument('--live', action='store_true', help='Perform live updates.')
parser.add_argument('--owner', default='default-owner@example.com', help='Default owner email.')

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it make sense to have a default owner? Can we just leave it empty for now if we're not sure, and then keep the existing behavior if it is empty?

Comment thread scripts/migrate_fuzzer_owners.py Outdated

if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Backfill primary_owner for Fuzzers.')
parser.add_argument('--live', action='store_true', help='Perform live updates.')

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if you run this using the butler run script the arg should be non-dry-run

Comment thread src/clusterfuzz/_internal/datastore/data_types.py Outdated
logs.info(f'Filing new issue for testcase: {testcase.key.id()}.')

policy = issue_tracker_policy.get(issue_tracker.project)
fuzzer = None

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this need to be a DataStore look up?

Comment thread scripts/migrate_fuzzer_owners.py Outdated
Comment thread scripts/migrate_fuzzer_owners.py Outdated
for fuzzer in query.fetch():
print(f"Processing fuzzer: {fuzzer.name}")
if not dry_run:
fuzzer.primary_owner = default_owner

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we expect the primary_owner to be the same for most of these fuzzers? I would have guessed that there were for example 10 externally contributed fuzzers and maybe 8 different authors of those fuzzers.

Comment thread scripts/migrate_fuzzer_owners.py Outdated

def migrate(dry_run=True, default_owner='default-owner@example.com'):
"""Migrates fuzzer owners."""
query = data_types.Fuzzer.query(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add a filter on external_contribution

external_contribution=True,
primary_owner='owner@example.com').put()

issue_tracker = monorail.IssueTracker(IssueTrackerManager('chromium'))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this the correct way to create an IssueTracker? My understanding is that we migrated from Monorail to IssueTracker/Buganizer at some point.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right! Checking it


issue_filer.file_issue(self.testcase1, issue_tracker, user_email='reporter@example.com')

self.assertEqual('owner@example.com', issue_tracker._itm.last_issue.reporter)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: is there a better way to check the reporter for the filed issue? _itm.last_issue.reporter seems a bit roundabout and reaches into a private method

@jr2bg jr2bg changed the base branch from dev to master June 12, 2026 20:03
@jr2bg jr2bg force-pushed the feature/report-by-fuzzer-owner branch 2 times, most recently from 71a3845 to 1c3affd Compare June 15, 2026 18:52
jr2bg added 4 commits July 16, 2026 13:41
- issue_filer.py
Get fuzzer from DataStore query, handles cases when no `primary_owner` is found, does not consider yet `external_contribution.

- migrate_fuzzer_owners.py
Removes the owner
@jr2bg jr2bg force-pushed the feature/report-by-fuzzer-owner branch from 1c3affd to e4b33cd Compare July 16, 2026 13:51
issue.components.add(policy.unreproducible_component)

issue.reporter = user_email
if fuzzer and getattr(fuzzer, 'primary_owner', None):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of getattr, can you just check the field directly with fuzzer.primary_owner?

try:
fuzzer = data_types.Fuzzer.query(
data_types.Fuzzer.name == testcase.fuzzer_name).get()
except Exception:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know when an Exception is thrown here? We'd want to log it depending on what happened.

Just to confirm, this isn't an exception because the query returned no results, right?

@@ -0,0 +1,59 @@
# Copyright 2026 Google LLC

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can just revert this file and keep it in a draft PR for testing or manual backfills. We don't expect to run this more than once

fuzzer.sample_testcase = None
fuzzer.console_output = None
fuzzer.external_contribution = bool(external_contribution)
fuzzer.primary_owner = primary_owner

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a test you can update alongside this change?

<paper-input
label="Primary owner (email)"
value="{{fuzzer.primary_owner}}"
title="Primary owner for VRP reasons.">

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
title="Primary owner for VRP reasons.">
title="Primary owner for VRP rewards.">

# Intercept new_issue so we can capture the saved issue object.
original_new_issue = issue_tracker.new_issue

def mock_new_issue():

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to mock as little as possible and keep the mocks to the external calls, e.g. the _execute request in test_filed_issue_google_issue_tracker


issue.reporter = user_email
if fuzzer and getattr(fuzzer, 'primary_owner', None):
issue.reporter = fuzzer.primary_owner

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We sometimes use the reporter to determine whether clusterfuzz filed the bug. Is there another place where we are setting metadata of some kind, e.g. a label/hotlist that stays on the bug so that we can continue to track clusterfuzz filed bugs?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants