feat(a11y): iframe accessibility and focus delegation - #1652
feat(a11y): iframe accessibility and focus delegation#1652AbhishekChorotiya wants to merge 1 commit into
Conversation
|
💡 Focus delegation The // Current - broadcasts to all
let sendFocusNext = (~iframeId, ~targetOrigin="*") =>
// Recommended - use configured origin from GlobalVars
let sendFocusNext = (~iframeId, ~targetOrigin=GlobalVars.targetOrigin) =>Impact: Low security risk (focus delegation is benign), but defense-in-depth suggests constraining the message target. |
95e8464 to
4b11bc9
Compare
f6035f0 to
7e98542
Compare
Descriptive title on every iframe; focus delegation across the iframe boundary via postMessage (FocusDelegation reuses AccessibilityUtils focus/selector primitives).
Review SummaryPR: #1652 - feat(a11y): iframe accessibility and focus delegation Findings
No blocking issues. The focus delegation implementation follows accessibility best practices. |
7e98542 to
7636a92
Compare
4b11bc9 to
b1de9da
Compare
| [("focusDelegation", "next"->JSON.Encode.string), ("iframeId", iframeId->JSON.Encode.string)], | ||
| ~targetOrigin, | ||
| ) | ||
|
|
There was a problem hiding this comment.
targetOrigin="*" in postMessage allows any origin to receive focus delegation messages.
While the message content (focus delegation) is relatively low-risk, this pattern establishes a precedent that could be copied for more sensitive messages. Consider deriving the target origin from the actual merchant origin or using a restrictive whitelist rather than the wildcard.
| // Notify the parent page to move focus to the next focusable element after the iframe. | |
| let sendFocusNext = (~iframeId, ~targetOrigin) => | |
| Utils.messageParentWindow( | |
| [("focusDelegation", "next"->JSON.Encode.string), ("iframeId", iframeId->JSON.Encode.string)], | |
| ~targetOrigin, | |
| ) |
|
🚨 Critical security concern - While the message content (focus delegation) is relatively low-risk, this pattern establishes a precedent that could be copied for more sensitive messages. Fix: Derive the target origin from the actual merchant origin or use a restrictive whitelist: // Instead of:
~targetOrigin="*"
// Use:
~targetOrigin=GlobalVars.hyperSwitchSdkUrlOr iterate over allowed origins if multiple are supported. |
| let scheduleKnownIframeTitleRepair = () => { | ||
| ensureKnownIframeTitles() | ||
| setTimeout(ensureKnownIframeTitles, 1000)->ignore | ||
| setTimeout(ensureKnownIframeTitles, 3000)->ignore | ||
| } |
Type of Change
Description
This PR improves accessibility around embedded payment contexts. It centralizes the frame-title repair logic, removes duplicated frame-title handling, and improves focus delegation at embedded boundaries so keyboard users can move through the payment experience more predictably.
The user impact is clearer frame identification for assistive technology and better handoff when focus moves between merchant content and the embedded payment experience.
This PR is stacked after the live-region PR and should be reviewed after the announcement behavior is in place.
Closes #1651
How did you test it?
Validated as part of the completed accessibility stack. The checks cover the combined flow after all stacked PRs are applied, including embedded-frame behavior exercised during the local accessibility smoke checks.
npm run re:buildon the completed accessibility stack.npm run test:hookson the completed accessibility stack.npm run buildon the completed accessibility stack.Checklist
npm run re:build