microsoft / microsoft/PyRIT

Scanner run preview dismissal does not restore keyboard focus

Open Beginner friendly
#2,680 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug: triage
Dominant language
Python
Stars
4.5k
Forks
893
Avg merge
3d 50m
Merged PRs (30d)
165

Description

Describe the bug

Dismissing Scanner's Run preview dialog with either Cancel or Escape leaves document.activeElement on <body> instead of returning focus to the Launch scan button that opened the modal.

The dialog initially receives and contains focus correctly. The defect is specific to focus restoration after dismissal. Keyboard users lose their point of reference and must navigate back to the launch workflow before continuing.

A search of currently open issues and pull requests using Scanner, run preview, dialog, focus restoration, and keyboard terms found no exact tracker. #2653 discusses decomposing ScenarioDetail while preserving accessibility, but it does not describe this behavior.

The relevant state-controlled dialog is in frontend/src/components/Scenarios/ScenarioDetail.tsx:1216-1223,1228-1234,1322-1327. Both onOpenChange and the Cancel handler close the dialog by updating previewOpen; neither path restores focus to the launch control.

Steps/Code to Reproduce
  1. Open Scanners and select airt.jailbreak.
  2. Select any configured compatible target.
  3. Select baseline plus prompt_sending, set num_jailbreaks=1, num_jailbreak_attempts=1, and set the maximum dataset size to 1.
  4. Activate Launch scan to open Run preview.
  5. Select Cancel, wait for the dialog to close, and inspect document.activeElement.
  6. Reopen Run preview, dismiss it with Escape, and inspect document.activeElement again.

The focused Playwright probe used for both dismissal paths was:

await page.getByRole('button', { name: 'Cancel' }).click()
await page.waitForTimeout(300)

const activeElement = await page.evaluate(() => ({
  tag: document.activeElement?.tagName,
  testId: document.activeElement?.getAttribute('data-testid'),
  ariaLabel: document.activeElement?.getAttribute('aria-label'),
}))

// { tag: 'BODY', testId: null, ariaLabel: null }

The same result reproduced after pressing Escape.

Expected Results

After either Cancel or Escape closes Run preview, focus returns to the Launch scan button (data-testid="launch-scenario-btn") that opened the dialog.

Actual Results

After both dismissal paths:

document.activeElement.tagName: BODY
data-testid: null
aria-label: null

The behavior reproduced in two focused runs with a 300 ms wait after dismissal. No scan was launched.

A likely fix is to retain a ref to the launch button and restore focus after every non-submitting dismissal path, with regression coverage for both Cancel and Escape.

Screenshots

N/A. The modal renders correctly; the failure is the programmatic focus position after it closes. The exact active-element result is included above.

Versions
  • OS: Windows_NT
  • Browser: Playwright Chromium (@playwright/test 1.62.1)
  • Python: 3.14.4
  • PyRIT: 1.2.0.dev0, main at b0dba3edd0abc2a88c15a5e8ebd106fe8396d27d
  • Python package versions: repository uv.lock at the tested commit

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in frontend/src/components/Scenarios/ScenarioDetail.tsx at the preview dialog state, onOpenChange, and Cancel handler. Run the focused Playwright dismissal probe described in the issue for Cancel and Escape, then add regression coverage showing that both paths restore focus to the button with data-testid="launch-scenario-btn".

Written by the indexing model from the issue text.

Assessment

Tech stack
playwright, typescript
Domain
accessibility, frontend, testing-qa
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.